目录标题
- 哈夫曼树
- 哈夫曼树的定义
- 哈夫曼树的构造
- 哈夫曼编码
- 哈夫曼树的实现
哈夫曼树
哈夫曼树的定义
- 路径:从一个结点到另一个结点的路线
- 树的路径长度:从树根到树中每个结点的路径长度之和
- 结点的权:在一些应用中,赋予树中结点的一个有某种意义的实数
- 结点的带权路径长度:结点到树根之间的路径长度与该结点权值的乘积
- 树的带权路径长度WPL:树中所有叶子结点的带权路径长度之和
WPL
=
∑
i
=
1
n
w
i
l
i
\text{WPL} = \sum_{i=1}^{n} w_i l_i
WPL=i=1∑nwili
- 其中,w是叶子结点的权值,n是叶子结点的个数,l是叶子结点到根的路径长度.
- 带权路径长度最小的二叉树称为最优二叉树.
哈夫曼树的构造
- 有n棵权值分别为w₁, w₂, …, wₙ的二叉树所组成的集合,这些二叉树的左右子树都为空
- 从集合中选取出权值最小的两棵二叉树构成一棵新的二叉树。为了保证新树仍是二叉树,需要增加一个新结点作为新二叉树的根,将所选的两棵子树作为其根结点的左右子树,并将其两个子树的权值之和作为其根的权值。从集合中删除已经选中的二叉树,将新生成的树加入集合中参与下一轮选择
- 重复上一步操作,直至集合中剩下最后一棵二叉树,这棵二叉树便是哈夫曼树
- 哈夫曼树的构造过程

- 上述哈夫曼树的WPL值情况:
W
P
L
=
5
×
2
+
1
×
3
+
4
×
3
+
7
×
2
+
9
×
2
=
57
WPL= 5×2+1×3+4×3+7×2+9×2=57
WPL=5×2+1×3+4×3+7×2+9×2=57
哈夫曼编码
- 一般地,设需要编码的字符集为{a₁, a₂, a₃, …, aₙ},各个字符出现的频率为{w₁, w₂, …, wₙ}。规定左分支为0,右分支为1,则从根结点到叶子结点经过的分支所组成的0和1字符串便是对应字符的编码,这就是哈夫曼编码。
- 示意图

哈夫曼树的实现
class Node(object):
def __init__(self, weight):
self.weight = weight
self.left = None
self.right = None
self.isNew = False
def __gt__(self, other):
"""用于对结点之间的排序"""
return self.weight > other.weight
class huffmanTree(object):
def __init__(self, nodeList):
self.WPL = 0
self.root = self.createHuffmanTree(nodeList)
def createHuffmanTree(self, nodeList):
"""
创建哈夫曼树
:param nodeList: 森林中的单个结点构成的二叉树
:return:
"""
while len(nodeList) > 1:
nodeList.sort()
left = nodeList.__getitem__(0)
right = nodeList.__getitem__(1)
newNode = Node(left.weight + right.weight)
newNode.isNew = True
newNode.left = left
newNode.right = right
nodeList.pop(0)
nodeList.pop(0)
nodeList.append(newNode)
return nodeList.__getitem__(0)
def calculate_WPL(self, node, level):
"""
计算哈夫曼树的wpl
:param node: 根结点
:param level: 层数
:return:
"""
if node != None:
if not node.isNew:
self.WPL += node.weight * level
self.calculate_WPL(node.left, level+1)
self.calculate_WPL(node.right, level+1)
if __name__ == "__main__":
print('PyCharm')
nodeList = []
nodeList.append(Node(1))
nodeList.append(Node(7))
nodeList.append(Node(4))
nodeList.append(Node(5))
nodeList.append(Node(9))
hufftree = huffmanTree(nodeList)
hufftree.calculate_WPL(hufftree.root, 0)
print("哈夫曼树的WPL:", hufftree.WPL)
