huffman

哈夫曼树

💫哈夫曼(Huffman)树又称为最优树,是一类带权路径长度最短的树

概念引进:

💥两个结点的路径:由树中一个结点到另一个结点的分支构成。

💟路径的长度:路径上的分支数目。

💨树的路径的长度:根节点到每个结点的路径的长度之和

完全二叉树就是这种路径长度最短的二叉树

❤结点的带权路径长度为从该结点到树根之间的路径长度与结点上的权值的乘积。

💓树的带权路径长度:树中所有叶子结点的带权路径长度之和,通常记作
W P L = ∑ i = 1 n w k l k , 其 中 n 为 树 中 结 点 的 数 目 , w k 为 第 k 个 结 点 上 的 权 值 , l k 为 第 k 个 结 点 的 路 径 长 度 WPL=\sum_{i=1}^nw_kl_k,其中n为树中结点的数目,w_k为第k个结点上的权值,\\l_k为第k个结点的路径长度 WPL=i=1nwklk,nwkklkk

1.最优二叉树(哈夫曼树)

​ 树的带权路径长度WPL最小的二叉树称为最优二叉树或者哈夫曼树

2.哈夫曼树的构造(哈夫曼算法)


1. 根 据 给 定 的 n 个 权 值 { w 1 , w 2 , . . . , w n } 构 成 n 棵 二 叉 树 的 集 合 F = { T 1 , T 2 , . . . , T n } , 其 中 每 棵 二 叉 树 T i 中 只 有 一 权 为 w i 的 根 节 点 , 七 左 右 子 树 为 空 。 2. 在 F 中 选 取 两 颗 权 值 最 小 的 二 叉 树 作 为 左 右 子 树 构 造 一 个 新 的 二 叉 树 , 新 二 树 的 根 结 点 的 权 值 为 其 左 右 子 树 根 结 点 权 值 之 和 。 3. 在 F 中 删 除 这 两 棵 树 , 同 时 将 这 棵 新 的 二 叉 树 加 入 到 F 中 4. 重 复 2 和 3 , 直 到 F 中 中 含 有 一 棵 树 为 止 1.根据给定的n个权值\{w_1,w_2,...,w_n\}构成n棵二叉树的集合F=\{T_1,\\T_2,...,T_n\},其中每棵二叉树T_i中只有一权为w_i的根节点,七左右子树为\\空。\\ 2.在F中选取两颗权值最小的二叉树作为左右子树构造一个新的二叉树,新二\\树的根结点的权值为其左右子树根结点权值之和。\\ 3.在F中删除这两棵树,同时将这棵新的二叉树加入到F中 4.重复2和3,直到\\F中中含有一棵树为止 1.n{w1,w2,...,wn}nF={T1,T2,...,Tn},Tiwi2.F3.FF4.23F
​ 由构造过程可知:哈夫曼树没有度为1的结点,所以一颗n个结点的哈夫曼树共由2n-1个结点

在这里插入图片描述

哈夫曼树的构造过程

代码:

const int max = 10000;
typedef struct HNode *HTree;
struct HNode {
    int weight;
    int ls,rs,parent;
}
HTree HuffmanTree(int w[],int n) {
    HTree root;
    if(n<=1) return NULL;
    int m = (n<<1)-1;
    root = (struct HNode*)malloc(m*sizeof(struct HNode));
    assert(root);
    for(int i=0;i<n;i++) {
        root[i].weight=w[i];
        root[i].parent = root[i].ls = root[i].rs = -1;
    }
    for(int i=n;i<m;i++) {
        root[i].weight=0;
        root[i].parent = root[i].ls = root[i].rs = -1;
    }
    int MAX1,MAX2,x1,x2;
    for(int i=n;i<m;i++) {
        MAX1 = MAX2 = INT_MAX;
        x1 = x2 = 0;
        for(int j=0;j<i;j++) {
            if(w[j]<MAX1&&root[j].parent==-1) {MAX2=MAX1;x2=x1;MAX1=root[j].weight;x1=j;}
        	else if(w[j]<MAX2&&root[j].parent==-1) {MAX2=root[j].weight;x2=j;}
        }
        root[x1].parent=i;root[x2].parent=i;
        root[i].ls=x1;root[i].rs=x2;
        root[i].weight=root[x1].weight+root[x2].weight;
    }
    return root;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值