1、哈夫曼树, 即带权路径最小的树, 权值最小的结点远离根结点, 权值越大的结点越靠近根结点:
2、简单介绍完原理,我们来看这个实现:
# 哈夫曼编码字典(键为字母,值为编码)
codeDic = {}
# 树节点类构建
class TreeNode(object):
def __init__(self, data):
self.val = data[0]
self.priority = data[1]
self.leftChild = None
self.rightChild = None
self.code = ""
# 创建树节点队列函数
def creatnodeQ(codes):
q = []
for code in codes:
q.append(TreeNode(code))
return q
# 为队列添加节点元素,并保证优先度从大到小排列
def addQ(queue, nodeNew):
if len(queue) == 0:
return [nodeNew]
for i in range(len(queue)):
if queue[i].priority >= nodeNew.priority:
return queue[:i] + [nodeNew] + queue[i:]
return queue + [nodeNew]
# 节点队列类定义
class nodeQeuen(object):
def __init__(self, code):
self.que = creatnodeQ(code)
self.size = len(self.que)
def addNode(self,node):
self.que = addQ(self.que, node)
self.size += 1
def popNode(self):
self.size -= 1
return self.que.pop(0)
# 各个字符在字符串中出现的次数,即计算优先度
def freChar(string):
d ={}
for c in string:
if not c in d:
d[c] = 1
else:
d[c] += 1
return sorted(d.items(),key=lambda x:x[1])
# 创建哈夫曼树
def creatHuffmanTree(nodeQ):
while nodeQ.size != 1:
node1 = nodeQ.popNode()
node2 = nodeQ.popNode()
r = TreeNode([None, node1.priority+node2.priority])
r.leftChild = node1
r.rightChild = node2
nodeQ.addNode(r)
return nodeQ.popNode()
# 由哈夫曼树得到哈夫曼编码表
def HuffmanCodeDic(head, x):
global codeDic, codeList
if head:
HuffmanCodeDic(head.leftChild, x+'0')
head.code += x
if head.val:
codeDic[head.val] = head.code
HuffmanCodeDic(head.rightChild, x+'1')
# 字符串编码
def TransEncode(string):
global codeDic
transcode = ""
for c in string:
transcode += codeDic[c]
return transcode
if __name__ == '__main__':
str = "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
t = nodeQeuen(freChar(str))
tree = creatHuffmanTree(t)
HuffmanCodeDic(tree, '')
print("哈夫曼编码如下:\n", codeDic)
print("原字符串为:\n", str)
a = TransEncode(str)
print("经哈夫曼编码转换后如下:", a)
3、这是编译结果
哈夫曼编码如下:
{'Y': '0000', 'Z': '0001', 'W': '0010',
'X': '0011', 'A': '0100', 'B': '0101',
'E': '01100', 'F': '01101', 'C': '01110',
'D': '01111', 'Q': '10000', 'R': '10001',
'O': '10010', 'P': '10011', 'U': '10100',
'V': '10101', 'S': '10110', 'T': '10111',
'I': '11000', 'J': '11001', 'G': '11010',
'H': '11011', 'M': '11100', 'N': '11101',
'K': '11110', 'L': '11111'}
原字符串为:
ABCDEFGHIJKLMNOPQRSTUVWXYZ
经哈夫曼编码转换后如下:
01000101011100111101100011011101011011110
00110011111011111111001110110010100111000
010001101101011110100101010010001100000001