DS二叉树——Huffman编码与解码(不含代码框架)

Posted szu-ds-wys

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了DS二叉树——Huffman编码与解码(不含代码框架)相关的知识,希望对你有一定的参考价值。

题目描述

1、问题描述

 

给定n个字符及其对应的权值,构造Huffman树,并进行huffman编码和译(解)码。

 

构造Huffman树时,要求左子树根的权值小于、等于右子树根的权值。

 

进行Huffman编码时,假定Huffman树的左分支上编码为‘0’,右分支上编码为‘1’。

 

2、算法

 

构造Huffman树算法:

 

⑴ 根据给定的n个权值(w1, w2, …, wn)构成n棵二叉树的集合F={T1, T2, …, Tn},其中每棵二叉树Ti中只有一个权值为wi的根结点。

 

⑵ 在F中选取两棵根结点的权值最小的树,作为左、右子树构造一棵新的二叉树,且置其根结点的权值为其左、右子树权值之和。

 

⑶ 在F中删除这两棵树,同时将新得到的二叉树加入F中。

 

(4) 重复⑵, ⑶,直到F只含一棵树为止。

 

3、Huffman编码算法:

 

⑴ 从Huffman树的每一个叶子结点开始。

 

⑵ 依次沿结点到根的路径,判断该结点是父亲结点的左孩子还是右孩子,如果是左孩子则得到编码‘0’,否则得到编码‘1’,先得到的编码放在后面。

 

⑶ 直到到达根结点,编码序列即为该叶子结点对应的Huffman编码。

 

4、Huffman译(解)码算法:

 

⑴ 指针指向Huffman树的根结点,取第一个Huffman码。

 

⑵ 如果Huffman码为‘0’,将指针指向当前结点的左子树的根结点;如果Huffman码为‘1’,将指针指向当前结点的右子树的根结点。

 

⑶ 如果指针指向的当前结点为叶子结点,则输出叶子结点对应的字符;否则,取下一个Huffman码,并返回⑵。

 

⑷ 如果Huffman码序列未结束,则返回⑴继续译码。

 

输入

第一行测试次数

 

2行:第一组测试数据的字符个数n,后跟n个字符

 

3行:第一组测试数据的字符权重

 

待编码的字符串s1

 

编码串s2

 

其它组测试数据类推

 

输出

第一行~第n行,第一组测试数据各字符编码值

 

n+1行,串s1的编码值

 

n+2行,串s2的解码值,若解码不成功,输出error!

 

其它组测试数据类推

 

样例输入

2 5 A B C D E 15 4 4 3 2 ABDEC 00000101100 4 A B C D 7 5 2 4 ABAD 1110110

样例输出

A :1 B :010 C :011 D :001 E :000 1010001000011 error! A :0 B :10 C :110 D :111 0100111 DAC

提示

#include<iostream>
#include<string>
using namespace std;
#define maxw 9999
class HuffmanNode
{
public:
    int weight;
    int parent;
    int left;
    int right;
    HuffmanNode()
    {
        weight=0;
        parent=left=right=-1;
    }
};
 
class HuffmanTree
{
public:
    int len;///总长
    int num;///元素个数
    HuffmanNode *Tree;
    string *HuffmanCode;
    char *message;
    HuffmanTree(int n,char *c,int *w)
    {
        num=n;
        len=2*num-1;
        Tree=new HuffmanNode[len];
        HuffmanCode=new string[num];
        message=new char[num];
        CreateHuffmanTree(c,w);
    }
    void CreateHuffmanTree(char *c,int *w)
    {
        int s1=0,s2=0;
        for(int i=0;i<num;i++)
        {
            Tree[i].weight=w[i];
        }
        for(int i=0;i<num;i++)
        {
            message[i]=c[i];
        }
        for(int i=0;i<len;i++)
        {
            if(i>=num)
                Tree[i].weight=0;
            Tree[i].parent=Tree[i].left=Tree[i].right=-1;
        }
        for(int i=num;i<len;i++)
        {
            SelectMin(i-1,s1,s2);
            Tree[s1].parent=i;
            Tree[s2].parent=i;
            Tree[i].left=s1;
            Tree[i].right=s2;
            Tree[i].weight=Tree[s1].weight+Tree[s2].weight;
        }
    }
    void SelectMin(int pos,int &s1,int &s2)
    {
        int w1=maxw,w2=maxw;
        for(int i=0;i<=pos;i++)
        {
            if(Tree[i].weight<w1&&Tree[i].parent==-1)
            {
                w1=Tree[i].weight;
                s1=i;
            }
        }
        for(int i=0;i<=pos;i++)
        {
            if(i==s1)
                continue;
            if(Tree[i].weight<w2&&Tree[i].parent==-1)
            {
                w2=Tree[i].weight;
                s2=i;
            }
        }
    }
    void HuffmanCoding()
    {
        char *cd=new char[num];
        cd[num-1]=;
        int start;
        for(int i=0;i<num;i++)
        {
            start=num-1;
            for(int j=i,k=Tree[i].parent;k!=-1;j=k,k=Tree[k].parent)
            {
                if(Tree[k].left==j)
                {
                    start--;
                    cd[start]=0;
                }
                else
                {
                    start--;
                    cd[start]=1;
                }
                HuffmanCode[i].assign(&cd[start]);
            }
        }
    }
    string code(string str)
    {
        string coding="";
        int length=str.size();
        for(int i=0;i<length;i++)
        {
            char c=str[i];
            for(int j=0;j<num;j++)
            {
                if(c==message[j])
                {
                    coding+=HuffmanCode[j];
                }
            }
        }
        return coding;
    }
    string decode(string str)
    {
        string decoding="";
        string iter="";
        int length=str.size();
        int judge1=0;
        for(int i=0;i<length;i++)
        {
            iter+=str[i];
            for(int j=0;j<num;j++)
            {
                if(iter==HuffmanCode[j])
                {
                    decoding+=message[j];
                    judge1+=(int)iter.size();
                    iter="";
                }
            }
        }
        int judge2=iter.size();
        if(judge1!=length)
            return "error!";
        if(judge2!=0)
            return "error!";
        return decoding;
    }
};
 
int main()
{
    int T;
    cin>>T;
    while(T--)
    {
        int n;
        cin>>n;
        char *c=new char[n];
        for(int i=0;i<n;i++)
            cin>>c[i];
        int *w=new int[n];
        for(int i=0;i<n;i++)
            cin>>w[i];
        HuffmanTree Tree(n,c,w);
        Tree.HuffmanCoding();
        string codeneeding,decodeneeding;
        cin>>codeneeding>>decodeneeding;
        for(int i=0;i<Tree.num;i++)
        {
            cout<<Tree.message[i]<<" "<<":"<<Tree.HuffmanCode[i]<<endl;
        }
        cout<<Tree.code(codeneeding)<<endl;
        cout<<Tree.decode(decodeneeding)<<endl;
        delete []c;
        delete []w;
    }
    return 0;
}

以上是关于DS二叉树——Huffman编码与解码(不含代码框架)的主要内容,如果未能解决你的问题,请参考以下文章

DS二叉树—二叉树构建与遍历(不含框架)

基础数据结构-二叉树-赫夫曼树的解码(详解)

h5房卡源码C语言实现哈夫曼树编码解码及问题总结

数据结构 赫夫曼树

二叉树

基于二叉树和数组实现限制长度的最优Huffman编码