#include<stdio.h> #include<stdlib.h> #define leafNumber 20 //默认权值集合大小 #define totalNumber 39 //数结点个数=2*leafNumber-1 typedef struct { char data; //结点的值 int weight; //结点的权 int Parent,lchild,rchild; //双亲、左、右子女结点指针 }HTNode; typedef struct { char elem[totalNumber]; //Huffman树存储数组 int num; //num是外结点数,root是根 }HFTree; //算法 void createHFTree (HTNode HT[],HFTree HElem[],char value[],int fr[],int n){ //输入数据value[n]和相应权值fr[n],构造用三叉链表表示的Huffman树HT for(int i = 0;i<n;i++){ HT[i].data = value[i]; HElem[i].elem[i] = fr[i]; } int i,k,s1,s2; int min1,min2; for(i = 0;i<leafNumber;i++) //所有指针置空 HT[i].Parent = HT[i].lchild = HT[i].rchild = -1; for(i = n;i<2*n-1;i++){ //逐步构造Huffman树 min1 = min2 = 0x7fff; //min1是最小值,min2是次小值 s1 = s2 = 0; //s1是最小值点,s2是次小值点 for(k = 0;k<i;k++) //构造Huffman树的过程 if(HT[k].Parent == -1) //未成为其他树的子树 if(HT[k].weight<min1){ //新的最小值 min2 = min1; s2 = s1; //原来的最小值变成次小值 min1 = HT[k].weight; //记忆新的最小值 s1 = k; }else if(HT[k].weight<min2){ //新的次小值 min2 = HT[k].weight; s2 = k; } HT[s1].Parent=HT[s2].Parent=i; //构造子树 HT[i].lchild=s1; HT[i].rchild=s2; HT[i].weight=HT[s1].weight+HT[s2].weight; } } //建立Huffman编码 void createMessage(HTNode HT[],HFTree HElem[],int n){ HFTree d; int i,c,f; for(i=0;i<n;i++) { d.num=n; c=i; f=HT[i].Parent; while(f!=0) { if(HT[f].lchild==c) d.elem[--d.num]='0'; else d.elem[--d.num]='1'; c=f; f=HT[f].Parent; } HElem[i]=d; } } //输出Huffman编码 void printMessage (HTNode HT[],HFTree HElem[],int n) { printf("输出huffman编码:\n"); for(int i=0;i<n;i++) { printf("%c\n",HT[i].data); for(int k=HElem[i].num;k<n;k++) printf("%c",HElem[i].elem[k]); printf("\n\n"); } } main(){ HTNode HT[2*leafNumber]; HFTree HElem[leafNumber],d; int n,b[n]; //所需要的数据个数 printf("请输入需要编码的元素个数(1->%d):",leafNumber); scanf("%d",&n); if(n>leafNumber||n<1) return 1; char a[n]; for(int i = 0;i<n;i++){ fflush(stdin); printf("\n请输入第%d位的结点值:",i+1); scanf("%c",&a[i]); printf("\n请输入第%d位权值:",i+1); scanf("%d",&b[i]); } createHFTree(HT,HElem,a,b,n); createMessage(HT,HElem,n); printMessage(HT,HElem,n); }