/*哈夫曼编码示例程序,来自百度百科*/ #include<stdio.h> #include<stdlib.h> #include<malloc.h> #include<string.h> #define N 100 #define M 2*N-1 typedef char * HuffmanCode[2*M]; typedef struct { char weight; int parent; int LChild; int RChild; }HTNode,Huffman[M+1]; typedef struct Node { int weight; /*叶子结点的权值*/ char c; /*叶子结点*/ int num; /*叶子结点的二进制码的长度*/ }WNode,WeightNode[N]; /***产生叶子结点的字符和权值***/ void CreateWeight(char ch[],int *s,WeightNode *CW,int *p) { int i,j,k; int tag; *p=0; for(i=0;ch[i]!='/0';i++) { tag=1; for(j=0;j<i;j++) { if(ch[j]==ch[i]) { tag=0; break; } } if(tag) { (*CW)[++*p].c=ch[i]; (*CW)[*p].weight=1; for(k=i+1;ch[k]!='/0';k++) { if(ch[i]==ch[k]) (*CW)[*p].weight++; } } } *s=i; } /********创建HuffmanTree********/ void CreateHuffmanTree(Huffman *ht,WeightNode w,int n) { int i,j; int s1,s2; for(i=1;i<=n;i++) { (*ht)[i].weight =w[i].weight; (*ht)[i].parent=0; (*ht)[i].LChild=0; (*ht)[i].RChild=0; } for(i=n+1;i<=2*n-1;i++) { (*ht)[i].weight=0; (*ht)[i].parent=0; (*ht)[i].LChild=0; (*ht)[i].parent=0; } for(i=n+1;i<=2*n-1;i++) { for(j=1;j<=i-1;j++) { if(!(*ht)[j].parent) break; } s1=j; /*找到第一个双亲不为零的结点*/ for(;j<=i-1;j++) { if(!(*ht)[j].parent) s1 = (*ht)[s1].weight > (*ht)[j].weight ? j : s1; }/*且权值最小*/ (*ht)[s1].parent=i; (*ht)[i].LChild=s1; for(j=1;j<=i-1;j++) { if(!(*ht)[j].parent) break; } s2=j; /*找到第一个双亲不为零的结点*/ for(;j<=i-1;j++) { if(!(*ht)[j].parent) s2=(*ht)[s2].weight>(*ht)[j].weight?j:s2; } (*ht)[s2].parent=i; (*ht)[i].RChild=s2; (*ht)[i].weight=(*ht)[s1].weight+(*ht)[s2].weight; } } /***********叶子结点的编码***********/ void CrtHuffmanNodeCode(Huffman ht,char ch[],HuffmanCode *h,WeightNode *weight,int m,int n) { int i,c,p,start; char *cd; cd=(char *)malloc(n*sizeof(char)); cd[n-1]='/0'; for(i=1;i<=n;i++) { start=n-1; c=i; p=ht[i].parent; while(p) { start--; if(ht[p].LChild==c) cd[start]='0'; else cd[start]='1'; c=p; p=ht[p].parent; } (*weight)[i].num=n-start; (*h)[i]=(char *)malloc((n-start)*sizeof(char)); p=-1; strcpy((*h)[i],&cd[start]); } system("pause"); } /*********所有字符的编码*********/ void CrtHuffmanCode(char ch[],HuffmanCode h,HuffmanCode *hc,WeightNode weight,int n,int m) { int i,j,k; for(i=0;i<m;i++) { for(k=1;k<=n;k++) /*从(*weight)[k].c中查找与ch相等的下标K*/ { if(ch[i]==weight[k].c) break; } (*hc)[i]=(char *)malloc((weight[k].num+1)*sizeof(char)); for(j=0;j<=weight[k].num;j++) (*hc)[i][j]=h[k][j]; } } /*****解码*****/ void TrsHuffmanTree(Huffman ht,WeightNode w,HuffmanCode hc,int n,int m) { int i=0,j,p; printf("***StringInformation***/n"); while(i<m) { p=2*n-1; for(j=0;hc[i][j]!='/0';j++) { if( hc[i][j] == '0' ) p=ht[p].LChild; else p=ht[p].RChild; } printf("%c",w[p].c); /*打印原信息*/ i++; } } int main() { int i,n,m; /*n为叶子结点的个数*/ char ch[N]; /*ch[N]存放输入的字符串*/ Huffman ht; /*二叉数 */ HuffmanCode h,hc; /* h存放叶子结点的编码,hc 存放所有结点的编码*/ WeightNode weight; /*存放叶子结点的信息*/ printf("/t***HuffmanCoding***/n"); printf("please input information :"); gets(ch); /*输入字符串*/ CreateWeight(ch,&m,&weight,&n); /*产生叶子结点信息,m为字符串ch[]的长度*/ printf("***WeightInformation***/n Node "); /*输出叶子结点的字符与权值*/ for(i=1;i<=n;i++) printf("%c ",weight[i].c); printf("/nWeight "); for(i=1;i<=n;i++) printf("%d ",weight[i].weight); CreateHuffmanTree(&ht,weight,n); /*产生Huffman树*/ printf("/n***HuffamnTreeInformation***/n"); for(i=1;i<=2*n-1;i++) /*打印Huffman树的信息*/ printf("/t%d %d %d %d/n",i,ht[i].weight,ht[i].parent,ht[i].LChild,ht[i].RChild); CrtHuffmanNodeCode(ht,ch,&h,&weight,m,n); /*叶子结点的编码*/ printf(" ***NodeCode***/n"); /*打印叶子结点的编码*/ for(i=1;i<=n;i++) { printf("/t%c:",weight[i].c); printf("%s/n",h[i]); } CrtHuffmanCode(ch,h,&hc,weight,n,m); /*所有字符的编码*/ printf("***StringCode***/n"); /*打印字符串的编码*/ for(i=0;i<m;i++) printf("%s",hc[i]); system("pause"); TrsHuffmanTree(ht,weight,hc,n,m); /*解码*/ system("pause"); return 0; }