比较难理解的 都打了备注了
1 #include "stdio.h" 2 #include "stdlib.h" 3 #include "string.h" 4 char alphabet[]={‘A‘,‘B‘,‘C‘,‘D‘}; 5 typedef struct 6 { 7 int weight; //权值 8 int parent; //父节点序号 9 int left ; 10 int right; 11 }HuffmanTree; 12 13 typedef char *HuffmanCode; //Huffman编码指针 14 void SelectNode (HuffmanTree *ht,int n,int *bt1,int *bt2) 15 //从n个节点中选择parent节点为0,权重最小的两个节点 16 { 17 int i; 18 HuffmanTree *ht1,*ht2,*t; 19 ht1=ht2=NULL; 20 for(i=1;i<=n;i++) 21 { 22 if(!ht[i].parent) //父节点为空 23 { 24 if(ht1==NULL) 25 { 26 ht1=ht+i; // 27 continue; 28 } 29 if(ht2==NULL) 30 { 31 ht2=ht+i; 32 if(ht1->weight>ht2->weight) 33 { 34 t=ht2; 35 ht2=ht1; 36 ht1=t; //让ht1指向最小节点 ht2指向第二小 37 } 38 continue; 39 } 40 if(ht1 &&ht2) 41 { 42 if(ht[i].weight<=ht1->weight) 43 { 44 ht2=ht1; //如果还有比ht1更小的则把ht1赋给ht2 ,ht1继续等于最小 45 ht1=ht+i; 46 } 47 else if(ht[i].weight<ht2->weight){ 48 ht2=ht+i; //没有比ht1更小的 但有比ht2小的 49 } 50 } 51 } 52 } 53 if(ht1>ht2){ //按数组最初的位置排序 54 *bt2=ht1-ht; 55 *bt1=ht2-ht; 56 } 57 else 58 { 59 *bt1=ht1-ht; 60 *bt2=ht2-ht; 61 } 62 } 63 void CreateTree(HuffmanTree *ht,int n,int *w) 64 { 65 int i,m=2*n-1; //总节点数 66 int bt1,bt2; 67 if(n<=1) 68 return ; 69 for(i=1;i<=n;++i) 70 { 71 ht[i].weight=w[i-1]; 72 ht[i].parent=0; 73 ht[i].left=0; 74 ht[i].right=0; 75 } 76 for(;i<=m;++i) 77 { 78 ht[i].weight=0; 79 ht[i].parent=0; 80 ht[i].left=0; 81 ht[i].right=0; 82 } 83 for(i=n+1;i<=m;++i) 84 { 85 SelectNode(ht,i-1,&bt1,&bt2); 86 ht[bt1].parent=i; 87 ht[bt2].parent=i; 88 ht[i].left=bt1; 89 ht[i].right=bt2; 90 ht[i].weight=ht[bt1].weight+ht[bt2].weight; 91 } 92 } 93 94 95 void HuffmanCoding(HuffmanTree *ht,int n,HuffmanCode *hc) 96 { 97 char *cd; 98 int start,i; 99 int current,parent; 100 cd=(char*)malloc(sizeof(char)*n); 101 cd[n-1]=‘\0‘; 102 for(i=1;i<=n;i++) 103 { 104 start=n-1; 105 current=i; //获得当前节点序号 106 parent=ht[current].parent; //获得当前节点父亲的序号 107 while(parent) //当父节点不为空 108 { 109 if(current==ht[parent].left) //若当前节点是父亲的左节点 110 cd[--start]=‘0‘; //字符最后编码为0 注意这个编码是逆序的 最后其实根节点 111 else 112 cd[--start]=‘1‘; 113 current=parent; //从当前节点向根节点寻找 114 parent=ht[parent].parent; 115 } 116 hc[i-1]=(char*)malloc(sizeof(char)*(n-start)); //分配保存编码的内存 117 strcpy(hc[i-1],&cd[start]); //复制生成的编码 118 } 119 free(cd); 120 } 121 122 void Encode(HuffmanCode *hc,char *alphabet,char *str,char *code) 123 { 124 int len=0,i=0,j; 125 code[0]=‘\0‘; 126 while(str[i]) 127 { 128 j=0; 129 while(alphabet[j]!=str[i]) //搜索字母在编码表的位置 130 j++; 131 strcpy(code+len,hc[j]); //字母在叶节点的编号到根节点的编号全部复制给code 132 len=len+strlen(hc[j]); // 扩大len的长度(也就是节点深度) 133 i++; 134 } 135 code[len]=‘\0‘; 136 } 137 138 void Decode(HuffmanTree *ht,int m,char *code,char *alphabet,char *decode)//解码 139 { 140 int position=0,i,j=0; 141 m=2*m-1; 142 while(code[position]) 143 { 144 for(i=m;ht[i].left &&ht[i].right;position++ ) 145 { 146 if(code[position]==‘0‘) 147 i=ht[i].left; 148 else 149 i=ht[i].right; 150 } 151 decode[j]=alphabet[i-1]; 152 j++; 153 } 154 decode[j]=‘\0‘; 155 } 156 int main() 157 { 158 int i,n=4,m; 159 char test[]="DBDBDABDCDADBDADBDADACDBDBD"; 160 char code[100],code1[100]; 161 162 int w[]={5,7,2,13}; 163 HuffmanTree *ht; 164 HuffmanCode *hc; 165 m=2*n-1; 166 ht=(HuffmanTree *)malloc((m+1)*sizeof(HuffmanTree)); 167 if(!ht) 168 { 169 printf("分配内存失败\n"); 170 exit(0); 171 } 172 CreateTree(ht,n,w); 173 HuffmanCoding(ht,n,hc); 174 for(i=1;i<=n;i++) 175 printf("字母:%c,权重:%d,编码:%s\n",alphabet[i-1],ht[i].weight,hc[i-1]); 176 Encode(hc,alphabet,test,code); 177 printf("\n字符串:\n%s\n转换后:\n%s\n",test,code); 178 Decode(ht,n,code,alphabet,code1); 179 printf("\n编码:\n%s\n转换后:\n%s\n",code,code1); 180 181 return 0; 182 }
时间: 2024-11-04 12:36:34