#include <iostream>
#define N 50
#define M 2*N-1
using namespace std;
//哈夫曼树结点定义
typedef struct
{
string data;
int pd;
double weight;
int parent;
int lchild;
int rchild;
}HTNode;
//哈夫曼编码结点定义
typedef struct
{
char cd[N];
int start;
}HCode;
//创建哈夫曼树
void CreateHT(HTNode ht[], int n)
{
int i, k, lnode, rnode;
double min1, min2;//min1用于记录较小的那个结点,min2记录较大的那个
for (i = 0; i < 2 * n - 1; i++)//初始化结点
{
ht[i].parent = ht[i].lchild = ht[i].rchild = -1;
}
for (i = n; i < 2 * n - 1; i++)//开始构造哈夫曼树
{
min1 = min2 = INT_MAX;
lnode = rnode = -1;//记录可用的最小的两个结点的位置
for (k = 0; k <= i - 1; k++)//随着过程的进行,会加入两个选用结点构成的新结点,所以判断条件为k<=i-1
{
if (ht[k].parent == -1)//可用结点
{
if (ht[k].weight < min1)//比最小的那个结点更小
{
min2 = min1; rnode = lnode;//将较大结点换为较小结点
min1 = ht[k].weight; lnode = k;//较小结点更新
}
else if (ht[k].weight < min2)//只比较大结点小
{
min2 = ht[k].weight; rnode = k;//较大结点更新
}
}
}
ht[i].weight = ht[lnode].weight + ht[rnode].weight;//产生新节点
ht[i].lchild = lnode; ht[i].rchild = rnode;//记录新节点的孩子结点
ht[lnode].parent = i; ht[rnode].parent = i;//记录孩子结点的父亲
}
}
//求哈夫曼编码
void CreateHCode(HTNode ht[], HCode hcd[], int n)
{
int i, f, c;
HCode hc;
for (i = 0; i < n; i++)
{
hc.start = n; c = i;//从该节点倒着回到根结点,编码长度最大也不会超过n
f = ht[i].parent;
while (f != -1)//未回到根结点
{
if (ht[f].lchild == c)
hc.cd[hc.start--] = '0';
else
hc.cd[hc.start--] = '1';
c = f; f = ht[f].parent;
}
hc.start++;
hcd[i] = hc;
}
}
//输出哈夫曼编码
void DispHCode(HTNode ht[], HCode hcd[], int n)
{
int i, k;
int sum = 0, m = 0, j;//sum存储树的带权路径长度,m存储权和,j存储路径长度
//输出哈夫曼编码
cout << "单词"<<'\t'<<"频度"<<'\t'<<"哈夫曼编码"<<endl;
for (i = 0; i < n; i++)
{
j = 0;
cout << ht[i].data << '\t'<<ht[i].pd<<'\t';
for (k = hcd[i].start; k <= n; k++)//输出哈夫曼编码
{
cout << hcd[i].cd[k];
j++;//路径长度+1
}
m += ht[i].weight;
sum += ht[i].weight * j;
cout << endl;
}
}
int main()
{
int n = 15, i;
string str[] = { "The","of","a","to","and","in","that","he","is","at","on","for","His","are","be" };
int fnum[] = { 1192,677,541,518,462,450,242,195,190,181,174,157,138,124,123 };
HTNode ht[M];
HCode hcd[N];
for (i = 0; i < n; i++)
{
ht[i].data = str[i];
ht[i].pd = fnum[i];
ht[i].weight = fnum[i];
}
CreateHT(ht, n);//创建哈夫曼树
CreateHCode(ht, hcd, n);//求得哈夫曼编码
DispHCode(ht, hcd, n);//输出哈夫曼编码
return 0;
}
12-06
4216
08-21
740
11-08
7875