zoukankan      html  css  js  c++  java
  • 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("请输入一串字符串(该字符串只能为小写字母):
    ");
     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]='';
    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]='';            
    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编码为:
    "); 
    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("输入串对应的哈夫曼编码为:
    ");
    145     for(int i=0;str[i];i++)//根据字符匹配编码 
    146     {
    147         printf("%s",Huffman_code[str[i]-'a']);    
    148     }
    149     printf("
    ");
    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("该字符串压缩比为:
    ");
    175     printf("%.2lf%%
    ",ans*100);
    176 }
    177 
    178 void Solve2()//译码
    179 {
    180     char tem[maxn];
    181 //    char ans[maxn];
    182 //    int len=0;
    183     printf("请输入要进行译码的0-1串:
    ");
    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]='';
    216 //    printf("该0-1串译文为:
    ");
    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("
    ");
    243 }
    244 
    245 int main()
    246 {
    247     Init();
    248     printf("--------------------------------
    "); 
    249     Print_out();
    250     printf("--------------------------------
    ");
    251     Solve1();
    252     printf("--------------------------------
    ");
    253     Solve2();
    254     printf("--------------------------------
    ");
    255     return 0;
    256 } 
  • 相关阅读:
    jQuery遍历之siblings()
    命名空间
    AnsiString
    《linux内核完全注释》读书笔记 2
    mciSendString
    PeekMessage, GetMessage, PostMessage, SendMessage
    c/c++中运行外部程序或打开文件(转)
    定义基类和派生类
    复制构造函数
    让StringGrid控件显示下拉菜单
  • 原文地址:https://www.cnblogs.com/jiamian/p/11696366.html
Copyright © 2011-2022 走看看