Huffman编码实验

一、 实验目的

熟练掌握哈夫曼树的建立和哈夫曼编码的算法实现。

二、 实验内容

根据哈夫曼编码的原理,编写一个程序,在用户输入结点权值的基础上求赫夫曼编码,并能把给定的编码进行译码。

三、 实验要求

(1)初始化:从键盘输入一字符串(或读入一文件),统计出现的字符和每个字符出现的频率,将字符出现的频率作为结点的权值,建立哈夫曼树。对各个字符进行哈夫曼编码,最后打印输出字符及每个字符对应的哈夫曼编码。

(2)编码:利用已建好的哈夫曼树对“输入串”进行哈夫曼编码,最后打印输入串对应的哈夫曼编码(写入文件)。

(3)计算压缩比(选作)

(4)译码:利用已建好的哈夫曼树对给定的一串代码进行译码,并打印输出得到的字符串。(选作)

测试数据:对字符串{casbcatbsatbat}进行编码;对电文“1101000”译码。字符集D={   ?},出现频率为w={?}

  1 #include <stdio.h>
  2 #include <string.h>
  3 #include <iostream>
  4 #include <string>
  5 #include <math.h>
  6 #include <algorithm>
  7 #include <vector>
  8 #include <stack>
  9 #include <queue>
 10 #include <set>
 11 #include <map>
 12 #include <sstream>
 13 const int INF=0x3f3f3f3f;
 14 typedef long long LL;
 15 const int mod=1e9+7;
 16 const int maxn=1e4+10;
 17 using namespace std;
 18 
 19 struct node
 20 {
 21     int val;//权值 
 22     int lc;//左孩子 
 23     int rc;//右孩子 
 24     int parent;//双亲 
 25     char c;//节点字符 
 26     int flag;//标志
 27 }Huffman_Tree[26*2];
 28 
 29 int num[26]={0};//每种字符的个数 
 30 char Huffman_code[26][100];//每种字符对应的编码 
 31 char str[maxn];//原字符串 
 32 int cnt;//Huffman树节点个数计数器 
 33 
 34 void Init()//初始化
 35 {
 36     printf("请输入一串字符串(该字符串只能为小写字母):\n");
 37     gets(str);
 38     for(int i=0;str[i];i++)
 39     {
 40         num[str[i]-'a']++;
 41     }
 42     int sum=0;
 43     for(int i=0;i<26;i++)
 44     {
 45         if(num[i])//初始化 
 46         {
 47             sum++;
 48             Huffman_Tree[++cnt].c=i+'a';
 49             Huffman_Tree[cnt].val=num[i];
 50             Huffman_Tree[cnt].lc=0;
 51             Huffman_Tree[cnt].rc=0;
 52             Huffman_Tree[cnt].parent=0;
 53             Huffman_Tree[cnt].flag=0;
 54         }
 55     }
 56     for(int k=0;k<sum-1;k++)//建树 
 57     {
 58         int MIN1=INF;
 59         int MIN2=INF;
 60         int Index1,Index2;
 61         for(int i=1;i<=cnt;i++)
 62         {
 63             if(Huffman_Tree[i].flag==0)
 64             {
 65                 if(Huffman_Tree[i].val<MIN1)
 66                 {
 67                     MIN2=MIN1;
 68                     Index2=Index1;
 69                     MIN1=Huffman_Tree[i].val;
 70                     Index1=i;
 71                 }
 72                 else if(Huffman_Tree[i].val<MIN2)
 73                 {
 74                     MIN2=Huffman_Tree[i].val;
 75                     Index2=i;
 76                 }
 77             }
 78         }
 79         Huffman_Tree[Index1].flag=1;
 80         Huffman_Tree[Index2].flag=1;
 81         int t=MIN1+MIN2;
 82         Huffman_Tree[++cnt].val=t;
 83         Huffman_Tree[cnt].c='*';
 84         Huffman_Tree[cnt].lc=Index1;
 85         Huffman_Tree[cnt].rc=Index2;
 86         Huffman_Tree[cnt].parent=0;
 87         Huffman_Tree[cnt].flag=0;
 88         Huffman_Tree[Index1].parent=cnt;
 89         Huffman_Tree[Index2].parent=cnt;
 90     }
 91     for(int i=0;i<26;i++)//求Huffman编码 
 92     {
 93         if(num[i])
 94         {
 95             char tem[100];
 96             int len=0;
 97             int p;
 98             for(int j=1;j<=cnt;j++)
 99             {
100                 if(Huffman_Tree[j].c==i+'a')
101                 {
102                     p=j;
103                     break;
104                 }
105             }
106             while(Huffman_Tree[p].parent)
107             {
108                 if(Huffman_Tree[Huffman_Tree[p].parent].lc==p)
109                     tem[len++]='0';
110                 else
111                     tem[len++]='1';
112                 p=Huffman_Tree[p].parent;
113             }
114             tem[len]='\0';
115             int ccnt=0;
116             for(int j=len-1;j>=0;j--)
117             {
118                 Huffman_code[i][ccnt++]=tem[j];
119             }
120             Huffman_code[i][ccnt]='\0';            
121 //            for(int j=0;j<len/2;j++)
122 //            {
123 //                char t=tem[j];
124 //                tem[j]=tem[len-1-j];
125 //                tem[len-1-j]=t;
126 //            }
127 //            NUM[i]=tem;
128 //            puts(NUM[i]);
129         }
130     }
131     printf("每个字母对应的Huffman编码为:\n"); 
132     for(int i=0;i<26;i++)
133     {
134         if(num[i])
135         {
136             printf("%c:",i+'a');
137             puts(Huffman_code[i]);
138         }
139     }
140 }
141 
142 void Print_out()//编码
143 {    
144     printf("输入串对应的哈夫曼编码为:\n");
145     for(int i=0;str[i];i++)//根据字符匹配编码 
146     {
147         printf("%s",Huffman_code[str[i]-'a']);    
148     }
149     printf("\n");
150 }
151 
152 void Solve1()//计算压缩比
153 {
154     int sum=0;//字符种类个数 
155     for(int i=0;i<26;i++)
156     {
157         if(num[i])
158             sum++;
159     }
160     double a=0;//平均码长 
161     int b;//等长码 
162     if(sum==1)
163         b=1; 
164     else b=(int)log2(sum-1)+1;
165     double ans;
166     for(int i=0;i<26;i++)
167     {
168         if(num[i])
169         {
170             a+=(num[i]*1.0/strlen(str))*strlen(Huffman_code[i]);
171         }
172     }
173     ans=a/b*1.0;
174     printf("该字符串压缩比为:\n");
175     printf("%.2lf%%\n",ans*100);
176 }
177 
178 void Solve2()//译码
179 {
180     char tem[maxn];
181 //    char ans[maxn];
182 //    int len=0;
183     printf("请输入要进行译码的0-1串:\n");
184     scanf("%s",tem);
185 //    int i,j,k;
186 //    for(i=0;tem[i];i++)
187 //    {
188 //        for(k=0;k<26;k++)
189 //        {
190 //            if(num[k])
191 //            {
192 //                for(j=0;j<strlen(Huffman_code[k]);)
193 //                {
194 //                    if(tem[i]==Huffman_code[k][j])
195 //                    {
196 //                        i++;
197 //                        j++;
198 //                    }
199 //                    else
200 //                    {
201 //                        i-=j;
202 //                        j=0;
203 //                        break;
204 //                    }
205 //                }
206 //                if(j==strlen(Huffman_code[k]))
207 //                {
208 //                    i--;
209 //                    ans[len++]=k+'a';
210 //                    break;
211 //                }
212 //            }
213 //        }
214 //    }
215 //    ans[len]='\0';
216 //    printf("该0-1串译文为:\n");
217 //    puts(ans);
218     int rt;//Huffman树根 
219     for(int i=1;i<=cnt;i++)//找到根 
220     {
221         if(Huffman_Tree[i].parent==0)
222         {
223             rt=i;
224             break;
225         }
226     }
227     for(int i=0;tem[i];i++)//类似于字典树匹配 
228     {
229         for(int p=rt;;i++)
230         {
231             if(tem[i]=='0')
232                 p=Huffman_Tree[p].lc;
233             else
234                 p=Huffman_Tree[p].rc;
235             if(Huffman_Tree[p].c!='*')
236             {
237                 printf("%c",Huffman_Tree[p].c);
238                 break;
239             }
240         }
241     }
242     printf("\n");
243 }
244 
245 int main()
246 {
247     Init();
248     printf("--------------------------------\n"); 
249     Print_out();
250     printf("--------------------------------\n");
251     Solve1();
252     printf("--------------------------------\n");
253     Solve2();
254     printf("--------------------------------\n");
255     return 0;
256 } 

猜你喜欢

转载自www.cnblogs.com/jiamian/p/11696366.html
今日推荐