霍夫曼编码最简单的实现

    前两天发布那个rsync算法后,想看看数据压缩的算法,知道一个经典的压缩算法Huffman算法。相信大家应该听说过 David Huffman 和他的压缩算法—— Huffman Code,一种通过字符出现频率,Priority Queue,和二叉树来进行的一种压缩算法,这种二叉树又叫Huffman二叉树 —— 一种带权重的树。从学校毕业很长时间的我忘了这个算法,但是网上查了一下,中文社区内好像没有把这个算法说得很清楚的文章,尤其是树的构造,而正好看到一篇国外的文章《A Simple Example of Huffman Code on a String》,其中的例子浅显易懂,相当不错,我就转了过来。注意,我没有对此文完全翻译。

我们直接来看示例,如果我们需要来压缩下面的字符串:

 “beep boop beer!” 

首先,我们先计算出每个字符出现的次数,我们得到下面这样一张表 :

          

     然后,我把把这些东西放到Priority Queue中(用出现的次数据当 priority),我们可以看到,Priority Queue 是以Prioirry排序一个数组,如果Priority一样,会使用出现的次序排序:下面是我们得到的Priority Queue:

      接下来就是我们的算法——把这个Priority Queue 转成二叉树。我们始终从queue的头取两个元素来构造一个二叉树(第一个元素是左结点,第二个是右结点),并把这两个元素的priority相加,并放回Priority中(再次注意,这里的Priority就是字符出现的次数),然后,我们得到下面的数据图表:

    

      同样,我们再把前两个取出来,形成一个Priority为2+2=4的结点,然后再放回Priority Queue中 :

      

       继续我们的算法(我们可以看到,这是一种自底向上的建树的过程):

            

      

        

     最终我们会得到下面这样一棵二叉树:

      此时,我们把这个树的左支编码为0,右支编码为1,这样我们就可以遍历这棵树得到字符的编码,比如:‘b’的编码是 00,’p’的编码是101, ‘r’的编码是1000。我们可以看到出现频率越多的会越在上层,编码也越短,出现频率越少的就越在下层,编码也越长。

最终我们可以得到下面这张编码表:

                          

      这里需要注意一点,当我们encode的时候,我们是按“bit”来encode,decode也是通过bit来完成,比如,如果我们有这样的bitset “1011110111″ 那么其解码后就是 “pepe”。所以,我们需要通过这个二叉树建立我们Huffman编码和解码的字典表。

     这里需要注意的一点是,我们的Huffman对各个字符的编码是不会冲突的,也就是说,不会存在某一个编码是另一个编码的前缀,不然的话就会大问题了。因为encode后的编码是没有分隔符的。

    于是,对于我们的原始字符串  beep boop beer!

    其对就能的二进制为 : 0110 0010 0110 0101 0110 0101 0111 0000 0010 0000 0110 0010 0110 1111 0110 1111 0111 0000 0010 0000 0110 0010 0110 0101 0110 0101 0111 0010 0010 0001

   我们的Huffman的编码为: 0011 1110 1011 0001 0010 1010 1100 1111 1000 1001

   从上面的例子中,我们可以看到被压缩的比例还是很可观的。

   编写代码实现:实现结果与图示结果不一样的原因是次数出现了重复。

   代码CSDN下载地址:https://download.csdn.net/download/u013915688/10645042

          

  • 3
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
可以使用霍夫曼编码实现字符统计。霍夫曼编码是一种可变长度编码方式,根据字符出现的频率来分配较短的编码给出现频率较高的字符,以此来达到压缩数据的目的。 下面是一个简单的示例代码,实现了字符统计和霍夫曼编码/解码功能: ```python import heapq from collections import defaultdict # 定义节点类 class Node: def __init__(self, char, freq): self.char = char self.freq = freq self.left = None self.right = None # 定义小于运算符,用于堆排序 def __lt__(self, other): return self.freq < other.freq # 统计字符频率 def count_freq(text): freq_dict = defaultdict(int) for char in text: freq_dict[char] += 1 return freq_dict # 构建霍夫曼树 def build_huffman_tree(freq_dict): heap = [] for char, freq in freq_dict.items(): node = Node(char, freq) heapq.heappush(heap, node) while len(heap) > 1: left_child = heapq.heappop(heap) right_child = heapq.heappop(heap) parent_freq = left_child.freq + right_child.freq parent = Node(None, parent_freq) parent.left = left_child parent.right = right_child heapq.heappush(heap, parent) return heapq.heappop(heap) # 生成霍夫曼编码字典 def build_huffman_codes(node, code, huffman_codes): if node.char is not None: huffman_codes[node.char] = code else: build_huffman_codes(node.left, code + '0', huffman_codes) build_huffman_codes(node.right, code + '1', huffman_codes) # 编码文本 def encode_text(text, huffman_codes): encoded_text = '' for char in text: encoded_text += huffman_codes[char] return encoded_text # 解码文本 def decode_text(encoded_text, huffman_tree): decoded_text = '' node = huffman_tree for bit in encoded_text: if bit == '0': node = node.left else: node = node.right if node.char is not None: decoded_text += node.char node = huffman_tree return decoded_text # 示例用法 def main(): text = "hello world" freq_dict = count_freq(text) huffman_tree = build_huffman_tree(freq_dict) huffman_codes = {} build_huffman_codes(huffman_tree, '', huffman_codes) encoded_text = encode_text(text, huffman_codes) decoded_text = decode_text(encoded_text, huffman_tree) print("原始文本:", text) print("编码后:", encoded_text) print("解码后:", decoded_text) if __name__ == "__main__": main() ``` 这段代码将输入的文本进行字符统计,然后构建霍夫曼树,并生成霍夫曼编码。最后,使用生成的霍夫曼编码对文本进行编码和解码操作。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值