1 /* 2 哈夫曼编码C语言实现 3 */ 4 // n个数字,对应n个权值 5 // n作为主输入参数,确定需要编码的数量 6 // 输入n个权值,进行加权求解 7 // 求解最小生成树 8 // 9 // 涉及数据成员: 10 // weight 权值 11 // parent 父节点 12 // 13 #include<stdio.h> 14 #include<stdlib.h> 15 #include<string> 16 #define TREELEN 100 17 #define MAXVALUE 99999 18 struct HuffmanNode{ 19 int weight; 20 int parent; 21 int lchild; 22 int rchild; 23 public: HuffmanNode(int w=0,int p=-1):weight(w),parent(p) 24 {lchild=-1; 25 rchild=-1;} 26 }Nodes[TREELEN]; 27 struct HuffmanResult{ 28 int weight; 29 int *bit; 30 int length; 31 }* huffman; 32 /* 33 函数实现功能:完成哈夫曼树 34 完成哈夫曼编码 35 n 代表需要编码数据的个数 36 huffman表示要存储最终结果的数组,其中Weight存放其权值,maxbit 存放其结果 37 length表示编码长度 38 */ 39 void HuffmanAnswer(int n) 40 { 41 //申请n个保存编码 的空间 42 huffman=(HuffmanResult*)malloc(n*sizeof(HuffmanResult)); 43 int min1=0,min2=0;//每次寻找两个最小值,必须未访问,判断方式就是其父节点不为-1 44 int added=0; 45 int i=0,j=0; 46 int del1=0,del2=0; 47 int bitlen=0; 48 int* maxbit=(int*)malloc(n*sizeof(int)); 49 for(i=0;i<n;i++) 50 { 51 huffman[i].weight=Nodes[i].weight; 52 } 53 while(true) 54 { 55 min2=min1=MAXVALUE; 56 del1=del2=0; 57 for(i=0;i<n+added;i++) 58 { 59 //min1保留最小值,min2保存仅比Min1大的值 60 //del1 记录权值为min1的节点序号,del2记录权值为min2的节点序号 61 if(Nodes[i].parent==-1&&Nodes[i].weight<min2) 62 { 63 if(Nodes[i].weight<min1) 64 { 65 min2=min1; 66 del2=del1; 67 min1=Nodes[i].weight; 68 del1=i; 69 } 70 else{ 71 min2=Nodes[i].weight; 72 del2=i; 73 } 74 } 75 } 76 if(min2==MAXVALUE)break;//处理完毕,跳出循环 77 Nodes[del1].parent=n+added; 78 Nodes[del2].parent=n+added; 79 Nodes[n+added].weight=min1+min2; 80 Nodes[n+added].lchild=del1; 81 Nodes[n+added].rchild=del2; 82 added+=1; 83 } 84 int t=0; 85 for(i=0;i<n;i++) 86 { 87 bitlen=0; 88 j=i; 89 while(Nodes[j].parent!=-1) 90 { 91 t=j; 92 j=Nodes[j].parent; 93 if(Nodes[j].lchild==t) 94 maxbit[bitlen]=0; 95 else maxbit[bitlen]=1; 96 bitlen++; 97 } 98 huffman[i].bit=(int*)malloc(bitlen*sizeof(int)); 99 for(j=0;j<bitlen;j++) 100 huffman[i].bit[bitlen-j-1]=maxbit[j]; 101 huffman[i].length=bitlen; 102 } 103 printf("哈夫曼树及哈夫曼编码成功!\n"); 104 } 105 //index 索引序号 106 //h 深度 107 /* 108 函数功能 : 109 打印空格 110 */ 111 void printSpace(int cnt,FILE* fout) 112 { 113 for(int i=0;i<cnt;i++){ 114 printf(" "); 115 fprintf(fout," "); 116 } 117 } 118 /* 119 函数功能: 120 打印哈夫曼树(凹陷法) 121 */ 122 void printHuffTree(int index,int h,FILE* fout) 123 { 124 if(Nodes[index].lchild==-1&&Nodes[index].rchild==-1) 125 { 126 printSpace(h,fout); 127 fprintf(fout,"%d\n",index); 128 printf("%d\n",index); 129 return; 130 } 131 printSpace(h,fout); 132 printf("%d\n",index); 133 fprintf(fout,"%d\n",index); 134 printHuffTree(Nodes[index].lchild,h+1,fout); 135 printHuffTree(Nodes[index].rchild,h+1,fout); 136 } 137 /* 138 译码功能: 139 从文件中读取编码。 140 手动输入编码,需要知道长度 141 */ 142 void HuffmanDecoding(int n) 143 { 144 int choice,i,len; 145 char codestore[1000]; 146 char code; 147 int tcode; 148 char filename[60]; 149 char savename[60]; 150 151 FILE *fin; 152 FILE *fp; 153 printf("输入译码要保存的文件名(txt或bin文档):") ; 154 scanf("%s",savename); 155 if(!(fin=fopen(savename,"w"))) 156 { 157 printf("保存文档路径打开失败!") ; 158 return; 159 } 160 printf("请选择获取编码的方式:\n"); 161 printf("\t\t1--从文件中读取编码并翻译\n"); 162 printf("\t\t2--手动输入编码并翻译\n"); 163 scanf("%d",&choice); 164 if(choice==1) 165 { 166 printf("输入编码源文件名(txt或bin文档): "); 167 scanf("%s",filename); 168 169 if( !(fp=fopen(filename,"r"))) 170 { 171 printf("源码文档打开失败!") ; 172 return; 173 } 174 tcode=2*n-2; 175 while(!feof(fp)) 176 { 177 code=fgetc(fp); 178 if(code==‘0‘) 179 tcode=Nodes[tcode].lchild; 180 else if(code==‘1‘) 181 tcode=Nodes[tcode].rchild; 182 if(Nodes[tcode].lchild==-1&&Nodes[tcode].rchild==-1) 183 { 184 printf("%d ",tcode);// 185 fprintf(fin,"%4d",tcode); 186 tcode=2*n-2; 187 } 188 } 189 fclose(fp); 190 printf("\n译码成功!\n") ; 191 } 192 else if(choice==2) 193 { 194 printf("输入编码:\n"); 195 scanf("%s",codestore); 196 len=strlen(codestore); 197 i=0; 198 tcode=2*n-2; 199 while(i<len) 200 { 201 if(codestore[i]==‘0‘) 202 tcode=Nodes[tcode].lchild; 203 else if(codestore[i]==‘1‘)tcode=Nodes[tcode].rchild; 204 if(Nodes[tcode].lchild==-1&&Nodes[tcode].rchild==-1) 205 { 206 printf("%d ",tcode);// 207 fprintf(fin,"%4d",tcode); 208 tcode=2*n-2; 209 } 210 i++; 211 } 212 } 213 fclose(fin); 214 printf("\n译码成功!\n") ; 215 } 216 void PrintHuffCode(int n) 217 { 218 //输出所有权值所对应编码 219 int choice,i,j; 220 char savefile[60]; 221 int flag=0; 222 FILE *fin; 223 printf("是否要保存到文件中?\n"); 224 printf("\t\t1: 是\n\t\t2: 不\n"); 225 scanf("%d",&choice); 226 227 if(choice==1) 228 { 229 printf("输入编码要保存到文件名:"); 230 scanf("%s",savefile); 231 if(!(fin=fopen(savefile,"w"))){ 232 printf("保存路径有误!\n"); 233 return; 234 } 235 flag=1; 236 } 237 printf("权值\t编码长度\t编码\n"); 238 if(flag==1)fprintf(fin,"权值\t编码长度\t编码\n"); 239 for(i=0;i<n;i++) 240 { 241 printf("%3d\t%d\t\t",huffman[i].weight,huffman[i].length); 242 if(flag==1) fprintf(fin,"%3d\t%d\t\t",huffman[i].weight,huffman[i].length); 243 for(j=0;j<huffman[i].length;j++) 244 { 245 printf("%d",huffman[i].bit[j]); 246 if(flag==1) fprintf(fin,"%d",huffman[i].bit[j]); 247 } 248 printf("\n"); 249 } 250 if(flag==1) 251 { 252 printf("保存到文件%s成功.\n",savefile); 253 } 254 } 255 void menu() 256 { 257 printf("\t\t\t哈夫曼编译码系统\n"); 258 printf("\t\t1--输入权值并初始化数据\n"); 259 printf("\t\t2--译码\n"); 260 printf("\t\t3--打印哈夫曼树\n"); 261 printf("\t\t4--打印哈夫曼编码\n"); 262 printf("\t\t0--退出\n"); 263 } 264 int main() 265 { 266 267 int n;//参数n,代表输入权值数量 268 int i=0,j=0; 269 FILE *fout; 270 char save[60]; 271 menu(); 272 int ce=-1; 273 while(ce!=0) 274 { 275 printf("输入功能选项: "); 276 scanf("%d",&ce); 277 switch(ce) 278 { 279 case 1: { 280 printf("输入数据数量:"); 281 scanf("%d",&n); 282 //输入编码节点数据 283 printf("输入各权值\n"); 284 for(;i<n;++i) 285 scanf("%d",&Nodes[i].weight); 286 HuffmanAnswer(n);}break; 287 case 2:{ 288 HuffmanDecoding(n); 289 break; 290 } 291 case 3: { 292 printf("输入哈夫曼树保存路径:"); 293 scanf("%s",save); 294 fout=fopen(save,"w"); 295 printHuffTree(2*n-2,0,fout); 296 printf("哈夫曼树打印到文件%s成功!\n",save); 297 break; 298 } 299 case 4:{ 300 PrintHuffCode(n); 301 break; 302 } 303 default: break; 304 } 305 } 306 return 0; 307 } 308 /* 309 输入数据数量:7 310 输入各权值 311 3 7 10 15 20 20 25 312 1 2 3 4 5 6 7 313 权值 编码长度 编码 314 3 4 0110 315 7 4 0111 316 10 3 010 317 15 3 110 318 20 3 111 319 20 2 00 320 25 2 10 321 322 323 输入数据数量:7 324 输入各权值 325 3 7 10 15 20 20 25 326 327 12 328 10 329 5 330 8 331 2 332 7 333 0 334 1 335 11 336 6 337 9 338 3 339 4 340 341 */
时间: 2024-10-13 21:16:57