贪心法解决哈夫曼树编码

设需要编码的字符集为{d1,d2,...,dn},它们出现的频率为(w1,w2,...,wn),应用哈夫曼树构造最优的不等长的由0,1构成的编码方案。

#include <iostream>
#include <queue>
#include <vector>
#include <string>
#include <map>
using namespace std;
#define MAX 101
int n;
struct HTreeNode            //哈夫曼树节点类型
{
    char data;              //字符
    int weight;             //权值
    int parent;             //双亲的位置
    int lchild;             //左孩子的位置
    int rchild;             //右孩子的位置
};
HTreeNode ht[MAX];          //存放哈夫曼树
map<char,string>htcode;     //存放哈夫曼编码
struct NodeType{            //优先队列节点类型
    int no;                 //对应哈夫曼树ht中的位置
    char data;              //字符
    int weight;             //权值
    bool operator<(const NodeType &s)const //用于创建小根堆
    {
        return s.weight<weight;
    }
};

void CreateHTree()                              //构造哈夫曼树
{
    NodeType e,e1,e2;
    priority_queue<NodeType>qu;
    for(int k=0;k<2*n-1;k++)                    //设置所有节点的指针域
        ht[k].lchild=ht[k].rchild = ht[k].parent = -1;
    for(int i=0;i<n;i++){                        //将n个节点进队
        e.no = i;
        e.data = ht[i].data;
        e.weight = ht[i].weight;
        qu.push(e);
    }
    for(int j = n;j<2*n-1;j++)                      //构造哈夫曼树的n-1个非叶子节点。
    {
        e1 = qu.top();qu.pop();
        e2 = qu.top();qu.pop();
        ht[j].weight = e1.weight+e2.weight;
        ht[j].lchild = e1.no;
        ht[j].rchild = e2.no;
        ht[e1.no].parent =j;
        ht[e2.no].parent = j;
        e.no = j;
        e.weight=e1.weight+e2.weight;
        qu.push(e);
    }
}

void CreateHCode(){
    string code;
    for(int i=0;i<n;i++) //构造叶子节点i的哈夫曼编码
    {
        code = "";
        int curno = i;
        int  f = ht[curno].parent;
        while(f!=-1){                   //循环的跟节点
            if(ht[f].lchild == curno)   //curno为双亲节点的左孩子
                code = '0'+code;
            else                        //curno为双亲结点的右孩子。=
                code = '1'+code;
            curno =f;f=ht[curno].parent;
        }
        htcode[ht[i].data] =code;       //得到ht[i].data字符的哈弗曼编码
    }
}
void DispHCode(){                               //输出哈夫曼编码
    map<char,string> ::iterator it;
    for(it = htcode.begin();it!=htcode.end();++it)
        cout<<""<<it->first<<":"<<it->second<<endl;
}
void DispHTree(){                                   //输出哈夫曼树
    for(int i=0;i<2*n-1;i++){
        printf("data = %c,weight = %d, lchild = %d,rchild = %d,parent = %d\n",
               ht[i].data,ht[i].weight,ht[i].lchild,ht[i].rchild,ht[i].parent);
    }
}
int WPL(){                              //求WPL
    int wps=0;
    for(int i=0;i<n;i++)
        wps+=ht[i].weight*htcode[ht[i].data].size();
    return wps;
}
int  main()
{
    n =5;
    ht[0].data = 'a';ht[0].weight = 4;
    ht[1].data = 'b';ht[1].weight =2;
    ht[2].data = 'c';ht[2].weight = 1;
    ht[3].data = 'd';ht[3].weight =7;
    ht[4].data = 'e';ht[4].weight =3;
    CreateHTree();
    printf("构造的哈夫曼树:\n");
    DispHTree();
    CreateHCode();
    printf("产生的哈夫曼树编码如下:\n");
    DispHCode();
    printf("WPK=%d\n",WPL());
}

  • 3
    点赞
  • 12
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值