一颗名叫哈夫曼的树

来源:互联网 发布:mac qq和pc qq同时登录 编辑:程序博客网 时间:2024/04/28 04:42

写在开头——这是一个耗时两周,几度中断,最终还是未完成的代码。
事情的源头是一次上机实验,这是一道选做题:

  设计一个哈夫曼编码、译码系统。对一个 ASCII 编码的文本文件中的字符进行哈夫曼编码,生成编码 文件; 反过来,可将编码文件译码还原为一个文本文件。       (1) 从文件中读入任意一篇英文短文(文件为 ASCII 编码扩展名为 txt) (2) 统计并输出不同字符在文章中出现的频率(空格、换行、标点等也按字符处理); (3) 根据字符频率构造哈夫曼树,并给出每个字符的哈夫曼编码; 

开始的时候我觉得这道题可以做啊,重点不就是哈夫曼树的建立吗,书上的代码白纸黑字。于是我就入坑了。。

从哪里入手呢?嗯,先写一个读写文件的函数吧! 突然我的脑子一片空白,对文件是怎么操作来着,我怎么毫无印象,才反应过来c语言的文件操作早已经忘得精光。

从柜底扒出来大一的红皮书,看了几眼,嗯,就这么回事,so easy。既然要挑战自己,那就不能守旧,同时我也很好奇c++对文件是怎么操作的。于是乎,我就怀着程序猿的使命就是创造世界的满腔热血来回谷歌,万千百度。
说起来惭愧,c++对文件的操作我是掌握了,却是用了一周的时间!期间我还发了我在csdn的第一个博客,就是那个c++对文件的操作。

对文件的读取用的方法取自前一篇博客。文件操作是解决了,可新问题又来了,统计字符。开始我就用两个数组data[ ],weight[ ] ,一个存字符,一个计数,不用想 死路一条。

于是,又专门创建一个类Data 来初步保存从文件读取的字符的种类以及权值。然后是把他们排个序,为下一步建立哈夫曼树做准备。

好了,现在原材料有了,可以开始写哈夫曼树了。可后来我哭了,我才明白算法思想了然于胸和用代码实现是天壤之别。翻开书,恭恭敬敬地看了好几遍代码,又加上我自己

的改造,算是基本完成。树已经建好了,接下来就是对各个字符编码了,没成想这一步是如此的艰难,再一次卡死。这是昨天下午的事了。

开始想用非递归实现加一个辅助栈,因为我一碰见递归就犯迷糊,可是二叉树就是为递归而生的,我只能老老实实的迷失在递归里。还好今天上午把他给解决了。

还剩最后两个问题没解决,把txt文件哈夫曼编码,把编码后的文件按照哈夫曼解码。写到这对于学渣的我已经是不容易了,以后继续努力吧。

也就是说我现在的代码可以把一个txt文件里的字符读取,建成一个哈夫曼树,并且给出各个字符对应的哈夫曼编码。

下面是长篇代码,写的比较简陋,也没能来得及优化。函数都写到类里面了。。。

#include<iostream>#include<fstream>#include<string.h>#define MAX 80using namespace std;class Data{public:    char data;    int weight;    Data(char d=0,int w=0):data(d),weight(w){}};/*----------------哈夫曼树的节点类----------*/class NodeHuff{public:    NodeHuff* left;    NodeHuff* right;    char code[MAX];    //code是哈夫曼编码后的01字符串    int weight;    char data;    NodeHuff(NodeHuff* l=NULL,NodeHuff* r=NULL,int w=0,char c=0):left(l),right(r),weight(w),data(c){}    ~NodeHuff(){}};/*-----------------哈夫曼树类-----------------*/class Huffmantree{private:    NodeHuff* root;    int number=0;          //统计字符的种类数目    char data[MAX];    int weight[MAX];public:    Huffmantree(NodeHuff* r=NULL){root=r;}    ~Huffmantree()    {        deletetree(root);    }    NodeHuff* Getroot(){return root;}    void deletetree(NodeHuff* p)          //删除以p为根的整棵树    {        if(p==NULL) return;        NodeHuff* l,*r;            l=p->left;            r=p->right;        deletetree(l);        deletetree(r);        delete l;        delete r;    }    /*--------------建立哈夫曼树---------------*/    void CreatHuffman()    {        NodeHuff* H[MAX];        for(int i=0;i<MAX;i++)        {            H[i]=new NodeHuff;            H[i]->data=data[i];            H[i]->weight=weight[i];        }        int j=0;        NodeHuff* p1,*p2,*p,*t;        for(int i=0;i<MAX;i++)        {            t=new NodeHuff;            p1=H[i];            p2=H[i+1];            t->left=p1;            t->right=p2;            t->weight=p1->weight+p2->weight;            p=t;            j=i+2;            while(j<MAX&&(p->weight>H[j]->weight))            {                H[j-1]=H[j];                j++;            }            H[j-1]=p;        }        root=H[number-1];    }/*-------------------对文件中的字符计数并且按递增排序-------------------*/    void countAndSort(){    Data cc[MAX];                   //cc[]初步保存从文件读取的字符,后来再对其排序    char buffer[100];    ifstream infile("example.txt");    if(!infile.is_open())    {        cout<<"open error"<<endl;return;    }    char  q;    while(infile.good()&&!infile.eof())    {        memset(buffer,0,100*sizeof(char));        infile.getline(buffer,100);        for(int i=0;i<100;i++)        {            q=buffer[i];            if(q==0) ;            else            {                int o;                for(o=0;o<MAX;o++)                {                    if(cc[o].data==q)                    {cc[o].weight++;break;}                }                if((o==MAX)&&(number!=MAX))                    {                        cc[number].data=q;cc[number].weight++;                        number++;                    }            }        }    }    for(int i=number;i<=MAX;i++)    {        cc[i].weight=999;    }    infile.close();/*---------------对cc[]排序,将排好序的数据传给data[],weight[]--------------------*/    int j=0;    for(int k=0;k<number;k++)    {        for(int i=0;i<number;i++)        {            if(cc[j].weight>cc[i].weight)                j=i;        }        data[k]=cc[j].data;weight[k]=cc[j].weight;        cc[j].weight=999;    }    cout<<"---------各字符出现次数----------"<<endl<<endl;    for(int i=0;i<number;i++)    {        cout<<data[i]<<"\t"<<weight[i]<<"\t";    }    for(int i=number;i<MAX;i++)    {        data[i]=0;weight[i]=999;    }}/*---------按照哈夫曼树对字符编码------------*/    void Encode(NodeHuff* p,char *encode)    {        if(!p) return;         if(!(p->left)&&!(p->right))        {            for(int i=0;i<MAX;i++)                p->code[i]=encode[i];            cout<<p->data<<"\t"<<p->code<<endl;            return;}        NodeHuff*l,*r,*q;        char lcode[MAX];        char rcode[MAX];        l=p->left;int i=0;       while(encode[i]!='\0')       {           lcode[i]=encode[i];           i++;       };      lcode[i]='0';lcode[i+1]='\0';        r=p->right;i=0;        while(encode[i]!='\0')       {           rcode[i]=encode[i];           i++;       };        rcode[i]='1';rcode[i+1]='\0';       Encode(l,lcode);       Encode(r,rcode);    }};int main(){    Huffmantree h;    h.countAndSort();    h.CreatHuffman();    char en[MAX]={'\0'};    cout<<"--------------------"<<endl<<endl;    h.Encode(h.Getroot(),en);    return 0;}

0 0
原创粉丝点击