- 建立一个哈夫曼树的过程,核心思想在于找出集合中最小和次小的两个元素从集合中删除并将其构建为二叉树的左右孩子,然后将其data域值相加得到一个新的元素插入原来的集合中继续找最小和次小元素重复操作,但是如果上一次插入的元素并不是新找到的最小元素和次小元素之一,我们就得新建立一个子树。
而计算WPL也是相对简单的,核心代码必须要求得每个节点在哈夫曼树中的深度,只需要从节点开始,依次访问双亲节点,直到双亲节点为空或者0,再依次相乘相加即可。
#include<iostream>
#include<stack>
#include<queue>
using namespace std;
#define MAX 100
int arr[MAX][MAX];
int flag[MAX];
struct HT
{
int data;
int parent,lchild,rchild;
};
void selectmin(HT arr[], int& s1, int& s2,int n)
{
int min=-1000;
for (int i = 1; i <= n; i++)
{
if (arr[i].parent == 0)
{
min = i;
break;
}
}
for (int j = 1; j <= n; j++)
{
if(arr[j].parent==0)
if (arr[j].data < arr[min].data)
min = j;
}
s1 = min;
for (int i = 1; i <= n; i++)
{
if (arr[i].parent == 0 && i!=s1)
{
min = i;
break;
}
}
for (int j = 1; j <= n; j++)
{
if(arr[j].parent==0 && j!=s1)
if (arr[j].data < arr[min].data)
min = j;
}
s2 = min;
}
int finddeep(HT t[],HT a)
{
int cnt = 0,flag=1;
HT b = a;
while (b.parent)
{
cnt++;
b = t[b.parent];
}
return cnt;
}
int findWPL(HT t[],int n)
{
int cnt = 0;
for (int i = 1; i <= n; i++)
{
cnt += finddeep(t, t[i]) * t[i].data;
cout << t[i].data << "的带权路径值:" << finddeep(t, t[i]) * t[i].data << endl;
}
return cnt;
}
void createHT(int n)
{
int m = 2 * n - 1,s1,s2;
HT *p = new HT[m+1];
for (int i = 1; i <= m; i++)
{
p[i].lchild = 0;
p[i].rchild = 0;
p[i].parent = 0;
}
cout << "输入各个节点的权值:";
for (int i = 1; i <= n; i++)
{
cin>>p[i].data;
}
for (int i = n + 1; i <= m; i++)
{
selectmin(p, s1, s2, i-1);
p[s1].parent = i;
p[s2].parent = i;
p[i].lchild = s1;
p[i].rchild = s2;
p[i].data = p[s1].data + p[s2].data;
}
cout << "WPL值为:" << findWPL(p, n)<<endl;
}
int main()
{
int n;
cout << "请输入哈夫曼树的节点数:";
cin >> n;
createHT(n);
return 0;
}