[pta]哈夫曼树及编码

本文介绍了如何使用C++实现哈夫曼树的构造函数CreateHTree和生成哈夫曼编码的CreateHCode函数,以及计算WPL(WeightedPathLength)的方法。通过输入样例和优先队列操作构建哈夫曼树并计算其WPL值。
摘要由CSDN通过智能技术生成

构造哈夫曼树,计算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,用于存储编码
    code.reserve(MAX); // 预留空间,避免频繁扩容

    // 遍历哈夫曼树,生成哈夫曼编码
    for (int i=0;i<n;i++)
    {
        code=""; // 清空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; // 将编码存入哈夫曼编码表
    }
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值