哈夫曼编译系统

  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 */

 

posted @ 2015-05-10 15:49  SYTM  阅读(554)  评论(0编辑  收藏  举报