[pta]6-4 哈夫曼树及编码

构造哈夫曼树,计算WPL。

函数接口定义:

void CreateHTree();
void CreateHCode();

裁判测试程序样例:

#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();
void CreateHCode();

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()
{
    cin >> n;
    for(int i=0;i<n;i++)
    {
        cin >> ht[i].data >> ht[i].weight;
    }  
    CreateHTree();                    //建立哈夫曼树
    CreateHCode();                    //求哈夫曼编码
    printf("WPL=%d",WPL());
    return 0;
}
/* 请在这里填写答案 */

输入样例:

第一行输入一个数n(1<n<100),表示叶子节点的个数,接下去输入n行,每行输入一个字符和一个整数,表示每个节点表示的字符和权值。

5
A 8
B 10
C 2
D 11
E 1

输出样例:

输出WPL。

WPL=67

 

参考代码:

// 创建一个哈夫曼树
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++)
    {
        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++)
    {
        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; // 定义字符串变量,用于存储编码
    code.reserve(MAX); // 预分配内存空间,提高性能

    // 遍历哈夫曼树,生成哈夫曼编码
    for (int i=0;i<n;i++)
    {
        code=""; // 清空字符串
        int curno=i; // 当前节点编号
        int f=ht[curno].parent; // 当前节点的父节点编号
        while (f!=-1) // 当父节点不为根节点时
        {
            if (ht[f].lchild==curno) // 如果父节点的左子节点是当前节点
                code='0'+code; // 在编码前添加0
            else // 如果父节点的右子节点是当前节点
                code='1'+code; // 在编码前添加1
            curno=f; // 更新当前节点编号
            f=ht[curno].parent; // 更新父节点编号
        }
        htcode[ht[i].data]=code; // 将哈夫曼编码存入哈希表
    }
}

  • 9
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值