Loading

<数据结构>XDOJ261.理解哈夫曼树

问题与解答

问题描述:
假设用于通信的电文由 n(2≤n≤30)个字符组成,字符在电文中出现的频度(权值)为 w1 w2… wn,根据该权值集合构造哈夫曼树,并计算该树的带权路径长度。
输入说明:
输入分为两行。第 1 行为 n 的值,第 2 行为 n 个整数(数值不超过 100),表示每个字符在电文中的频度。
整数之间以空格或换行符间隔。
输出说明:
输出一个整数,表示所构造哈夫曼树的带权路径长度,换行。
测试样例:
输入样例 1
5
4 5 2 10 8
输出样例 1
64

/*哈夫曼树的理解*/
#include<stdio.h>
#include<algorithm>
using namespace std;
int main()
{
    int n, A[30],i,sum=0;
    scanf("%d", &n);
    for(i = 0; i < n; i++)
        scanf("%d", &A[i]);
    sort(A, A+n);  //从小到大排序找出最小的两个结点
    for(i=1; i <= n-1; i++)
    {
        A[i] = A[i]+A[i-1]; //构造结点
        sum += A[i];          //构造的结点求和即可得出最短带权路径
        sort(A+i-1, A+n);   //将构造的结点重新加入数组等待下次比较
    }
    printf("%d",sum);
}

题后反思:非必要实现

一开始想要直接实现哈夫曼树,直接模拟题目过程。后来转念一想发现没有必要直接实现哈夫曼树,只要用数组排序就可以模拟实现求解带权路径长度的过程。

哈夫曼树

定义

  1. 带权路径和最小的树(最优二叉树)
  2. 带权路径和的两种计算方法
    • 定义计算
    • 构造的结点求和

算法实现

  1. 基本算法: 把结点按权值排序,选权值较小的两个结点合成一个新结点,然后重复上述操作,最终得到的树就是哈夫曼树。
  2. 核心问题:如何找到权值最小的两个结点---利用最小堆!!!
  3. 伪码实现
typedef struct TreeNode *HuffmanTree;
struct TreeNode
{
    int Weight;
    HuffumanTree Left, Right;
};

HuffumanTree Huffuman(MinHeap H)
{
    /* 假设H->Size个权值已经按照最小堆的顺序存放在 MInHeap里 */
    int i; HuffumanTree T;
    /* 做H->Size - 1 次合并 */
    for(i = 0; i < H->Size-1; i++)
    {
        T = malloc(sizeof(struct HuffumanTree));
        T->Left = Delete(H);
            /* 从最小堆中删除一个结点,作为新T的左子节点 */
        T->Right = Delete(H);
            /* 从最小堆中删除一个结点,作为新T的右子节点 */
        T->Weight = T->Left->Weight + T->Right->Weight;
            /* 重新计算权值 */
        Insert(T, H);
            /* 将新T插入最小堆 */
    }
    T = Delete(H);
    return T;
}
  1. 时间复杂度O(lgN)
posted @ 2021-11-22 23:30  咪啪魔女  阅读(193)  评论(0编辑  收藏  举报