数据结构课程设计:3、哈夫曼编码/译码系统(树应用)

版权声明:转载请留言 https://blog.csdn.net/qq_40744093 https://blog.csdn.net/qq_40744093/article/details/86242477

                                               哈夫曼编码/译码系统(树应用)

[问题描述]

利用哈夫曼编码进行通信,可以压缩通信的数据量,提高传输效率,缩短信息的传输时间,还有一定的保密性。现在要求编写一程序模拟传输过程,实现在发送前将要发送的字符信息进行编码,然后进行发送,接收后将传来的数据进行译码,即将信息还原成发送前的字符信息。

 

[实现提示]

在本例中设置发送者和接受者两个功能,

发送者的功能包括:

①输入待传送的字符信息;

②统计字符信息中出现的字符种类数和各字符出现的次数(频率);

②根据字符的种类数和各自出现的次数建立哈夫曼树;

③利用以上哈夫曼树求出各字符的哈夫曼编码;

④将字符信息转换成对应的编码信息进行传送。

接受者的功能包括:

①接收发送者传送来的编码信息;

②利用上述哈夫曼树对编码信息进行翻译,即将编码信息还原成发送前的字符信息。

从以上分析可发现,在本例中的主要算法有三个:

(1)哈夫曼树的建立;

(2)哈夫曼编码的生成;

(3)对编码信息的翻译。

[设计思路]

  1. 哈夫曼树的建立
  2. 哈夫曼编码的生成
  3. 对编码信息的翻译

[代码及注释]

#include<iostream>
#include<map>
#include<cstring>
#include<algorithm>
using namespace std;
#define MAXSIZE 111                                       /*可传递信息的最大长度*/
//结构
typedef struct{
    int weight;                                           /*结点的权值*/
    int parent,lchild,rchild;                             /*结点的双亲、左孩子、右孩子的下标*/
    char ch;                                              /*结点的字符*/
    string HuffmanCode;                                   /*结点的哈夫曼编码*/
}HTNode,*HuffmanTree;                                     /*动态分配数组储存哈夫曼树*/
map<char,int> Map;                                        /*map容器储存字符及对应次数*/
//子函数
void GetInformation(int &kind);                           /*统计字符种类数和各字符出现的次数*/
void SelectMinNode(HuffmanTree &HT,int k,int &s1,int &s2);/*选择两个权值最小结点*/
bool CreatHuffmanTree(HuffmanTree &HT,int n);             /*哈夫曼树的创建*/
void CreatHuffmanCode(HuffmanTree &HT,int n);             /*哈夫曼编码的创建*/
void Translate(HuffmanTree HT,int n);                     /*译码*/
//具体内容
void GetInformation(int &kind)
{
    kind=0;
    cout<<"输入传递信息(不含中文):";
    char str[MAXSIZE];
    gets(str);                                            /*可读入含空格道德字符串*/
    for(int i=0;i<strlen(str);++i)
        Map[str[i]]++;                                    /*记录字符出现次数*/
    map<char,int> ::iterator it=Map.begin();
    while(it!=Map.end())
    {
        ++kind;
        it++;
    }                                                     /*迭代器遍历*/
    cout<<endl;
    cout<<"字符种类:"<<kind<<endl<<endl;
    cout<<" ---------"<<endl;
    cout<<"|字符"<<" 次数"<<endl;
    for(it=Map.begin();it!=Map.end();++it)
            cout<<"| "<<(*it).first<<"    "<<(*it).second<<endl;
    cout<<" ---------"<<endl;
}
void SelectMinNode(HuffmanTree &HT,int k,int &s1,int &s2)
{
    int Min=1e9;                                          /*初始化当前最小权值*/
    for(int i=1;i<=k;++i)
        if(!HT[i].parent)
            if(HT[i].weight<=Min)
            {
                Min=HT[i].weight;                         /*不断更新Min*/
                s1=i;
            }                                             /*从前k个结点找出最小结点*/
    Min=1e9;                                              /*重置权值*/
    for(int i=1;i<=k;++i)
        if(!HT[i].parent&&i!=s1)
            if(HT[i].weight<=Min)
            {
                Min=HT[i].weight;                         /*不断更新Min*/
                s2=i;
            }                                             /*从前k个结点除s1外找出最小结点*/
}
bool CreatHuffmanTree(HuffmanTree &HT,int n)
{
    if(n<=1)
    {
        cout<<"<<<<字符种类太少无需使用哈夫曼树"<<endl;
        return false;
    }
    else
    {
        int m=2*n-1;
        HT=new HTNode[m+1];                                 /*分配空间,0号单元未使用*/
        map<char,int> ::iterator it=Map.begin();
        int j=0;
        while(it!=Map.end())
        {
            ++j;
            HT[j].weight=(*it).second;                      /*初始化字符出现次数*/
            HT[j].ch=(*it).first;                           /*初始化字符*/
            HT[j].HuffmanCode="";                           /*初始化哈夫曼编码为空*/
            HT[j].lchild=HT[j].rchild=HT[j].parent=0;       /*左右孩子及双亲均初始化为0*/
            ++it;
        }
        for(int i=n+1;i<=m;++i)
            HT[i].weight=HT[i].parent=HT[i].rchild=HT[i].lchild=0;
                                                            /*初始化从n+1到m的结点*/
        for(int i=n+1;i<=m;++i)                             /*n-1次的选择删除合并来创建哈夫曼树*/
        {
            int s1,s2;
            SelectMinNode(HT,i-1,s1,s2);                    /*将最小两个结点的下标赋予s1,s2;*/
            HT[s1].parent=i;                                /*s1双亲亲赋予i第i编号*/
            HT[s2].parent=i;                                /*s2双亲亲赋予i第i编号*/
            HT[i].lchild=s1;                                /*s1成为编号为i的左孩子*/
            HT[i].rchild=s2;                                /*s2成为编号为i的右孩子*/
            HT[i].weight=HT[s1].weight+HT[s2].weight;       /*合并左右孩子权值*/
        }
        cout<<"<<<<哈夫曼树创建成功"<<endl<<endl;
        return true;
    }
}
void CreatHuffmanCode(HuffmanTree &HT,int n)
{
	int c,f;
	cout<<"<<<<哈夫曼编码创建成功,如下:"<<endl;
	for(int i=1;i<=n;i++)
	{
        c=i;                                                /*c:当前结点序号*/
        f=HT[i].parent;                                     /*f:当前节点的双亲*/
		while(f!=0)                                         /*f为根节点终止*/
		{
            if(HT[f].lchild==c)HT[i].HuffmanCode+="0";      /*左边加0*/
            else HT[i].HuffmanCode+="1";                    /*右边加1*/
            c=f;
            f=HT[f].parent;
                                                            /*不断向上层查找*/
        }
    reverse(HT[i].HuffmanCode.begin(),HT[i].HuffmanCode.end());
                                                            /*翻转,因为上步操作得到的是逆序*/
	cout<<HT[i].ch<<":"<<HT[i].HuffmanCode<<endl;
	}
	cout<<endl;
}
void Translate(HuffmanTree HT,int n)
{
    cout<<"输入译码:";
    string str;
    cin>>str;
    int len=str.size();
    int flag=-1;                                            /*判断译码是否成功的标志*/
    string ans,temp;                                        /*ans:最终译码答案*/
                                                            /*temp:匹配临时字符串*/
    for(int i=0;i<len;++i)
    {
        temp+=str[i];
        for(int j=1;j<=n;++j)
            if(HT[j].HuffmanCode==temp)
            {
                temp="";                                    /*匹配成功将临时字符串置空*/
                ans+=HT[j].ch;
                flag=i;
            }
    }
    if(flag!=len-1)cout<<"<<<<输入的源码有误!!!"<<endl;     /*没有匹配成功*/
    else
    {   cout<<"<<<<译码成功!内容如下"<<endl;
        cout<<ans<<endl;
    }
    cout<<"是否继续(y/n)?";
    char judge;                                             /*判断是否继续译码*/
    cin>>judge;
    if(judge=='y')Translate(HT,n);
    else return;
}
int main()
{
    HuffmanTree HT;
    int kind;
    GetInformation(kind);
    if(CreatHuffmanTree(HT,kind))
    {
        CreatHuffmanCode(HT,kind);
        Translate(HT,kind);
    }

    return 0;
}

[简单展示]

猜你喜欢

转载自blog.csdn.net/qq_40744093/article/details/86242477
今日推荐