#include<stdio.h> #include<stdlib.h> typedef struct { char content; int weight; int parent,lchild,rchild; }HTNode,*HuffmanTree;//动态分配数组存储赫夫曼树 typedef int **HuffmanCode;//动态分配数组存储赫夫曼编码表 void HuffmanCoding(HuffmanTree &HT,HuffmanCode &HC,char *ch,int *w,int n);//赫夫曼编码 void Select(HuffmanTree HT,int x,int &s1,int &s2);//选择权值最小的两个数 void Intcpy(int *p,int *q);//复制编码 void DecodeHuffman(HuffmanTree HT,int n);//解译赫夫曼编码 void main() { char x,ch[]={'A','B','C','D','E','F','G','H'};//需要编码的字符 int w[]={5,29,7,8,14,23,3,11},n=8;//各字符对应的权值 HuffmanTree HT; HuffmanCode HC; HuffmanCoding(HT,HC,ch,w,n); while(1) { DecodeHuffman(HT,n); printf("是否想继续解码?(Y/N):"); x=getchar(); getchar();//消去回车符,避免被DecodeHuffman中的gets()使用而出错 if(x!='Y'&&x!='y') break; } for (int i=0;i<n+1;i++) free(HC[i]); free(HC); free(HT); } void Select(HuffmanTree HT,int x,int &s1,int &s2) { HTNode p; int i,j=2,k; while(j--) { for(i=1;HT[i].parent;i++); for(k=i,p=HT[i];i<=x;i++) if(HT[i].parent==0&&HT[i].weight<p.weight) { p=HT[i]; k=i; } HT[k].parent=1; if(j==1) s1=k; else s2=k; } } void Intcpy(int *p,int *q) { for(;*p!=-1;p++,q++) *q=*p; *q=-1; } void HuffmanCoding(HuffmanTree &HT,HuffmanCode &HC,char *ch,int *w,int n) { //w存放权值,构造赫夫曼树,并求出n个字符的赫夫曼编码 int *cd,s1,s2,m,i,start,c,f,temp; if(n<=1) return; m=2*n-1; HT=(HuffmanTree)malloc((m+1)*sizeof(HTNode));//不用0号 for(HT,i=1;i<=n;++i,++w,++ch) { HT[i].weight=*w; HT[i].content=*ch; HT[i].parent=HT[i].lchild=HT[i].rchild=0; } for(;i<=m;++i) HT[i].weight=HT[i].parent=HT[i].lchild=HT[i].rchild=0; for(i=n+1;i<=m;++i) { //构造赫夫曼树 //在HT[1...i-1]选择parent为0且weight最小的两个节点,其序号分别为s1和s2 Select(HT,i-1,s1,s2); if(s1>s2) { temp=s1; s1=s2; s2=temp; } 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; } ////-----------从叶子到根逆向求每个字符的赫夫曼编码--------------- HC=(HuffmanCode)malloc((n+1)*sizeof(int *)); cd=(int*)malloc(n*sizeof(int)); cd[n-1]=-1; printf("Huffman编码结果为:\n"); for(i=1;i<=n;++i) { start=n-1; for(c=i,f=HT[i].parent;f!=0;c=f,f=HT[f].parent) if(HT[f].lchild==c) cd[--start]=0; else cd[--start]=1; HC[i]=(int *)malloc((n-start)*sizeof(int)); Intcpy(&cd[start],HC[i]); printf("%c---",HT[i].content); for(;*HC[i]!=-1;HC[i]++) printf("%d",*HC[i]); printf("\n"); } free(cd); } void DecodeHuffman(HuffmanTree HT,int n) {//根据字符'0'或'1'来确定找左右孩子,直至叶子结点 char str[100]; int i,m=2*n-1; HTNode p; printf("请输入你想解译的编码:\n"); gets(str); printf("解码结果为:"); for(i=0,p=HT[m];str[i];i++) { if(str[i]=='0') { p=HT[p.lchild]; if(p.lchild==0&&p.rchild==0) { printf("%c",p.content); p=HT[m]; } } else { p=HT[p.rchild]; if(p.lchild==0&&p.rchild==0) { printf("%c",p.content); p=HT[m]; } } } printf("\n"); }