哈夫曼编码

来源:互联网 发布:新零售软件 编辑:程序博客网 时间:2024/06/08 07:01
/*由于哈夫曼树中没有度为1的结点(这类树又称严格的(或正则的)二叉树),则一棵有n个叶子结点的哈夫曼树共有2n-1个结点,可以存储在大小为2n-1的一维数组中。在哈夫曼树中,为求编码需从叶子结点出发走一条从叶子到根的路径,而为译码需从根出发走一条从根到叶子的路径。则对每个结点而言,即需知双亲的信息,又需知孩子结点的信息,由此,存储结构定义如下:*/#include<stdio.h>#include<stdlib.h>#include<string.h>typedef struct{unsigned int weight;unsigned int parent,lchild,rchild;}HTNode,*HuffmanTree;typedef char *HuffmanCode;int m,s1,s2;void Select(HuffmanTree Ht,int n){int i,j;for(i=1;i<=n;i++){if(!Ht[i].parent){s1=i;break;}  for(j=i+1;j<=n;j++){  if(!Ht[j].parent){  s2=j;  break;} }}for(i=1;i<=n;i++){if(Ht[s1].weight>Ht[i].weight&&!Ht[i].parent&&s2!=i){s1=i;}}for(j=1;j<=n;j++){if(Ht[s2].weight>Ht[j].weight&&!Ht[j].parent&&s1!=j){s2=j;}}}void HuffmanCoding(HuffmanTree &Ht,HuffmanCode Hc[],int *w,int n){//w存放n个字符的权值(均>0),构造哈夫曼树Ht,并求出n个字符的哈夫曼编码Hcchar *cd;int i,p,cdlen;if(n<=0) return;m=2*n-1;Ht=(HuffmanTree)malloc((m+1)*sizeof(HTNode));  //0号单元未用for(i=1;i<=n;i++){Ht[i].weight=w[i-1];Ht[i].parent=0;Ht[i].lchild=0;Ht[i].rchild=0;} for(i=n+1;i<=m;i++){Ht[i].weight=0;Ht[i].parent=0;Ht[i].lchild=0;Ht[i].rchild=0;}for(i=n+1;i<=m;i++){//建哈夫曼树,在Ht[1...i-1]选择parent为0且weight最小的两个结点,其序号分别为s1,s2Select(Ht,i-1);Ht[s1].parent=i; Ht[s2].parent=i;Ht[i].lchild=s1; Ht[i].rchild=s2;Ht[i].weight=Ht[s1].weight+Ht[s2].weight; }//从叶子到根逆序求每个字符的哈夫曼编码cd=(char *)malloc(n*sizeof(char));p=m;      //编码结束符位置cdlen=0;for(i=1;i<=m;i++)Ht[i].weight=0;while(p){if(Ht[p].weight==0){  //向左 Ht[p].weight=1;if(Ht[p].lchild!=0){p=Ht[p].lchild;cd[cdlen++]='0';}else if(Ht[p].rchild==0) {Hc[p]=(char *)malloc((cdlen+1)*sizeof(char));cd[cdlen]='\0';strcpy(Hc[p],cd);}}else if(Ht[p].weight==1){  //向右Ht[p].weight=2; if(Ht[p].rchild!=0){ p=Ht[p].rchild; cd[cdlen++]='1'; }}else{Ht[p].weight=0;p=Ht[p].parent;--cdlen;}}}int main(){HuffmanTree Ht;HuffmanCode *Hc;int *w,n,i;printf("输入节点数:");scanf("%d",&n);getchar();Hc=(HuffmanCode *)malloc(n*sizeof(HuffmanCode));w=(int *)malloc(n*sizeof(int));printf("输入%d个节点的权值:\n",n);for(i=0;i<n;i++){scanf("%d",&w[i]);} getchar();HuffmanCoding(Ht,Hc,w,n);printf("\n各节点的哈夫曼编码:\n");for(i=1;i<=n;i++){printf("%2d(%4d):%s\n",i,w[i-1],Hc[i]);} return 0;}