注:本文结合递归思想求取哈夫曼树的WPL
Description |
对输入的一组权值,根据构造的哈夫曼树,计算其最小带权路径长度WPL。 |
Sample Input |
2 5 4 6 7 |
Sample Output |
54 |
Hint |
输出有换行 |
#include <bits/stdc++.h>
#define Maxnum 105
using namespace std;
// 链式存储
typedef struct BTnode
{
int data;
BTnode *lc, *rc;
} BTnode, *BTree;
void CreateHuff(BTree &HT, int *AR, int n)
{
BTnode *BR[n]; // 哈夫曼树组
for (int i = 0; i < n; i++)
{ // 初始化
BR[i] = new BTnode;
BR[i]->data = AR[i];
BR[i]->lc = NULL;
BR[i]->rc = NULL;
}
for (int i = 1; i < n; i++)
{ // 总共有n-1趟
int k1 = -1, k2; // 分别记录一趟的最小的两个结点
for (int j = 0; j < n; j++)
{ // 更新k1,k2为前两个不为空的结点
if (BR[j] != NULL && k1 == -1)
{
k1 = j;
continue;
}
if (BR[j] != NULL)
{
k2 = j;
break;
}
}
for (int j = k2; j < n; j++)
{ // 找到前两个最小的结点并记录
if (BR[j] != NULL)
{
if (BR[j]->data < BR[k1]->data)
{ // 要满足左小右大
k2 = k1;
k1 = j;
}
else if (BR[j]->data < BR[k2]->data)
{
k2 = j;
}
}
}
HT = new BTnode;
HT->data = BR[k1]->data + BR[k2]->data; // 父亲结点为左右两孩的和
HT->lc = BR[k1]; // 满足左小右大
HT->rc = BR[k2];
BR[k1] = HT; // 初始化更新BR树组
BR[k2] = NULL;
}
}
int WPL(BTree HT, int len)
{
if (HT == NULL)
{
return 0;
}
else
{
if (HT->lc == NULL && HT->rc == NULL)
{ // 说明HT的左孩和右孩为叶子结点
return HT->data * len; // 就拿值乘以路长
}
else
{ // 如果不是叶子结点,就递归左子树和右子树求叶子结点*路径长度
return WPL(HT->lc, len + 1) + WPL(HT->rc, len + 1); // 并且路长要加一
}
}
}
int main()
{
BTree HT = new BTnode;
int num, i = 0, arr[Maxnum];
char ch;
while (cin >> num)
{
arr[i] = num;
i++; // 后移并记录长度
ch = getchar();
if (ch == '\n')
break;
}
CreateHuff(HT, arr, i); // 建树
cout << WPL(HT, 0) << "\n"; // 路径长度从0开始
}