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

  • 相关阅读:
    Elasticsearch之如何合理分配索引分片
    mybatis 批量插入 decimal精度问题
    在Java项目中打印错误日志的正确姿势
    Fork/Join框架原理
    AOP切面之打印方法时间
    转java之基础 equals和==比较
    Kibana
    基于mq搭建elk
    LogBack
    MongoD副本集(一)
  • 原文地址:https://www.cnblogs.com/Catch-22/p/5137684.html
Copyright © 2020-2023  润新知