• 【转】哈夫曼树 九度1172


    题目描述:

    哈夫曼树,第一行输入一个数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 
    明白了这一点,就可以直接排序,每次取数组中最小的两个数,然后相加,并累加,最终就得到了输出。代码如下:

     1 #include<iostream>
     2 #include<algorithm>
     3 using namespace std;
     4 int main(){
     5     int n;
     6     int result = 0; //表示最后的结果,即3+5+10+19
     7     int node[1000] = { 0 };
     8     scanf("%d", &n);
     9     for(int i=0; i<n; i++){
    10         scanf("%d", &node[i]);
    11     }
    12     for (int i = 0; i < n - 1; i++){
    13         int sum = 0; //临时存储最小的两个数的和
    14         sort(node + i, node + n);
    15         sum = node[i] + node[i + 1];
    16         result += sum;
    17         node[i + 1] = sum;
    18     }
    19     printf("%d
    ", result);
    20     return 0;
    21 }

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

     1 #include<iostream>
     2 using namespace std;
     3 struct huffman{
     4     int weight;
     5     int parent, lchild, rchild;
     6 };
     7 int main(){
     8     struct huffman node[2000];
     9     int n, result = 0;
    10     int x1, x2, m1 = -1, m2 = -1; //x1,x2分别表示最小和次小的权值,m1,m2分别表示最小和次小的节点编号
    11     scanf("%d", &n);
    12     for (int i = 0; i < 2*n; i++){  //只需要初始化前2n个结构体就行,因为节点就2*n-1个
    13                                      //二叉树中,叶子节点的个数比度为2的节点的个数多1个
    14         node[i].parent = node[i].lchild = node[i].rchild = -1; //初始化
    15     }
    16     for (int i = 0; i < n; i++){
    17         scanf("%d", &node[i].weight);
    18     }
    19     for (int i = 0; i < n - 1; i++){
    20         x1 = 101, x2 = 101;    //注意每次循环前都要重新赋值,这里我开始就弄错了
    21         for (int j = 0; j < n + i; j++){  //每次都会增加一个节点,在没有parent的节点中找最小的和次小的
    22             if (node[j].weight < x1 && node[j].parent == -1){ //如果当前weight比最小的小,就替换,同时更新次小的
    23                 x2 = x1;
    24                 m2 = m1;
    25                 x1 = node[j].weight;
    26                 m1 = j;
    27             }
    28             else if (node[j].weight < x2 && node[j].parent == -1){
    29                 x2 = node[j].weight;
    30                 m2 = j;
    31             }
    32         }//经过这次循环,找到了最小和次小
    33         node[n + i].weight = x1 + x2;  //这五行是建树,将最小的两个相加,增加新节点
    34         node[n + i].lchild = m1;
    35         node[n + i].rchild = m2;
    36         node[m1].parent = n + i;
    37         node[m2].parent = n + i;
    38         result += node[n + i].weight;
    39     }
    40     printf("%d
    ", result);
    41     return 0;
    42 }
  • 相关阅读:
    Java集合
    java多线程
    IO学习笔记
    在阿里云服务器上部署项目失败的原因
    购买阿里云服务器学生机
    使用gitee创建个人的图床
    idea中springboot热部署(无需重启项目)
    Springboot实现验证码登录
    getAddress和getHostAddress的区别
    泛型学习第一天:List与IList的区别 (三)
  • 原文地址:https://www.cnblogs.com/hss-521/p/7239122.html
Copyright © 2020-2023  润新知