huffman树
哈夫曼树又称最优树。是一类带权路径长度最短的树
路径:树中从一个结点到另一个结点之间的分支构成的路径
路径长度:路径上分支的数目
树的路径长度:从树根到每一个结点的路径长度之和
权:赋予实体的一个量,对实体某个或某些属性的数值化。在数据结构中有结点权和边权。
结点的带权路径长度:该结点到根的路径长度和权值的乘积
树的带权路径长度(WPL):树中所有叶子结点的带权路径长度之和
哈夫曼树:存在m个权值{w1,w2…wm},可以构造一棵含n个叶子结点,每个结点的权值为wi的二叉树,且其中树的带权路径长度最小的二叉树被称为最优二叉树或哈夫曼树
下图的c图为哈夫曼树
哈夫曼树的构造
根据定义可知,WPL等于各个结点的路径长度和权值的乘积。要想WPL最小,那么如果保证了权值大的,它的路径长度设定小,乘积才会小,由此由各个结点保证为最小值来确定总体的最优解,是一种贪心法(局部最优解的集合代替整体最优解)。
构造思路:
(1)根据给定的n个权值{w1, w2,…, wn},构造一个有n棵只有对应权值根结点的二叉树的森林。
(2)在森林中选取两棵根结点的权值最小的树作为左右子树合并成一棵二叉树,且置新的二叉树的根结点的权值为其左、右子树上根结点的权值之和。
(3)重复(2),直到森林只含一棵树为止。这棵树便是哈夫曼树。
代码实现
核心函数实现
void Creat_huffman(Huffman_tree &T,int n) {
void Select(Huffman_tree T, int n, int& s1, int& s2); //选择最小权值
if (n <= 1)
return;
int m = 2 * n;
T = new Hnode[m]; //1~n存储初始的森林,n~2n-1存储新生成树的头结点
for (int i = 1; i < m; ++i) {
// 初始化
T[i].parent = 0;
T[i].lchild = 0;
T[i].rchild = 0;
}
for (int i = 1; i <= n; ++i) {
//输入m个权值构成森林
printf("输入第%d个结点的值\n", i);
scanf_s("%d", &T[i].data);
}
for (int i = n+1; i < m; ++i) {
//生成新的树
int s1, s2;
Select(T, i, s1, s2);
T[i].lchild = s1;
T[i].rchild = s2;
T[i].data = T[s1].data + T[s2].data;printf("%d,%d, %d\n", s1, s2,T[i].data);
T[s1].parent = T[s2].parent = i;
}
}
void Select(Huffman_tree T, int n, int& s1, int& s2) {
int min, min1, m;
min = min1 = m = 0;
for (int i = 1; i < n; ++i)