哈夫曼树 九度1172

来源:互联网 发布:淘宝联盟手机怎么推广 编辑:程序博客网 时间:2024/06/18 08:56

题目描述:

哈夫曼树,第一行输入一个数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<iostream>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;}
0 0
原创粉丝点击