【树】哈夫曼树(一)
题目
假设用于通信的电文仅由8个字母组成,字母在电文中出现的频率分别为7、19、2、6、32、3、21、10。试为这8个字母设计哈夫曼编码。如果用二进制数表示这8个字母的编码方案.(请按照左子树根节点的权小于等于右子树根节点的权的次序构造
Input
第一行为字母的个数n;
第二行至第n+1行分别为各个字母在电文中出现的频率。
Output
按照中序遍历输出各个编码
Sample Input
8
7
19
2
6
32
3
21
10
Sample Output
19:00
21:01
2:10000
3:10001
6:1001
7:1010
10:1011
32:11
解析
啊不开SPJ就很烦的
烦又能怎么样呢,我又不会写SPJ
哈夫曼树,是一个最优叶子节点划分问题,常被用于压缩
不得不说这个算法是真的冷门,全洛谷只有一道荷马史诗是哈夫曼题
code:
#include<cstdio>
#include<string>
#include<cstring>
#include<algorithm>
using namespace std;
int n,x[10010],r,j;
struct tree{
int s,l,r;}a[100010];
char q[100010];
inline void dfs(int x,int dep)
{
if((!a[x].l)&&(!a[x].r))
{
printf("%d:",a[x].s);
for(register int i=1;i<dep;++i)putchar(q[i]);
putchar('\n');
return;
}
if(a[x].l)q[dep]='0',dfs(a[x].l,dep+1);
if(a[x].r)q[dep]='1',dfs(a[x].r,dep+1);
}
inline bool cmp(int x,int y){
return a[x].s>a[y].s;}
int main()
{
scanf("%d",&n);
for(int i=1;i<=n;++i)scanf("%d",&a[i].s),x[i]=i;
sort(x+1,x+n+1,cmp);
for(int i=n;i>1;--i)
{
r=(n<<1)-i+1;
a[r].s=a[x[i]].s+a[x[i-1]].s,a[r].l=x[i],a[r].r=x[i-1];
for(j=i-1;j&&a[r].s>a[x[j]].s;--j)x[j+1]=x[j];
x[j+1]=r;
}
dfs((n<<1)-1,1);
return 0;
}