📜  霍夫曼代码(1)

📅  最后修改于: 2023-12-03 15:28:52.729000             🧑  作者: Mango

霍夫曼编码

霍夫曼编码是一种压缩数据的方式,它利用出现频率较高的字符(或者说是信息量大的字符)用较短的编码表示,而用较长的编码表示出现频率较低的字符(或者说是信息量小的字符),这样就可以使得整个文本的编码长度变短,从而达到压缩数据的目的。

原理

霍夫曼编码是通过构建霍夫曼树来实现的。构建霍夫曼树的过程如下:

  1. 统计每个字符出现的频率
  2. 将所得到的频率信息构建出叶子节点,用频率作为权值
  3. 将这些叶子节点插入一个优先队列中(队列的优先级为权值,即频率越小,优先级越高)
  4. 取出权值最小的两个叶子节点,并构造出它们的父节点,其权值为两个子节点的权值之和
  5. 将该父节点插入优先队列中
  6. 重复步骤4和5,直到队列只剩下一个节点,这个节点就是霍夫曼树的根节点

得到霍夫曼树后,对每个叶子节点进行编码,可以使用任意长度的二进制位表示。为了保证编码的唯一性,霍夫曼编码规则是:从根节点到每个叶子节点的路径上标上0或1,每个叶子节点的编码就是由路径上经过的0和1组成的二进制串。

代码实现

下面是一个简单的实现霍夫曼编码的Python代码片段:

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

class Node:
    def __init__(self, freq, char=''):
        self.freq = freq
        self.char = char
        self.left = None
        self.right = None

    def __lt__(self, other):
        return self.freq < other.freq

class Huffman:
    def __init__(self):
        self.heap = []
        self.codes = {}
        self.reverse_mapping = {}

    def make_frequency_dict(self, text):
        frequency = defaultdict(int)
        for character in text:
            frequency[character] += 1

        return frequency

    def make_heap(self, frequency):
        for key in frequency:
            node = Node(frequency[key], key)
            heappush(self.heap, node)

    def merge_nodes(self):
        while len(self.heap) > 1:
            node1 = heappop(self.heap)
            node2 = heappop(self.heap)

            merged = Node(node1.freq + node2.freq)
            merged.left = node1
            merged.right = node2

            heappush(self.heap, merged)

    def make_codes_helper(self, root, current_code):
        if root is None:
            return

        if root.char != '':
            self.codes[root.char] = current_code
            self.reverse_mapping[current_code] = root.char
            return

        self.make_codes_helper(root.left, current_code + '0')
        self.make_codes_helper(root.right, current_code + '1')

    def make_codes(self):
        root = heappop(self.heap)
        current_code = ''
        self.make_codes_helper(root, current_code)

    def get_encoded_text(self, text):
        encoded_text = ''
        for character in text:
            encoded_text += self.codes[character]

        return encoded_text

    def pad_encoded_text(self, encoded_text):
        extra_padding = 8 - len(encoded_text) % 8
        for i in range(extra_padding):
            encoded_text += '0'

        padding_info = "{0:08b}".format(extra_padding)
        encoded_text = padding_info + encoded_text
        return encoded_text

    def get_byte_array(self, padded_encoded_text):
        if len(padded_encoded_text) % 8 != 0:
            print("Encoded text not padded properly")
            sys.exit(0)

        b = bytearray()
        for i in range(0, len(padded_encoded_text), 8):
            byte = padded_encoded_text[i:i+8]
            b.append(int(byte, 2))

        return b

    def compress(self, text):
        frequency = self.make_frequency_dict(text)
        self.make_heap(frequency)
        self.merge_nodes()
        self.make_codes()
        encoded_text = self.get_encoded_text(text)
        padded_encoded_text = self.pad_encoded_text(encoded_text)
        byte_array = self.get_byte_array(padded_encoded_text)

        return byte_array
总结

霍夫曼编码是一种常见的压缩数据的方式,它能够有效地减少数据的体积,提高数据传输的效率。在实现过程中,需要首先构建霍夫曼树,然后对每个叶子节点进行编码。虽然实现过程相对复杂,但是霍夫曼编码的原理和实现流程是非常重要而值得学习的。