huffman编码【python,编码,算法】

27 篇文章 0 订阅
1 篇文章 0 订阅

哈夫曼编码(Huffman Coding),又称霍夫曼编码,是一种编码方式,哈夫曼编码是可变字长编码(VLC)的一种。该方法完全依据字符出现概率来构造整体平均长度最短的码字,有时称之为最佳编码,一般就叫做Huffman编码(有时也称为霍夫曼编码)。

霍夫曼编码的主要步骤如下:

  1. 根据文本内容,进行字符频次统计。
  2. 根据频次统计字典,构建霍夫曼树。
    • 树的左节点值小于等于右边节点的频次。
    • 对于频次相同的字符采用路径深度优先原则,即相同频次的节点,路径深度小的放在左边节点。
    • 非叶子节点的值等于两个子节点的频次之和。
  3. 根据霍夫曼树得到霍夫曼编码字典。
    • 左边路径的值定义为 0,右边路径的值定义为 1。
    • 从根节点开始遍历到达叶子节点,将经过的路径值按照遍历顺序连接起来就是单个字符的编码值。
  4. 根据编码字典对文本按照顺序进行编码。

示例代码如下:

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用于对编码字符串进行解码。

注意,你可以根据实际情况替换上述代码中的测试数据。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值