初始森林中有n颗只有根结点的树,要合成哈夫曼树必要进行n-1次合并,n-1次合并也就产生了n-1个新的结点,这些新结点的度是2,所以哈夫曼树的总结点数是2n-1,哈夫曼树没有度为1的分支结点(严格的或正则的二叉树)。编码:从叶子结点出发走到根;译码:从根结点走到叶子结点。
例子:
输入文件内容:
4
a 7
b 5
c 2
d 4
8
a 9
b 3
c 7
d 6
e 10
f 2
g 1
h 5
两者对应的最优二叉树:
#include <iostream> #include<cstdio> using namespace std; const int maxn=50,INF=0x3f3f3f3f; typedef struct { char date; int w,parent,lch,rch,flag; //flag=-1:没有选,falg=1已经选过了 }huffnode; typedef struct{ char str[maxn]; int start; }huffcode; huffnode htree[2*maxn]; huffcode hcd[maxn]; int select(int a){ int k=INF,i,q; //令k等于一个极大值. for(i=0;i<=a;i++){ if(htree[i].w<k&&htree[i].flag==-1){ k=htree[i].w; q=i; } } htree[q].flag=1; return q; } void creat_hufftree(int n){ int i,l,r; for(i=0;i<2*n-1;i++)htree[i].parent=htree[i].lch=htree[i].rch=htree[i].flag=-1; for(i=n;i<2*n-1;i++){ l=select(i-1); r=select(i-1); htree[l].parent=htree[r].parent=i; // 树的深度越小,下标越大。 htree[i].lch=l; htree[i].rch=r; htree[i].w=htree[l].w+htree[r].w; } } void creat_huffcode(int n){ //由叶子结点走到根结点,进行编码 int i,f,c; huffcode d; for(i=0;i<n;i++){ d.start=n+1; c=i; f=htree[i].parent; while(f!=-1){ if(htree[f].lch==c)d.str[--d.start]='0'; else d.str[--d.start]='1'; //cout<<d.str[d.start]<<endl; c=f; f=htree[f].parent; } //d.str[d.start-1]=0; hcd[i]=d; } } void disp_huffcode(int n){ int i,k; cout<<"哈夫曼编码:\n"; for(i=0;i<n;i++){ cout<<htree[i].date<<": "; //<<hcd[i].str<<endl; for(k=hcd[i].start;k<=n;k++){ printf("%c",hcd[i].str[k]); } cout<<endl; } } int main(int argc, char *argv[]) { freopen("cin.txt","r",stdin); int n,i,t=2; while(t--){ cin>>n; for(i=0;i<n;i++){ getchar(); scanf("%c%d",&htree[i].date,&htree[i].w); } creat_hufftree(n); creat_huffcode(n); disp_huffcode(n); } return 0; }输出:
哈夫曼编码:
a: 0
b: 10
c: 110
d: 111
哈夫曼编码:
a: 00
b: 1100
c: 111
d: 101
e: 01
f: 11011
g: 11010
h: 100