哈夫曼编码是一种常用的无损压缩算法,它通过构建最优前缀编码来实现数据的压缩。哈夫曼编码的原理是根据符号出现的频率来构建一个最优的二叉树(哈夫曼树),并将出现频率高的符号用较短的编码表示,出现频率低的符号用较长的编码表示。
步骤:
统计输入数据中每个符号的出现频率。
根据频率构建哈夫曼树。首先创建一个包含所有符号的叶子节点集合,每个节点的权重为符号的频率。然后重复以下步骤直到只剩下一个根节点:
从节点集合中选择两个权重最小的节点,作为左右子节点创建一个新的父节点。
将新节点的权重设为左右子节点权重之和。
将新节点加入节点集合。
从节点集合中删除原先选出的两个节点。
根据哈夫曼树为每个符号分配唯一的编码。从根节点出发,沿着左子树走为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