[DataStructure]HuffMan编码与译码

HuffMan编码与译码

Iris.Catch-22.S`

一、题目描述:

设字符集为26个英文字母,给出其出现频度。(空格、a~z大小写不敏感)

先建哈夫曼树,再利用此树对报文“This program is my favorite”进行编码和译码。

 

二、解题报告

1.建立结构

 1 /*HuffManTree Node*/
 2 struct HuffManTNode
 3 {
 4     int Weight;//权重
 5     int Par;
 6     int LChild;
 7     int RChild;
 8 };
 9 
10 /*HuffMan Code*/
11 struct HuffCode
12 {
13     int Codes[MAXLEN]; //HuffMan 编码
14     int Length; //HuffMan 编码长度
15     char Data;//字母空格
16 };
1718 
19 /*字母出现的频数*/
20 int a[MAXNUM] = 
21 {186,64,13,22,32,103,21,15,47,57,1,5,32,20,57,63,15,1,48,51,80,23,8,18,1,16,1};
22 
23 char Letter['z'];//存储字符位置
24 
25 
26 /*Declare HuffManTree Node&&HuffMan Code*/
27 
28 HuffManTNode *HuffManTN = new HuffManTNode[2*MAXNUM-1];
29 HuffCode *HuffManTC = new HuffCode[MAXNUM];
30 
31 
32 /*初始化String*/
33 string Words="This program is my favorite";

2.主程序框架

 1 int main()
 2 {
 3 CopyRight();
 4 
 5 /*HuffMan Tree构建及HuffMan Code生成*/
 6 Huffman(a,MAXNUM,HuffManTN,HuffManTC);
 7 
 8 /*HuffManCode输出*/
 9 OutputHuffManCode();
10 
11 /*译码解码任务分配过程*/
12     TaskMgr();
13     
14 return 0;
15 }

3.HuffManTree建立及HuffManCode形成

 1 void Huffman(int Weight[], int n, HuffManTNode HuffManTN[], HuffCode HuffManTC[])      //出现频次/字符个数/HMTree结点/HM编码
 2 {
 3    /*Flag字符标识*/
 4     char ch;
 5     char Flag[n];
 6     Flag[0]=' ';
 7     for (int i=1,ch='a';i<=n;++i,++ch)
 8         Flag[i]=ch;
 9 
10    /* Create Huffman Node ,Step 1*/
11 for(int i=0; i<2*n-1;++i)      
12 {
13         if (i<n)
14           HuffManTN[i].Weight=Weight[i];
15         else
16           HuffManTN[i].Weight=0;
17         HuffManTN[i].Par=0;
18         HuffManTN[i].LChild=HuffManTN[i].RChild=-1;
19     }
20 
21     /* Create Huffman Node ,Step 2*/
22     int l,r; //l,r分别代表新建的节点所用到的两个结点
23 int min1,min2; //存储每次选择的最小的两个Weight
24 for(int i=0;i<n-1;++i)
25 {
26         min1=min2=Maxlongint;
27         l=r=0;
28         for(int j=0;j<n+i;j++)
29         {
30             if(HuffManTN[j].Weight < min1 && HuffManTN[j].Par==0)
31             {
32                 min2= min1;
33                 min1= HuffManTN[j].Weight;
34                 r=l;
35                 l=j;
36             }
37             else if(HuffManTN[j].Weight < min2 && HuffManTN[j].Par==0)
38             {
39                 min2=HuffManTN[j].Weight;
40                 r=j;
41             }
42         }
43 
44         ///Create a new HuffMan Node
45         HuffManTN[n+i].Weight=min1+min2;
46         HuffManTN[l].Par=n+i;
47         HuffManTN[r].Par=n+i;
48         HuffManTN[n+i].LChild=l;
49         HuffManTN[n+i].RChild=r;
50     }
51 
52     int Temp[MAXLEN]; ///在此逆序存储Huffman编码
53     int j;
54     for(int i=0;i<n;++i)
55     {
56         j=0;
57         int Child=i;
58         int Par=HuffManTN[i].Par;
59         while(HuffManTN[Child].Par != 0) ///逆序存储
60         {
61             if(HuffManTN[Par].LChild == Child) Temp[j++] = 0;
62             else Temp[j++] = 1;
63             Child=Par;
64             Par=HuffManTN[Par].Par;
65         }
66 
67         ///正序存储到HuffCode中
68         int k=0;
69         HuffManTC[i].Length=j;
70         HuffManTC[i].Data=Flag[i];
71         while(j)
72           HuffManTC[i].Codes[k++]=Temp[--j];
73        ///仔细想想++ --的意义……
74     }
75 }

4.HuffMan编码的输出

 1 void OutputHuffManCode()
 2 {
 3 char ch1,ch2;
 4 /*由于ASCII码特殊性,特殊输出空格……*/
 5 int i=0;
 6 ch1=’ ‘;
 7 Letter[ch1]=i;
 8     cout<<"Letter:"<<HuffManTC[i].Data<<",Code=";
 9     for(int j=0;j<HuffManTC[i].Length;++j)
10        cout<<HuffManTC[i].Codes[j];
11 cout<<endl;
12 /*输出a~z*/
13     for(int i=1,ch1='a',ch2='A'; i<MAXNUM; ++i,++ch1,++ch2)
14     {
15         Letter[ch1]=Letter[ch2]=i;///此处为下文译码便捷性做出
16                                  ///即找到i对应a-z及A-Z
17         cout<<"Letter:"<<HuffManTC[i].Data<<",Code=";
18         for(int j=0;j<HuffManTC[i].Length;++j)
19           cout<<HuffManTC[i].Codes[j];
20         cout<<endl;
21     }
22 }

5.解码译码任务模块

 1 void TaskMgr()
 2 {
 3    cout<<"请问您是要编码还是解码?编码输入A,解码输入B"<<endl;
 4    string Flag;//如果用Char标识的话字符串在getline读入时会丢失首字母
 5    getline(cin,Flag);
 6    while (Flag!="A" && Flag!="B")
 7    {
 8        cout<<"输入有误,请重新输入!"<<endl;
 9        getline(cin,Flag);
10    }
11    if (Flag=="A")
12    {
13        Making_InputData();
14        Making_OutputData();
15    }
16    if (Flag=="B")
17    {
18        De_InputData();
19     }
20 } 

6.译码模块一读入模块

 1 ///因为有空格所以不能cin
 2 void Making_InputData()
 3 {
 4     cout<<"请输入要编码的语句"<<endl;
 5     char flag;
 6     cin>>flag;
 7     getline(cin,Words);
 8     Words=flag+Words;
 9     cout<<"您输入的是:"<<Words<<endl;
10 }

7.译码模块二--输出模块(内嵌译码过程)

 1 void Making_OutputData()
 2 {
 3     for (int i=0;i<Words.size();++i)///逐个字母输出对应编码,可省略
 4     {
 5         cout<<Words[i]<<"-----------------";
 6         for(int j=0;j<HuffManTC[Letter[Words[i]]].Length;++j)
 7           cout<<HuffManTC[Letter[Words[i]]].Codes[j];
 8         cout<<endl;
 9     }
10     for (int i=0;i<Words.size();++i)///完整编码
11     {
12         for(int j=0;j<HuffManTC[Letter[Words[i]]].Length;++j)
13           cout<<HuffManTC[Letter[Words[i]]].Codes[j];
14     }
15     cout<<endl;
16 }

8.解码模块一-读入模块

1 void De_InputData()
2 {
3     cout<<"请输入要译码的语句"<<endl;
4     cin>>Words;
5     cout<<"您输入的是:"<<Words<<endl;
6     DeCoding(Words); cout<<endl;
7 }

9.解码模块二-解码过程(内嵌输出)

 1 void DeCoding(string Words)
 2 {
 3    int Flag,Tmp;
 4    for (int i=0;i<Words.size();)
 5    {   Tmp=i;       
 6        for (int j=0;j<MAXNUM;++j)       
 7 {
 8           Flag=1;
 9           for(int k=0;k<HuffManTC[j].Length;++k)
10              {
11                  if (HuffManTC[j].Codes[k]==Words[Tmp]) ++Tmp;
12               else
13               {
14                   Flag=-1;
15                   Tmp=i;
16                   break;
17               }
18              }
19           if (Flag==1)
20           {  i=Tmp;
21             if (j==0) cout<<' ';
22             else cout<<char('a'+j-1);
23             break;
24           } 
25           else if (Flag==-1 && j==MAXNUM-1) return;//此情形说明输入有误
26        }                                //遍历一遍后发现之后无对应字母
27    }
28 }

10.完整代码

  1 /*
  2    By
  3      Iris.Catch-22.S、`
  4      Dept. of Mathematics,
  5      School of Science,
  6      HIT
  7    December,2015
  8 */
  9 #include<iostream>
 10 #include<cstring>
 11 using namespace std;
 12 void CopyRight()
 13 {
 14    cout<<"------------By ICS,HIT,2015/12-------------"<<endl;
 15    cout<<"-------------HuffmanTree Code--------------"<<endl;
 16    cout<<"-----------------Ver 1.0.0-----------------"<<endl;
 17 }
 18 
 19 /*#define一些定值*/
 20 #define MAXNUM 27
 21 #define MAXLEN 100 //HuffMan编码最大长度
 22 #define Maxlongint 2147483647
 23 
 24 /*字母出现的频数,可简单修改程序达到读入频数的目的*/
 25 int a[MAXNUM] 
 26 ={186,64,13,22,32,103,21,15,47,57,1,5,32,20,57,63,15,1,48,51,80,23,8,18,1,16,1};
 27 
 28 /*HuffManTree Node*/
 29 struct HuffManTNode
 30 {
 31     int Weight;//权重
 32     int Par;
 33     int LChild;
 34     int RChild;
 35 };
 36 
 37 /*HuffMan Code*/
 38 struct HuffCode
 39 {
 40     char Codes[MAXLEN]; //HuffMan 编码
 41     int Length; //HuffMan 编码长度
 42     char Data;
 43 };
 44 char Letter['z'];
 45 /*Declare HuffManTree Node&&HuffMan Code*/
 46 HuffManTNode *HuffManTN = new HuffManTNode[2*MAXNUM-1];
 47 HuffCode *HuffManTC = new HuffCode[MAXNUM];
 48 /*HuffMan*/
 49 void Huffman(int Weight[], int n, HuffManTNode HuffManTN[], HuffCode HuffManTC[])      //出现频次/字符个数/HMTree结点/HM编码
 50 {
 51    /*Flag字符标识*/
 52     char ch;
 53     char Flag[n];
 54     Flag[0]=' ';
 55     for (int i=1,ch='a';i<=n;++i,++ch)
 56         Flag[i]=ch;
 57    /* Create Huffman Node ,Step 1*/
 58    for(int i=0; i<2*n-1;++i)
 59    {
 60         if (i<n)
 61           HuffManTN[i].Weight=Weight[i];
 62         else
 63           HuffManTN[i].Weight=0;
 64         HuffManTN[i].Par=0;
 65         HuffManTN[i].LChild=HuffManTN[i].RChild=-1;
 66     }
 67     /* Create Huffman Node ,Step 2*/
 68     int l,r; //l,r分别代表新建的节点所用到的两个结点
 69     int min1,min2; //存储每次选择的最小的两个Weight
 70     for(int i=0;i<n-1;++i)
 71     {
 72         min1=min2=Maxlongint;
 73         l=r=0;
 74         for(int j=0;j<n+i;j++)
 75         {
 76             if(HuffManTN[j].Weight < min1 && HuffManTN[j].Par==0)
 77             {
 78                 min2= min1;
 79                 min1= HuffManTN[j].Weight;
 80                 r=l;
 81                 l=j;
 82             }
 83             else if(HuffManTN[j].Weight < min2 && HuffManTN[j].Par==0)
 84             {
 85                 min2=HuffManTN[j].Weight;
 86                 r=j;
 87             }
 88         }
 89         ///Create a new Huffman Node
 90         HuffManTN[n+i].Weight=min1+min2;
 91         HuffManTN[l].Par=n+i;
 92         HuffManTN[r].Par=n+i;
 93         HuffManTN[n+i].LChild=l;
 94         HuffManTN[n+i].RChild=r;
 95     }
 96     int Temp[MAXLEN]; ///逆序存储HuffMan编码
 97     int j;
 98     for(int i=0;i<n;++i)
 99     {
100         j=0;
101         int Child=i;
102         int Par=HuffManTN[i].Par;
103         while(HuffManTN[Child].Par != 0) ///逆序存储
104         {
105             if(HuffManTN[Par].LChild == Child) Temp[j++] = '0';
106             else Temp[j++] = '1';
107             Child=Par;
108             Par=HuffManTN[Par].Par;
109         }
110         ///正序存储到HuffManTC中
111         int k=0;
112         HuffManTC[i].Length=j;
113         HuffManTC[i].Data=Flag[i];
114         while(j)
115           HuffManTC[i].Codes[k++]=Temp[--j];
116     }
117 }
118 
119 void OutputHuffManCode()
120 {
121 
122     char ch1,ch2;
123     int i=0;
124     cout<<"Letter:"<<HuffManTC[i].Data<<",Code=";
125     for(int j=0;j<HuffManTC[i].Length;++j)
126        cout<<HuffManTC[i].Codes[j];
127     cout<<endl;
128     for(int i=1,ch1='a',ch2='A'; i<MAXNUM; ++i,++ch1,++ch2)
129     {
130         cout<<"Letter:"<<HuffManTC[i].Data<<",Code=";
131         Letter[ch1]=Letter[ch2]=i;
132         for(int j=0;j<HuffManTC[i].Length;++j)
133           cout<<HuffManTC[i].Codes[j];
134         cout<<endl;
135     }
136 }
137 /*-----------------------编码解码-----------------------*/
138 string Words="This program is my favorite";
139 ///1101000101100011111100010001010011000010010101011001011101100011111110010100011111110011101011000001001001001101101010
140 /*编码*/
141 void Making_InputData()
142 {
143     cout<<"请输入要编码的语句"<<endl;
144     getline(cin,Words);
145     cout<<"您输入的是:"<<Words<<endl;
146 }
147 void Making_OutputData()
148 {
149     for (int i=0;i<Words.size();++i)
150     {
151         cout<<Words[i]<<"-----------------";
152         for(int j=0;j<HuffManTC[Letter[Words[i]]].Length;++j)
153           cout<<HuffManTC[Letter[Words[i]]].Codes[j];
154         cout<<endl;
155     }
156     for (int i=0;i<Words.size();++i)
157     {
158         for(int j=0;j<HuffManTC[Letter[Words[i]]].Length;++j)
159           cout<<HuffManTC[Letter[Words[i]]].Codes[j];
160     }
161     cout<<endl;
162 }
163 /*解码*/
164 void DeCoding(string Words)
165 {  int Flag,Tmp;
166    for (int i=0;i<Words.size();)
167    {   Tmp=i;  
168        for (int j=0;j<MAXNUM;++j)
169        {  Flag=1;
170           for(int k=0;k<HuffManTC[j].Length;++k)
171              {
172                  if (HuffManTC[j].Codes[k]==Words[Tmp])
173                     ++Tmp;
174               else
175               {   Flag=-1;
176                   Tmp=i;
177                   break;
178               }
179              }
180           if (Flag==1)
181           { i=Tmp;
182             if (j==0) cout<<' ';
183             else cout<<char('a'+j-1);
184             break;
185           }
186           else if (Flag==-1 && j==MAXNUM-1) return;//此情形说明输入有误
187          }                              //遍历一遍后发现之后无对应字母
188        }
189    }
190 }
191 void De_InputData()
192 {
193     cout<<"请输入要译码的语句"<<endl;
194     cin>>Words;
195     cout<<"您输入的是:"<<Words<<endl;
196     DeCoding(Words);
197 }
198 void TaskMgr()
199 {
200    cout<<"请问您是要编码还是解码?编码输入A,解码输入B"<<endl;
201    string Flag;
202    getline(cin,Flag);
203    while (Flag!="A" && Flag!="B")
204    {
205        cout<<"输入有误,请重新输入!"<<endl;
206        getline(cin,Flag);
207    }
208    if (Flag=="A")
209    {
210        Making_InputData();
211        Making_OutputData();
212    }
213    if (Flag=="B")
214    {
215        De_InputData();
216     }
217 int main()
218 {
219     CopyRight();
220     Huffman(a,MAXNUM,HuffManTN,HuffManTC);
221     OutputHuffManCode();
222     TaskMgr();
223     return 0;
224 }

 

P.S.

呃、 DataStructure Rank1了、不过也理所当然(hhhhh)

然而发现写代码都不知道要写int main的也90+我直接呵呵哒了(23333333)

算了、你们开心就好。

想起Matrix67神犇大概的一句话,“正因为没在数学专业学习,我才能不以考试为目的地学习任何自己想学的数学知识,才能对数学有如此浓厚的兴趣”

嗯,改个主语233

在我系除了还有个数据库数据挖掘外基本不学Coding了吧

好吧、你们开心就好

有发现什么bug的话说一声……反正我这三个作业是满分(然而这并不能说明任何问题呵呵哒)

posted @ 2016-01-17 19:49  Iris.Catch-22.S、`  阅读(423)  评论(0编辑  收藏  举报