zoukankan      html  css  js  c++  java
  • [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的话说一声……反正我这三个作业是满分(然而这并不能说明任何问题呵呵哒)

  • 相关阅读:
    1062 Talent and Virtue (25 分)
    1083 List Grades (25 分)
    1149 Dangerous Goods Packaging (25 分)
    1121 Damn Single (25 分)
    1120 Friend Numbers (20 分)
    1084 Broken Keyboard (20 分)
    1092 To Buy or Not to Buy (20 分)
    数组与链表
    二叉树
    时间复杂度与空间复杂度
  • 原文地址:https://www.cnblogs.com/Catch-22/p/5137684.html
Copyright © 2011-2022 走看看