解决

/*设计思路,采用线性标存储,用数组存储二叉树,数组从1开始存储,舍弃a[0],所有非叶子节点的info存储字符#,不影响对#的编码,
把编码结果保存在HT数组中*/  //测试样例  输入:aaaaabbbbcccdde 111000011010
#include<bits/stdc++.h>
using namespace std;
typedef struct
{
    char info;//关联字符信息
    int weight;//每个节点的权值
    int parent,lchild,rchild;//索引
}TNode,*Huffmancode;
typedef struct
{
    char ch;
    string s;
}Coding;
int count(TNode a[],string s)
{
    int i=1,n;
    string::iterator it1;//指向string的迭代器
    map<char,int> T;
    map<char,int>::iterator it;//it指向T
    T.clear();//清空T
    for(it1=s.begin();it1!=s.end();it1++)
    {
        T[*it1]++;
    }
    for(it=T.begin();it!=T.end();it++)
    {
        pair<char,int>item=*it;
        a[i].info=item.first;
        a[i++].weight=item.second;
    }
    n=i-1;
    cout<<"叶子节点的数量为"<<n<<endl;
    for(i=1;i<=n;i++)
    {
        cout<<a[i].info<<"---->"<<a[i].weight<<endl;//打印每个叶子的info,及weight
    }
    return n;//叶子节点数
}
TNode initalize(TNode a[],int n)//初始化函数
{
    int i;//一颗有n个节点的哈夫曼树有2n-个节点
    for(i=1;i<=n;i++)
    {
        a[i].parent=0;
        a[i].rchild=0;
        a[i].lchild=0;
    }
    for(i=n+1;i<=2*n-1;i++)
    {
        a[i].parent=0;
        a[i].rchild=0;
        a[i].lchild=0;
        a[i].weight=0;
        a[i].info='#';
    }
}
TNode HuffmanTree(TNode a[],int n)
{
    int m=2*n-1,i,j,k;
    int min1,min2;
    if(n>1) //当n=1时,m=1,不能构建HuffmanTree,直接对该字符编1,没有深度为一的哈夫曼树
    {
        for(i=n+1;i<=m;i++)
        {
            int min1=min2=0;
            a[min1].weight=1<<30,a[min2].weight=1<<30;
            for(j=1;j<i;j++)
            {
                if(!a[j].parent&&a[j].weight<a[min1].weight)
                {
                    min1=j;
                }
            }//第一小weight
            a[min1].parent=1;//1表示已被选取,便于选取第二小
            for(j=1;j<i;j++)
            {
                if(!a[j].parent&&a[j].weight<a[min2].weight)
                {
                    min2=j;
                }
            }//第二小weight
            a[i].weight=a[min1].weight+a[min2].weight;
            a[i].lchild=min1;
            a[i].rchild=min2;
            a[min1].parent=i;
            a[min2].parent=i;
        }
    }
}//Huffmantree构建完成
TNode Huffmancodeing(Coding b[],Coding HT[],TNode a[],int n)//编码函数,向右走为1,向左走为0;
{
    int i,j;
    string s;
    char ch;
    int c,p;
    for(i=1;i<=n;i++)//求编号为1-n的叶子节点的编码
    {
        c=i;//child索引
        p=a[i].parent;//找到parent的索引
        while(1)
        {
            if(!a[c].parent)
            {
                break;//根节点跳出循环
            }
            else if(a[c].parent)//p=0则说明到根节点,在2*n-的节点中根节点的parent=0
            {
                if(a[p].rchild==c)//i为p的右孩子
                {
                    s=s+'1';//cout<<'1';
                }
                else if(a[p].lchild==c)//i为p的左孩子
                {
                    s=s+'0';//cout<<'1';
                }
            }
            c=p;//继续从p走直到根节点
            p=a[c].parent;
        }
        b[i].ch=a[i].info;
        b[i].s=s;
        s.clear();
    }//从叶子节点向跟节点走,记录所走的路径,即为对应的编码 //接下来让路径反转
    string::iterator it;
    cout<<"输出对应编码"<<endl;
    for(i=1;i<=n;i++)
    {
        string s1;
        s1.clear();
        s=b[i].s;
        for(it=s.end()-1;it>=s.begin();it--)
        {
            s1=s1+*it;
        }
        HT[i].ch=b[i].ch;
        HT[i].s=s1;
        cout<<HT[i].ch<<"--->"<<HT[i].s<<endl;
        s.clear();
    }
}//从叶子节点向跟节点走,记录所走的路径,即为对应的编码
string decoder(TNode a[],string s1,string str,int n)//译码函数,对串s1进行树的遍历,将结果保存在str串中
{
    int m=2*n-1;
    str.clear();
    string::iterator  it;
    int c=m,y=m;//当前结点,y为叶子节点
    s1=s1+'#';
    for(it=s1.begin();it!=s1.end();it++)
    {
        if(c>=1&&c<=n)//判断当前节点是否为叶子节点
        {
            str+=a[c].info;
            it--;
            c=m;
        }
        else
        {
            if(*it=='1')
            {
                c=a[c].rchild;  
            }
            else  if(*it=='0')
            {
                c=a[c].lchild;
            }
        }
    }
    return str;
}
int main()
{
    string s,s1;
    int n;//叶子节点数
    TNode a[200];//存放需进行编码的字符的数组
    Coding b[200],HT[200];//存储NI编码的数组,编码数组HT
    getline(cin,s);//可以读入带空格的字符串
    n=count(a,s);//统计函数
    initalize(a,n);//初始化函数
    HuffmanTree(a,n);//建树函数
    Huffmancodeing(b,HT,a,n);//编码函数
    getline(cin,s1);//译码输入时需要以任意字符结尾,随便输入一个字符就可以,否则最后一个字符不能输出
    string str;
    str=decoder(a,s1,str,n);
    cout<<str<<endl;
}

    原文作者: 汉诺塔问题
    原文地址: https://blog.csdn.net/yanyuqingchen/article/details/78973698
    本文转自网络文章,转载此文章仅为分享知识,如有侵权,请联系博主进行删除。
点赞