求哈弗曼编码

  1 /********************************************************
  2 **         功能:求哈夫曼编码                          **
  3 **         时间:2015年5月10号                         **
  4 ********************************************************/
  5 #include<stdio.h>
  6 #include<stdlib.h>
  7 #include<string.h>
  8 #define MAXLEN 10000
  9 #define MAXVALUE 10000
 10 
 11 //结构体形式的字符包含的信息
 12 struct ChNode
 13 {
 14     int ascii;//存储字符的asci码
 15     char ch;//存储字符
 16     int count;//字符出现的次数
 17 };
 18 
 19 //定义哈夫曼树节点的结构体
 20 typedef struct HTNode
 21 {
 22     int weight;
 23     int parent,lchild,rchild;
 24 }HTNode;
 25 
 26 typedef char * *HuffmanCode;//定义指针类型的数据类型HuffmanCode
 27 typedef struct ChNode ChNode;//定义数据类型ChNode
 28 
 29 void Count_Times(char text[],ChNode freq[]);
 30 void Select(HTNode HT[],int i,int &s1,int &s2);
 31 void HuffmanCoding(HTNode HT[],HuffmanCode &HC,ChNode freq[],char text[]);
 32 
 33 void main()
 34 {
 35     ChNode freq[256];//存储字符出现次数的数组
 36     char text[MAXLEN];//将字符存储到数组中以后反编译时用
 37     HTNode HT[511];
 38     HuffmanCode HC;
 39     
 40     Count_Times(text,freq);
 41     HuffmanCoding(HT,HC,freq,text);
 42 }
 43 void Count_Times(char text[],ChNode freq[])
 44 {
 45     FILE *fp;//文件指针
 46     char chtmp;//临时存储从文件中读取的字符
 47     
 48     //跟freq数组赋初值
 49     for(int i=0;i<256;i++)
 50     {
 51         freq[i].ascii=i;
 52         freq[i].ch=(char)i;//强制转换为ascii码对应的字符型
 53         freq[i].count=0;
 54     }
 55     
 56     i=0;
 57     fp=fopen("a.txt","r");//以读的方式打开文件
 58     
 59     //统计文件里的字符的出现次数并赋值给text
 60     fscanf(fp,"%c",&chtmp);
 61     while(!feof(fp))
 62     {
 63         freq[chtmp].count++;
 64         fscanf(fp,"%c",&chtmp);
 65         text[i++]=chtmp;
 66         
 67     }
 68     fclose(fp);
 69     
 70     //以写方式打开文件并将统计结果输出到文件中
 71     fp=fopen("freq.txt","w");
 72     for(i=0;i<256;i++)
 73         fprintf(fp,"%d   %c   %d\n",freq[i].ascii,freq[i].ch,freq[i].count);
 74     fclose(fp);
 75     
 76 }
 77 
 78 //选出两个权值最小的结点
 79 void Select(HTNode HT[],int i,int &s1,int &s2)
 80 {
 81     int m1,m2;//用来存储最小的两个权值
 82     
 83     m1 = m2 = MAXVALUE;
 84     s1 = s2 = -1;//用来存储最小权值的字符的序号
 85     
 86     for(int j = 0;j <= i;j ++)
 87     {
 88         //若一个字符的权值小于m1且parent为空(没有已经用过)
 89         if(HT[j].weight > 0 && HT[j].weight < m1 && HT[j].parent == -1)//s1存储的是字符中权值最小的序号
 90         {
 91             //权值比s1小,将s1赋值给s2再将字符序号给s1
 92             m2 = m1;
 93             s2 = s1;
 94             m1 = HT[j].weight;
 95             s1 = j;
 96         }
 97         else if(HT[j].weight > 0 && HT[j].weight < m2 && HT[j].parent == -1)//s2存储的是字符中权值第二小的序号
 98         {
 99             m2 = HT[j].weight;
100             s2 = j;
101 
102         }
103     }
104     
105     
106 }
107 
108 void HuffmanCoding(HTNode HT[],HuffmanCode &HC,ChNode freq[],char text[])
109 {
110     //前256个单位有可能出现的字符将权值赋初值
111     for(int i = 0;i < 256;i ++)
112     {
113         HT[i].weight = freq[i].count;
114         HT[i].parent = -1;
115         HT[i].lchild = -1;
116         HT[i].rchild = -1;
117     }
118     //后面255的赋初值
119     for(i = 256;i < 511;i ++)
120     {
121         HT[i].weight = 0;
122         HT[i].parent = -1;
123         HT[i].lchild = -1;
124         HT[i].rchild = -1;
125     }
126 
127     int s1,s2;
128 
129     //构造哈夫曼树的开始,构造parent节点
130     for(i = 256;i < 511;i++)
131     {
132         Select(HT,i - 1,s1,s2);
133         if(s1 != -1 && s2 != -1)
134         {
135             HT[i].weight = HT[s1].weight + HT[s2].weight;
136             HT[s1].parent = i;
137             HT[s2].parent = i;
138             HT[i].lchild = s1;
139             HT[i].rchild = s2;
140         }
141         else
142         {
143             HT[i - 1].parent = -1;
144             break;
145         }
146     }
147 
148     //HuffmanTree.txt文件用来存放各个字符的权值、父母、孩子等信息
149     FILE *fp;
150     fp = fopen("HuffmanTree.txt","w");
151     for(i = 0;i < 511;i ++)
152         fprintf(fp,"(%d)    %d    %d    %d    %d\n",i,HT[i].weight,HT[i].parent,HT[i].lchild,HT[i].rchild);
153     fclose(fp);
154 
155     //HC相当于一个存放指针类型的数组,每一个元素相对应于一个字符编码数组的首地址
156     HC = (HuffmanCode)malloc(256 * sizeof(char *));
157     char cd[256];
158     cd[255] = '\0';
159     int c,f;
160     int start;
161     for(i =0 ;i < 256;i ++)
162     {
163         if(HT[i].parent != -1)
164         {
165             start = 255;
166             //记录每个字符的编码,是0还是1
167             for(c = i;f = HT[c].parent,f != -1;c = f,f = HT[f].parent)
168             {
169                 if(HT[f].lchild == c)
170                     cd[--start] = '0';
171                 else
172                     cd[--start] = '1';
173             }
174             HC[i] = (char *)malloc((256 - start) * sizeof(char));
175             strcpy(HC[i],&cd[start]);
176         }
177         else
178         {
179             HC[i] = NULL;
180         }
181     }
182 
183     //HuffmanCode.txt文件中记录字符出现的次数及其哈弗曼编码
184     fp = fopen("HuffmanCode.txt","w");
185     fprintf(fp,"ASCII值\t字符\t出现次数\t编码 \n");
186     for(i = 0;i < 256;i ++)
187         if(HC[i] != NULL)
188             fprintf(fp,"%d\t%c\t%d\t%s\n",i,i,freq[i]);
189         fclose(fp);
190 
191         //以对应的哈弗曼编码形式输出到文件中去
192         fp = fopen("translate.txt","w");
193         char ch;
194         i =0;
195         while(text[i] != '\0')
196         {
197             ch = text[i ++];
198             fprintf(fp,"%s",HC[ch]);
199         }
200         fclose(fp);
201 
202 }

 

posted @ 2015-05-13 15:55  banshaohuan  阅读(219)  评论(0编辑  收藏  举报