哈夫曼编码--贪心策略

Posted acmblog

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了哈夫曼编码--贪心策略相关的知识,希望对你有一定的参考价值。

哈夫曼编码还是在暑假时候看的,那时候并没有看懂因为比较菜(虽然现在也是很菜的),在《趣学算法》一书中这个问题讲解十分到位,我这篇博客真的是难以望其项背,只能对其进行一点借鉴和摘抄吧

哈夫曼编码是一棵树,权值越大的节点越靠近树根,越小的节点就越远离树根,从他的定义来看,首先想到的应该是贪心策略吧,没错就是贪心算法

虽然说是贪心算法,但是还要知道它 的实现方式啊,他的贪心策略是:每次从树的集合中取出没有双亲且权值最小的两棵树作为左右子树,并合并他们

步骤 :

  1 :确定合适的数据结构(要知道他的左右子树,双亲,权值)

  2:初始化,构造n颗节点为n的字符单节点树集合T={t1,t2,t3,t4···········tn},并且每棵树只有树根

  3:如果集合中只剩下一棵树,那么哈夫曼树就构造成功,直接跳转到步骤6,否则就是从集合中继续拿出没有双亲的左右子树x,y,并将它们合并到一颗z树中,

    z的权值为左右子树权值之和

  4:从T集合中删除x,y 把新树z加入到集合T中

  5:重复步骤3~4

  6:约定左分支上的编码都是0,有分支上的编码都是1,从叶子节点开始逆序求出树的编码

图解:(这儿就直接调用这本书上的图片吧,是在太懒不想画图)

  技术分享图片

技术分享图片

技术分享图片

技术分享图片

代码的实现:

#include<bits/stdc++.h>
using namespace std;
#define MAXBIT 100
#define MAXVALUE 10000
#define MAXLEAF 30
#define MAXNODE MAXLEAF*2-1
typedef struct{
    double weight;
    int parent;
    int lchild;
    int rchild;
    char value;
}HNodeType;//?¨ò?μ?ê??úμ?·?±eóDè¨??£????×?úμ?£?×óóòo¢×ó£??1óD′ú±íμ?×?·? 
typedef struct{
    int bit[MAXBIT];
    int start;
}HCodeType;//?aê?±à???á11ì? 
HNodeType HuffNode[MAXNODE];//?úμ??á11ì?êy×é 
HCodeType HuffCode[MAXLEAF];//±à???á11ì?êy×é 
/*?ó??à′?aê?11?ì1t·ò?üê÷*/
void HuffmanTree(HNodeType HuffNode[MAXNODE],int n)
{
    /*i,jê??-?·±?á?£?m1,m2ê?×?D?μ?è¨?μ
    x1,x2ê?1t·ò?üê÷×?D?è¨?μ??ó|μ?Dòo?
    */
    int i,j,x1,x2;
    double m1,m2;
//    3?ê??ˉ?úμ? 
    for(i=0;i<2*n-1;i++)
    {
        HuffNode[i].lchild=-1;
        HuffNode[i].parent=-1;
        HuffNode[i].rchild=-1;
        HuffNode[i].weight=0;
    }
    for(i=0;i<n;i++)
    {
        cout<<"Please enter the value of every Node "<<i+1<<endl;
        cin>>HuffNode[i].value>>HuffNode[i].weight;
    }
//    11?ì1t?¥?üê÷
    for(i=0;i<n-1;i++)
    {//òa?-?·n-1′? 
        m1=m2=MAXVALUE;
        x1=x2=0;
    //?????aê??ò×?D?μ?á????μ
        for(j=0;j<n+i;j++)
        {
            if(HuffNode[j].weight<m1&&HuffNode[j].parent==-1)
            {
                m2=m1;
                x2=x1;
                m1=HuffNode[j].weight;
                x1=j;
            }
            else if(HuffNode[j].weight<m2&&HuffNode[j].parent==-1)
            {
                m2=HuffNode[j].weight;
                x2=j;
            }
        }
        HuffNode[x1].parent=n+i;
        HuffNode[x2].parent=n+i;
        HuffNode[n+i].weight=m1+m2;
        HuffNode[n+i].lchild=x1;
        HuffNode[n+i].rchild=x2;
        cout<<"x1.weight and x2.weight in round "<<i+1<<"	"
            <<HuffNode[x1].weight<<"	"<<HuffNode[x2].weight<<endl;//ó?óú2aê?
         
    }
}
void HuffmanCode(HCodeType HuffCode[MAXLEAF],int n)
{
    HCodeType cd;
    int i,j,c,p;
    for(i=0;i<n;i++)
    {
        cd.start=n-1;
        c=i;
        p=HuffNode[c].parent;
        while(p!=-1)
        {
            if(HuffNode[p].lchild==c)
                cd.bit[cd.start]=0;
            else 
                cd.bit[cd.start]=1;
            cd.start--;
            c=p;
            p=HuffNode[c].parent;
        }
        for(j=cd.start+1;j<n;j++)
            HuffCode[i].bit[j]=cd.bit[j];
        HuffCode[i].start=cd.start;
    }
}
int main()
{
    int i,j,n;
    cout<<"Please enter n"<<endl;
    cin>>n;
    HuffmanTree(HuffNode,n);
    HuffmanCode(HuffCode,n);
    for(i=0;i<n;i++)
    {
        cout<<HuffNode[i].value<<": Huffman Code is: ";
        for(j=HuffCode[i].start+1;j<n;j++)
        {
            cout<<HuffCode[i].bit[j];
        }
        cout<<endl;
    }
    return 0;
}

 

以上是关于哈夫曼编码--贪心策略的主要内容,如果未能解决你的问题,请参考以下文章

贪心算法应用-哈夫曼编码

贪心算法之哈夫曼树和哈夫曼编码

贪心算法 哈夫曼树编码

POJ - 3253 Fence Repair(贪心)

HDU 1053 Entropy(哈夫曼编码 贪心+优先队列)

贪心算法——哈夫曼编码树