哈夫曼编码(Huffman Coding),又称霍夫曼编码,是一种编码方式,哈夫曼编码是可变字长编码(VLC)的一种。该方法完全依据字符出现概率来构造整体平均长度最短的码字,有时称之为最佳编码,一般就叫做Huffman编码(有时也称为霍夫曼编码)。
霍夫曼编码的主要步骤如下:
- 根据文本内容,进行字符频次统计。
- 根据频次统计字典,构建霍夫曼树。
- 树的左节点值小于等于右边节点的频次。
- 对于频次相同的字符采用路径深度优先原则,即相同频次的节点,路径深度小的放在左边节点。
- 非叶子节点的值等于两个子节点的频次之和。
- 根据霍夫曼树得到霍夫曼编码字典。
- 左边路径的值定义为 0,右边路径的值定义为 1。
- 从根节点开始遍历到达叶子节点,将经过的路径值按照遍历顺序连接起来就是单个字符的编码值。
- 根据编码字典对文本按照顺序进行编码。
示例代码如下:
from collections import Counter
from sortedcontainers import SortedList
# huffman 树的节点
class TreeNode:
def __init__(self, chr, frequency):
self.chr = chr
self.frequency = frequency
self.left = None
self.right = None
# 节点的路径长度
self.deep = 1
# 构建 huffman 树
def construct_huffman(plaintext):
# 统计频次
chars_freq = Counter(plaintext)
# 指定排序规则:从小到大排序,频次相同的节点,deep 值大的往后排
nodes = SortedList((TreeNode(k, v) for k, v in chars_freq.items()),
key=lambda x: x.frequency)
while len(nodes) > 1:
# 取出两个较小的节点
first_min_node = min(nodes, key=lambda x: (x.frequency, x.deep))
nodes.remove(first_min_node)
second_min_node = min(nodes, key=lambda x: (x.frequency, x.deep))
nodes.remove(second_min_node)
# 创建一个新节点
new_node = TreeNode("", first_min_node.frequency + second_min_node.frequency)
# 为新节点挂上左右叶子
new_node.left = first_min_node
new_node.right = second_min_node
# 更新新节点的深度
new_node.deep = max(first_min_node.deep, second_min_node.deep) + 1
# 将新节点插入到排序列表中
nodes.add(new_node)
return nodes.pop(0)
# 获取 huffman 编码字典
def get_huffman_code_dict(root):
code_dict = {}
# 递归获取编码
def get_code(node, code):
if not node:
return
if node.chr:
code_dict[node.chr] = code
return
get_code(node.left, code + "0")
get_code(node.right, code + "1")
get_code(root, "")
return code_dict
# huffman 编码
def huffman_encode(plaintext):
root = construct_huffman(plaintext)
code_dict = get_huffman_code_dict(root)
return "".join(code_dict.get(c) for c in plaintext), code_dict
# huffman 解码
def huffman_decode(ciphertext, code_dict):
result = []
while ciphertext:
for k, v in code_dict.items():
if ciphertext.startswith(v):
result.append(k)
ciphertext = ciphertext[len(v):]
break
return "".join(result)
# 测试
root = construct_huffman("编程语言,编程")
ciphertext, code_dict = huffman_encode("编程语言,编程")
print(code_dict)
print(ciphertext)
decode_text = huffman_decode("1001001000111001", code_dict)
print(decode_text)
上述代码定义了huffman_encode
函数用于对文本进行霍夫曼编码,函数返回编码的字符串和霍夫曼编码字典。函数huffman_decode
用于对编码字符串进行解码。
注意,你可以根据实际情况替换上述代码中的测试数据。