zoukankan      html  css  js  c++  java
  • 哈夫曼编码器

    整理了一下最近做的数据结构上机实习题:

    【问题描述】 利用哈夫曼编码进行信息通讯可以大大提高信道利用率,缩短信息 传输时间,降低传输成本。但是,这要求在发送端通过一个编码系统对 待传数据预先编码;在接收端将传来的数据进行译码(复原)。对于双 工信道(即可以双向传输信息的信道),每端都需要一个完整的编/译码 系统。试为这样的信息收发站写一个哈夫曼码的编译码系统。

    【基本要求】 一个完整的系统应具有以下功能: (1)I:初始化(Initialization)。从终端读入字符集大小n,及n个 字符和n个权值,建立哈夫曼树,并将它存于文件hfmtree中。 (2)C:编码(Coding )。利用已建好的哈夫曼树(如不在内存, 则从文件hfmtree中读入),对文件tobetrans中的正文进行编码,然后 将结果存入文件codefile中。 (3)D:译码(Decoding)。利用已建好的哈夫曼树将文件codefile 中的代码进行译码,结果存入文件textfile中。

    (4)P:印代码文件(Print)。将文件codefile以紧凑格式显示在终端 上,每行50个代码。同时将此字符形式的编码文件写入文件codeprint中。 (5)T:印哈夫曼树(Tree printing)。将已在内存中的哈夫曼树以 直观的方式(树或凹入表形式)显示在终端上,同时将此字符形式的哈夫 曼树写入文件treeprint中。

    【测试数据】 (1)已知某系统在通信联络中只可能出现八种字符,其频率分别为 0.05,0.29,0.07,0.08,0.14,0.23,0.03,0.11,试设计哈夫曼编码。 (2)实现以下报文的编码和译码:“THIS PROGRAM IS MY FAVORITE”。

    【实现提示】 (1)用户界面可以设计为“菜单”方式:显示上述功能符号,再加上 “E”,表示结束运行End,请用户键入一个选择功能符。此功能执行完毕 后再显示此菜单,直至某次用户选择了“E”为止。 (2)程序的一次执行过程中,第一次执行I、D或C命令之后,哈夫曼 树已经在内存了,不必再读入。每次执行中不一定执行I命令,因为文件 hfmtree可能早已建好。

    haffman.h

     1 typedef struct {
     2     char data;
     3     int weight ;
     4     int flag;
     5     int parent ;
     6     int leftChild ;
     7     int rightChild ;
     8 }HaffNode ;
     9 
    10 typedef struct {
    11     char bit[MaxNode];
    12     int start ;
    13     int weight ;
    14     char data ;
    15 }Code ;
    16 
    17 void Haffman(int weight[],char str[],int n,HaffNode haffTree[])
    18 {
    19     int i,j,m1,m2,x1,x2 ;
    20     for(i=0;i<2*n-1;i++){
    21         if(i<n) {
    22             haffTree[i].weight=weight[i];
    23             haffTree[i].data=str[i];
    24         }else {
    25             haffTree[i].weight=0;
    26             haffTree[i].data='0';
    27         }
    28         haffTree[i].parent=-1;
    29         haffTree[i].flag=0;
    30         haffTree[i].leftChild=-1;
    31         haffTree[i].rightChild=-1;
    32     }
    33     for(i=0;i<n-1;i++){
    34         m1=m2=MaxValue ;
    35         x1=x2=0;
    36         for(j=0;j<n+i;j++){
    37             if(haffTree[j].weight<m1&&haffTree[j].flag==0){
    38                 m2=m1;
    39                 x2=x1;
    40                 m1=haffTree[j].weight;
    41                 x1=j;
    42             }else if(haffTree[j].weight<m2&&haffTree[j].flag==0)
    43             {
    44                 m2=haffTree[j].weight;
    45                 x2=j ;
    46             }
    47         }
    48         haffTree[x1].parent=n+i;
    49         haffTree[x2].parent=n+i;
    50         haffTree[x1].flag=haffTree[x2].flag=1;
    51         haffTree[n+i].weight=haffTree[x1].weight+haffTree[x2].weight;
    52         haffTree[n+i].leftChild=x1;
    53         haffTree[n+i].rightChild=x2;
    54     }
    55 }
    56 
    57 void HaffmanCode(HaffNode haffTree[],int n,Code haffCode[])
    58 {
    59     Code *cd=(Code *)malloc(sizeof(Code));
    60     int i,j,child,parent ;
    61     for(i=0;i<n;i++){
    62         cd->start=n-1;
    63         cd->weight=haffTree[i].weight;
    64         cd->data=haffTree[i].data ;
    65         child=i;
    66         parent=haffTree[child].parent ;
    67         while(parent!=-1){
    68             if(haffTree[parent].leftChild==child)
    69                 cd->bit[cd->start]='0';
    70             else 
    71                 cd->bit[cd->start]='1';
    72 
    73             cd->start--;
    74             child=parent ;
    75             parent=haffTree[child].parent;
    76         }
    77         for(j=cd->start+1;j<n;j++)
    78             haffCode[i].bit[j]=cd->bit[j];
    79         haffCode[i].bit[j]='\0';
    80         haffCode[i].start=cd->start+1;
    81         haffCode[i].weight=cd->weight;
    82         haffCode[i].data=cd->data;
    83     }
    84 }
      1 #include<iostream>
      2 #include<iomanip>
      3 #include<cstdio>
      4 #include<cstdlib>
      5 #include<cstring>
      6 #include<string>
      7 #include<fstream>
      8 #define MaxValue 32767
      9 #define MaxNode 10000
     10 #include"Haffman.h"
     11 using namespace std ;
     12 
     13 ifstream input_file ;
     14 ofstream output_file ;
     15 int n,m=0;
     16 HaffNode *myHaffTree=(HaffNode *)malloc(sizeof(HaffNode)*(2*MaxNode-1));
     17 Code *myHaffCode=(Code *)malloc(sizeof(Code)*MaxNode);
     18 
     19 void Initialization(){
     20     char str[MaxNode];
     21     int weight[MaxNode];
     22     cout<<"请输入字符个数:"<<endl;
     23     cin>>n;
     24     for(int i=0;i<n;i++){
     25         cout<<"请输入第"<<i+1<<"个字符以及相应的权值"<<endl;
     26         cin>>str[i]>>weight[i];
     27     }
     28 
     29     Haffman(weight,str,n,myHaffTree);
     30     HaffmanCode(myHaffTree,n,myHaffCode);
     31 
     32     for(int i=0;i<n;i++){
     33         cout<<myHaffCode[i].data<<": ";
     34         for(int j=myHaffCode[i].start;j<n;j++){
     35             cout<<myHaffCode[i].bit[j];
     36         }
     37         cout<<endl;
     38     }
     39 
     40     output_file.open("hfmTree.txt");
     41     if(!output_file){
     42         cout<<"can't open file !"<<endl;
     43         return ;
     44     }
     45     for(int i=0;i<n;i++){
     46         output_file<<"("<<myHaffTree[i].data<<myHaffTree[i].weight<<")"<<endl;
     47     }
     48     output_file.close();
     49     cout<<"哈夫曼树已创建完成,并且已放入hfmTree.txt中."<<endl;
     50     cout<<endl<<endl;
     51 }
     52 
     53 void Coding(){
     54     cout<<"请输入字符或字符串:"<<endl;
     55     string str ;
     56     string code ;
     57     cin>>str;
     58     output_file.open("tobetran.txt");
     59     if(!output_file){
     60         cout<<"can't open file !"<<endl;
     61         return ;
     62     }
     63     output_file<<str;
     64     output_file.close();
     65     output_file.open("codefile.txt");
     66     if(!output_file){
     67         cout<<"can't open file !"<<endl;
     68         return ;
     69     }
     70     for(int i=0;i<str.size();i++){
     71         for(int j=0;j<n;j++){
     72         if(myHaffTree[j].data==str[i]){
     73             for(int k=myHaffCode[j].start;k<n;k++){
     74                 output_file<<myHaffCode[j].bit[k];
     75             }
     76             break;
     77             }
     78         }
     79     }
     80     output_file.close();
     81     cout<<"编码完毕,并且已经存入codefile.txt中!"<<endl;
     82     input_file.open("codefile.txt");
     83     if(!input_file){
     84         cout<<"can't open file !"<<endl;
     85         return ;
     86     }
     87     input_file>>code;
     88     cout<<"编码码值为:"<<endl;
     89     cout<<code<<endl;
     90     input_file.close();
     91     cout<<endl<<endl;
     92 }
     93 
     94 
     95 void Decoding(){
     96     char s[MaxNode],s1[MaxNode];
     97     int i,j,k,l,p;
     98     input_file.open("codefile.txt");
     99     if(!input_file){
    100         cout<<"can't open file !"<<endl;
    101         return ;
    102     }
    103     input_file>>s;
    104     input_file.close();
    105     output_file.open("textfile.txt");
    106     if(!output_file){
    107         cout<<"can't open file !"<<endl;
    108         return ;
    109     }
    110     k=0;
    111     while(s[k]!='\0'){
    112         for( i=0;i<n;i++){
    113             l=k;
    114             for( j=0;j<strlen(myHaffCode[i].bit)-myHaffCode[i].start;j++,l++){
    115                 s1[j]=s[l];
    116             }
    117             s1[j]='\0';
    118             for(p=myHaffCode[i].start,j=0;p<n;p++,j++)
    119                 if(myHaffCode[i].bit[p]!=s1[j]) break;
    120             if(p==n){
    121                 output_file<<myHaffTree[i].data;
    122                 k+=strlen(myHaffCode[i].bit)-myHaffCode[i].start;
    123                 break;
    124             }
    125         }
    126     }
    127     output_file.close();
    128     input_file.open("textfile.txt");
    129     if(!input_file){
    130         cout<<"can't open file !"<<endl;
    131         return ;
    132     }
    133     input_file>>s;
    134     cout<<s<<endl;
    135     input_file.close();
    136     cout<<"译码结束,字符已经存入textfile.txt文件中!"<<endl;
    137     cout<<endl<<endl;
    138 }
    139 
    140 void Print(){
    141     char s[MaxNode],s1[MaxNode];
    142     int i,j,k,l,p;
    143     input_file.open("codefile.txt");
    144     if(!input_file){
    145         cout<<"can't open file !"<<endl;
    146         return ;
    147     }
    148     input_file>>s;
    149     int icount=0;
    150     for(int i=1;i<strlen(s)+1;i++){
    151         cout<<s[i-1];
    152         if(i%50==0) cout<<endl;
    153     }
    154     cout<<endl;
    155     input_file.close();
    156     output_file.open("codeprint.txt");
    157     k=0;
    158     while(s[k]!='\0'){
    159         for( i=0;i<n;i++){
    160             l=k;
    161             for( j=0;j<strlen(myHaffCode[i].bit)-myHaffCode[i].start;j++,l++){
    162                 s1[j]=s[l];
    163             }
    164             s1[j]='\0';
    165             for(p=myHaffCode[i].start,j=0;p<n;p++,j++)
    166                 if(myHaffCode[i].bit[p]!=s1[j]) break;
    167             if(p==n){
    168                 output_file<<myHaffTree[i].data;
    169                 k+=strlen(myHaffCode[i].bit)-myHaffCode[i].start;
    170                 break;
    171             }
    172         }
    173     }
    174     output_file.close();
    175     cout<<"字符形式的编码文件写入文件codeprint中!"<<endl;
    176     cout<<endl<<endl;
    177 }
    178 
    179 void TreePrinting(HaffNode *myHaffTree1,HaffNode *myHaffTree2,int m){
    180     if(myHaffTree1!=myHaffTree2-1)
    181     {
    182         if(m)output_file.close();
    183         output_file.open("treeprint.txt");
    184         if(!output_file){
    185             cout<<"can't  open file !"<<endl;
    186             return ;
    187         }
    188         TreePrinting(myHaffTree2+myHaffTree1->rightChild,myHaffTree2,m+1);
    189         cout<<setw(4*m)<<myHaffTree1->weight<<endl;
    190         output_file<<myHaffTree1->weight<<endl;
    191         TreePrinting(myHaffTree2+myHaffTree1->leftChild,myHaffTree2,m+1);
    192         output_file.close();
    193     }
    194 }
    195 
    196 
    197 int main(){
    198     char ch ;
    199     while(1){
    200         cout<<"          *******************哈夫曼编/译码器****************"<<endl;
    201         cout<<"              I---Initialization"<<"         C---Coding"<<endl;
    202         cout<<"              D---Decoding"<<"               P---Print"<<endl;
    203         cout<<"          T---Tree  printing"<<"         E---Exit"<<endl;
    204         cout<<"              ------------------------------------------"<<endl;
    205         cout<<"please select a function key:"<<endl;
    206         cin>>ch;
    207         if(ch=='I')
    208             Initialization();
    209         else if(ch=='C')
    210             Coding();
    211         else if(ch=='D')
    212             Decoding();
    213         else if(ch=='P')
    214             Print();
    215         else if(ch=='T'){
    216             TreePrinting(myHaffTree+2*n-2,myHaffTree,0);
    217             cout<<"此字符形式的哈夫曼树已写入文件treeprint中"<<endl;
    218             cout<<endl<<endl;
    219         }
    220         else if(ch=='E')
    221             break;
    222         else 
    223             cout<<"The key is not exsit, please select again !"<<endl;
    224     }
    225     return 0;
    226 }
  • 相关阅读:
    geoserver显示shapefile中汉字呈乱码问题的可选解决方案
    C++回调函数示例
    也谈谈技术面试
    轻快好的c++实践
    向 Hacker 迈进 我的书单
    CMake是个好东西
    工作之中总有几日不在状态_你是怎样度过的?
    我是如何从煤矿工成为程序员的
    java多线程系列_用Thread类创建线程(2)
    java多线程系列_使用Runnable接口创建线程(3)
  • 原文地址:https://www.cnblogs.com/wally/p/2763120.html
Copyright © 2011-2022 走看看