概念
路径长度: 树中从一个结点到另一个结点之间的分支数目。
树的路径长度: 树根到每一个结点的路径长度之和。
结点的带权路径长度: 从结点到树根之间的路径长度与结点上权的乘积。
树的带权路径长度: 树中所有叶子结点的带权路径长度之和。
W
P
L
=
∑
k
=
1
n
w
k
l
k
WPL= \sum_{k=1}^{n}{w_{k}l_{k}}
WPL=k=1∑nwklk
最优二叉树(哈夫曼树): WPL最小的二叉树
哈夫曼算法
(
1
)
根
据
给
定
的
n
个
权
值
{
w
1
,
w
2
,
.
.
.
,
w
n
}
构
成
二
叉
树
集
合
F
=
{
T
1
,
T
2
,
.
.
.
T
n
}
(1)根据给定的n个权值\{w_{1},w_{2},...,w_{n}\}构成二叉树集合F=\{T_{1},T_{2},...T_{n}\}
(1)根据给定的n个权值{w1,w2,...,wn}构成二叉树集合F={T1,T2,...Tn}
(2)在F中选取权值最小的两棵二叉树构成新的二叉树,并更新新二叉树的权值。
(3)在F中删除这两棵二叉树,并将新二叉树放入F中。
(4)重复(2)、(3)步直至只剩下一棵二叉树,即哈夫曼树。
数据结构
链表型
typedef struct HTCode{
char ch;//元素
int weight;//权重
HTCode* lChild, * rChild;//左右子树
bool isLeaf;//是否为叶子结点
}HTCode,*HuffmanTree;
由二叉树堆构建哈夫曼树
输入
HuffmanTree* heap;
cin >> N;
heap = new HuffmanTree[N];
weight = new int[N];
for (i = 0; i < N; i++)
heap[i] = new HTCode;
for (i = 0; i < N; i++)
{
cin >> heap[i]->ch >> heap[i]->weight;
heap[i]->lChild = NULL;
heap[i]->rChild = NULL;
}
从树堆中获取最小树
HuffmanTree GetMinTree(HuffmanTree* heap, int n)//从树堆中获取最小树
{
int minPos = 0, i;
HuffmanTree minTree = heap[0];
for (i = 0; i < n; i++)
if (heap[i]->weight < minTree->weight)
{
minTree = heap[i];
minPos = i;
}
for (i = minPos; i < n - 1; i++)
heap[i] = heap[i + 1];
return minTree;
}
构建哈夫曼树
HuffmanTree GetHuffmanTree(HuffmanTree* heap, int n)//由根节点树建立哈夫曼树
{
if (n == 1) return heap[0];
HuffmanTree min1, min2, newMin;
min1 = GetMinTree(heap, n);
min2 = GetMinTree(heap, n - 1);
newMin = new HTCode;
newMin->weight = min1->weight + min2->weight;
newMin->lChild = min1;
newMin->rChild = min2;
heap[n - 2] = newMin;
GetHuffmanTree(heap, n - 1);
}
获取哈夫曼树带权路径长度
int GetMinLength(HuffmanTree ht,int depth)//获取哈夫曼树带权路径长度
{
if (!ht->lChild && !ht->rChild)
return ht->weight * depth;
else
return GetMinLength(ht->lChild, depth + 1) + GetMinLength(ht->rChild, depth + 1);
}