哈夫曼树构建原则:
- .统计频率:对待编码字符(或数据块)的频率进行统计。
- .初始化森林:将每个字符视为一棵只有根节点的二叉树,权值为频率。
- .合并树:重复以下操作,直到只剩一棵树:
- 选取权值最小的两棵树合并,新树的根节点权值为两者之和。
- 权值较小的树作为左子树,较大的为右子树(约定方向不影响结果)。
- 生成编码:从根节点出发,向左子树路径标记
0
,向右标记1
,到叶子节点的路径即为该字符的哈夫曼编码。
引用python模块说明:
heapq.heapify
是 heapq
模块(堆队列算法)的核心函数,用于将普通列表原地转换为最小堆数据结构。
import heapq# 原始未排序列表
data = [3, 1, 4, 1, 5, 9, 2, 6]
print("转换前:", data) # [3, 1, 4, 1, 5, 9, 2, 6]# 原地转换为最小堆
heapq.heapify(data)print("转换后:", data) # 输出可能: [1, 1, 2, 3, 5, 9, 4, 6]
print("最小元素:", data[0]) # 1 (始终是堆顶)
图示化:
1 ← 堆顶 (最小元素)
/ \
1 2
/ \ / \
3 5 9 4
/
6
import heapqclass Node:def __init__(self, char=None, freq=0, left=None, right=None):self.char = char # 字符(仅叶子节点有)self.freq = freq # 频率self.left = left # 左子节点self.right = right # 右子节点# 用于优先队列比较def __lt__(self, other):return self.freq < other.freqdef build_huffman_tree(freq_dict):heap = [Node(char=char, freq=freq) for char, freq in freq_dict.items()]heapq.heapify(heap) # 转为最小堆while len(heap) > 1:left = heapq.heappop(heap) # 弹出最小频率节点right = heapq.heappop(heap) # 弹出次小频率节点merged = Node(freq=left.freq + right.freq, left=left, right=right)heapq.heappush(heap, merged) # 合并后的树放回堆中,继续转为最小堆return heap[0] # 返回哈夫曼树的根节点def generate_codes(root, current_code="", code_dict={}):if root is None:returnif root.char is not None: # 叶子节点,则加入字典code_dict[root.char] = current_codegenerate_codes(root.left, current_code + "0", code_dict) #递归调用generate_codes(root.right, current_code + "1", code_dict) #递归调用return code_dict# 示例:压缩字符串 "aabbbcd"
freq = {'a': 2, 'b': 3, 'c': 1, 'd': 1}
huffman_tree = build_huffman_tree(freq)
codes = generate_codes(huffman_tree)
print("哈夫曼编码:", codes) # 输出如 {'b': '0', 'a': '10', 'c': '110', 'd': '111'}