三、实验代码与注释

# 定义 HuffmanNode 类,用于构建 Huffman 树
class HuffmanNode:
    def __init__(self, weight, value=None):
        self.weight = weight  # 节点权重,即信源符号的概率
        self.value = value  # 节点存储的值,即信源符号本身
        self.left = None  # 左子节点
        self.right = None  # 右子节点
        self.code = ''  # 存储该节点对应的编码

# 定义 HuffmanTree 类,用于构建 Huffman 树并生成编码
class HuffmanTree:
    def __init__(self, weights):
        self.weights = weights  # 存储信源符号及其概率
        self.root = None  # Huffman 树的根节点
        self.codes = {}  # 存储每个信源符号的编码

    # 构建 Huffman 树
    def build_tree(self):
        nodes = [HuffmanNode(weight[1], weight[0]) for weight in self.weights]  # 初始化节点列表
        while len(nodes) > 1:  # 当节点数目大于1时,继续构建 Huffman 树
            nodes.sort(key=lambda x: x.weight)  # 按权重从小到大排序
            left = nodes.pop(0)  # 取出权重最小的节点作为左子节点
            right = nodes.pop(0)  # 取出权重次小的节点作为右子节点
            new_node = HuffmanNode(left.weight + right.weight)  # 新节点的权重为左右子节点的权重之和
            new_node.left = left  # 将左子节点作为新节点的左子节点
            new_node.right = right  # 将右子节点作为新节点的右子节点
            nodes.append(new_node)  # 将新节点加入节点列表中
        self.root = nodes[0]  # 最后剩下的节点即为根节点

    # 生成编码
    def generate_code(self, node, code):
        if not node:  # 如果节点为空,则返回
            return
        if node.value:  # 如果节点存储了信源符号,则将该符号的编码存储到字典中
            self.codes[node.value] = code
            node.code = code
        self.generate_code(node.left, code + '0')  # 递归调用,生成左子节点的编码
        self.generate_code(node.right, code + '1')  # 递归调用,生成右子节点的编码

    # 打印生成的编码
    def print_code(self):
        print('Symbol	Weight	Code')
        for weight in self.weights:
            symbol = weight[0]
            w = weight[1]
            code = self.codes[symbol]
            print(f'{symbol}	{w}	{code}')

# 测试代码
if __name__ == '__main__':
    char_weights = [('a1', 4), ('a2', 2), ('a3', 2), ('a4', 1), ('a5', 1)]
    tree = HuffmanTree(char_weights)
    tree.build_tree()
    tree.generate_code(tree.root, '')
    tree.print_code()

注:以上代码中,用到了递归调用的方法来生成编码。递归调用的过程类似于深度优先搜索,先从根节点开始,沿着左子节点一直走到叶子节点,然后返回上一级节点,走右子节点,继续沿左子节点走到叶子节点,如此往复,直到遍历完整棵树。在递归调用的过程中,需要传递一个参数 code,用来记录当前节点所对应的编码。对于每个叶子节点,将其对应的信源符号及其编码存储到字典中,并将编码赋值给节点的 code 属性。最终,通过遍历字典,将信源符号、概率和编码输出到屏幕上。

Huffman 编码实现:Python 代码及注释

原文地址: https://www.cveoy.top/t/topic/oAPg 著作权归作者所有。请勿转载和采集!

免费AI点我,无需注册和登录