Huffman编码-python代码实现
统计编码:根据信源的概率分布进行可变长编码,使平均码长接近熵。
Huffman编码是一种统计编码,是消除编码冗余常用的技术。它的基本原理是按照信源符号出现概率的大小进行排序,概率大的分配短码,概率小的分配长码。
Huffman编码算法
1:将信源符号按照出现概率从小到大排序,记为p1>=p2>=…>=p{m-1}>=p{m}
2:给最小的概率赋予符号1,倒数第二小的概率赋予符号0
3:计算联合概率pi=p{m-1}+p{m},将未处理的m-2个概率与pi一起重新排序
4:重复步骤1~3,直到所有的概率都被赋予了一个符号为止
附上源码:
Huffman编码实现:huffman_code.py
import math
#节点类
class Node:
def __init__(self, value):
self.value = value
self.prev = None
self.left = None
self.right = None
def is_left(self):
return self.prev.left == self
#每一个节点赋值,调用Node类默认方法初始化
def set_value(values):
nodes = [Node(value) for value in values]
return nodes
#创建哈夫曼树
def create_huffman_tree(nodes):
nodes_huf = nodes[:]
while len(nodes_huf) != 1:
nodes_huf.sort(key=lambda object: object.value)
#自底向上构造树
node_left = nodes_huf.pop(0)
node_right = nodes_huf.pop(0)
node_prev = Node(node_left.value + node_right.value)
node_prev.left = node_left
node_prev.right = node_right
node_left.prev = node_prev
node_right.prev = node_prev
nodes_huf.append(node_prev)
nodes_huf[0].prev = None
return nodes_huf[0] #概率之和1
#哈夫曼编码
def huffman_encoding(nodes, node_huf):
codes = [''] * len(nodes)
for i in range(len(nodes)):
node_tmp = nodes[i]
while node_tmp != node_huf:
if node_tmp.is_left():
codes[i] = '1' + codes[i]
else:
codes[i] = '0' + codes[i]
#从底向上查找
node_tmp = node_tmp.prev
return codes
#哈夫曼解码
def huffman_decoding(code, node_huf):
node_tmp = node_huf
for i in range(len(code)):
if node_tmp.left != 0:
if code[i] == '1': #容易写成数字1
node_tmp = node_tmp.left
else:
node_tmp = node_tmp.right
return node_tmp.value
#计算平均码长
def average_code_length(values, codes):
a = 0.0
for i in range(len(codes)):
b = values[i] * len(codes[i])
a += b
return a
#理论最佳平均码长
def best_code_length(values):
a = 0.0
for i in range(len(values)):
b = values[i] * math.log(values[i], 2)
a -= b
return a
Huffman编码测试:test.py
import huffman_code
values = [0.40,0.18,0.10,0.10,0.07,0.06,0.05,0.04]
nodes = huffman_code.set_value(values)
nodes_huf = huffman_code.create_huffman_tree(nodes)
codes = huffman_code.huffman_encoding(nodes, nodes_huf)
print('{0} → {1}.'.format(values, codes))
# value = codes[2]
# decode = huffman_code.huffman_decoding(value, nodes_huf)
# print("'{0}' → {1}.".format(value, decode))
average_code_length = huffman_code.average_code_length(values, codes)
print('the average code length of Huffman coding is {0}.'.format(average_code_length))
best_code_length = huffman_code.best_code_length(values)
print('the best code length in theory is {0}.'.format(best_code_length))