构造哈夫曼树,计算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; // 将哈夫曼编码存入哈希表
}
}