哈夫曼树
💫哈夫曼(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=1∑nwklk,其中n为树中结点的数目,wk为第k个结点上的权值,lk为第k个结点的路径长度
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}构成n棵二叉树的集合F={T1,T2,...,Tn},其中每棵二叉树Ti中只有一权为wi的根节点,七左右子树为空。2.在F中选取两颗权值最小的二叉树作为左右子树构造一个新的二叉树,新二树的根结点的权值为其左右子树根结点权值之和。3.在F中删除这两棵树,同时将这棵新的二叉树加入到F中4.重复2和3,直到F中中含有一棵树为止
由构造过程可知:哈夫曼树没有度为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;
}