您的位置:首页 > 其它

哈夫曼树 九度1172

2017-04-22 21:34 225 查看
题目描述:

哈夫曼树,第一行输入一个数n,表示叶结点的个数。需要用这些叶结点生成哈夫曼树,根据哈夫曼树的概念,这些结点有权值,即weight,题目需要输出所有结点的值与权值的乘积之和。


输入:

输入有多组数据。
每组第一行输入一个数n,接着输入n个叶节点(叶节点权值不超过100,2<=n<=1000)。


输出:

输出权值。


样例输入:

5
1 2 2 5 9


样例输出:

37


这个题可以建树也可以不建树。

不建树比较容易。首先要明确,题目要求输出的乘积之和,其实就是哈夫曼树中去除叶节点之外,其他节点的值的和。比如



题目要求意思是 1*4+2*4+2*3+5*2+9*1=37
其实可以直接 3+5+10+19=37
明白了这一点,就可以直接排序,每次取数组中最小的两个数,然后相加,并累加,最终就得到了输出。代码如下:

#include<iostream>
#include<algorithm>
using namespace std;
int main(){
int n;
int result = 0; //表示最后的结果,即3+5+10+19
int node[1000] = { 0 };
scanf("%d", &n);
for(int i=0; i<n; i++){
scanf("%d", &node[i]);
}
for (int i = 0; i < n - 1; i++){
int sum = 0; //临时存储最小的两个数的和
sort(node + i, node + n);
sum = node[i] + node[i + 1];
result += sum;
node[i + 1] = sum;
}
printf("%d\n", result);
return 0;
}


建哈夫曼树的话,其实也是每次计算最小的两个,然后把他们的和累加,建树反而比较麻烦,最终的计算也是 3+5+10+19=37。代码如下:

#include<i
4000
ostream>
using namespace std;
struct huffman{
int weight;
int parent, lchild, rchild;
};
int main(){
struct huffman node[2000];
int n, result = 0;
int x1, x2, m1 = -1, m2 = -1; //x1,x2分别表示最小和次小的权值,m1,m2分别表示最小和次小的节点编号
scanf("%d", &n);
for (int i = 0; i < 2*n; i++){  //只需要初始化前2n个结构体就行,因为节点就2*n-1个
//二叉树中,叶子节点的个数比度为2的节点的个数多1个
node[i].parent = node[i].lchild = node[i].rchild = -1; //初始化
}
for (int i = 0; i < n; i++){
scanf("%d", &node[i].weight);
}
for (int i = 0; i < n - 1; i++){
x1 = 101, x2 = 101;    //注意每次循环前都要重新赋值,这里我开始就弄错了
for (int j = 0; j < n + i; j++){  //每次都会增加一个节点,在没有parent的节点中找最小的和次小的
if (node[j].weight < x1 && node[j].parent == -1){ //如果当前weight比最小的小,就替换,同时更新次小的
x2 = x1;
m2 = m1;
x1 = node[j].weight;
m1 = j;
}
else if (node[j].weight < x2 && node[j].parent == -1){
x2 = node[j].weight;
m2 = j;
}
}//经过这次循环,找到了最小和次小
node[n + i].weight = x1 + x2;  //这五行是建树,将最小的两个相加,增加新节点
node[n + i].lchild = m1;
node[n + i].rchild = m2;
node[m1].parent = n + i;
node[m2].parent = n + i;
result += node[n + i].weight;
}
printf("%d\n", result);
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: