压缩算法,哈夫曼编码,字符串压缩

哈夫曼编码是一种常用的无损压缩算法,它通过构建最优前缀编码来实现数据的压缩。哈夫曼编码的原理是根据符号出现的频率来构建一个最优的二叉树(哈夫曼树),并将出现频率高的符号用较短的编码表示,出现频率低的符号用较长的编码表示。

步骤:
统计输入数据中每个符号的出现频率。
根据频率构建哈夫曼树。首先创建一个包含所有符号的叶子节点集合,每个节点的权重为符号的频率。然后重复以下步骤直到只剩下一个根节点:
从节点集合中选择两个权重最小的节点,作为左右子节点创建一个新的父节点。
将新节点的权重设为左右子节点权重之和。
将新节点加入节点集合。
从节点集合中删除原先选出的两个节点。
根据哈夫曼树为每个符号分配唯一的编码。从根节点出发,沿着左子树走为0,沿着右子树走为1,记录下路径上的0和1即为符号的编码。
使用生成的编码对输入数据进行压缩。将每个符号替换为对应的编码。
将压缩后的数据以及编码表(记录每个符号的编码)一起保存,以便解压缩时使用。

from heapq import heapify, heappush, heappop
from collections import defaultdict


def build_huffman_tree(freq_dict):
    """构建哈夫曼树"""
    heap = [[freq, [char, ""]] for char, freq in freq_dict.items()]
    heapify(heap)

    while len(heap) > 1:
        lo = heappop(heap)
        hi = heappop(heap)
        for pair in lo[1:]:
            pair[1] = '0' + pair[1]
        for pair in hi[1:]:
            pair[1] = '1' + pair[1]
        heappush(heap, [lo[0] + hi[0]] + lo[1:] + hi[1:])

    return sorted(heappop(heap)[1:], key=lambda x: (len(x[-1]), x))


def encode(data):
    """对数据进行哈夫曼编码"""
    freq_dict = defaultdict(int)
    for char in data:
        freq_dict[char] += 1

    huffman_tree = build_huffman_tree(freq_dict)
    encoding_dict = dict(huffman_tree)

    encoded_data = ""
    for char in data:
        encoded_data += encoding_dict[char]

    return encoded_data, encoding_dict


def decode(encoded_data, encoding_dict):
    """对哈夫曼编码进行解码"""
    decoding_dict = {v: k for k, v in encoding_dict.items()}

    decoded_data = ""
    code = ""
    for bit in encoded_data:
        code += bit
        if code in decoding_dict:
            decoded_data += decoding_dict[code]
            code = ""

    return decoded_data


data = "mississippi river"
encoded_data, encoding_dict = encode(data)
decoded_data = decode(encoded_data, encoding_dict)

print("原始数据:", data)
print("编码后的数据:", encoded_data)
print("解码后的数据:", decoded_data)

原始数据: mississippi river
编码后的数据: 11101110100000111011110110011101100000010111110101
解码后的数据: mississippi river