博主自己手撸的代码,若有有错误,感谢指出 直接上代码
目录
0 讲义
0.1 二元前缀码 0.2 平均传输位数 0.3 伪码 0.4 实例
1 代码
代码:计算平均位数
代码:哈夫曼编码
代码:生成哈夫曼树&主函数
哈夫曼编码是数据结构常考知识点,对比以前C写的代码,python真的简单易懂。
# 哈夫曼编码, 计算平均位数
def huffmanCode(root, tree, rootCode='', codeDict={}, depth=1, res=0):
# 一般情况下 root = {'left': ['a', 45], 'right': ['cbfed', 55]}
# 对左子树进行处理:如果是叶子节点,就打印编码;否则递归
if len(root['left'][0]) == 1:
codeDict[root['left'][0]] = '0'+ rootCode
res += (len(rootCode)+1) * root['left'][1] # 计算平均位数
else:
codeDict, res = huffmanCode(tree[root['left'][0]], tree, '0'+rootCode, codeDict, depth+1, res)
# 对右子树进行处理:如果是叶子节点,就打印编码;否则递归
if len(root['right'][0]) == 1:
codeDict[root['right'][0]] = '1'+ rootCode
res += (len(rootCode)+1) * root['right'][1] # 计算平均位数
else:
codeDict, res = huffmanCode(tree[root['right'][0]], tree, '1'+rootCode, codeDict, depth+1, res)
return codeDict, res
s = eval(input('若干字符:'))
w = eval(input('对应权重:'))
# 合并成一个字典
arr = [[s[i],w[i]] for i in range(len(s))]
# [['a', 45], ['b', 13], ['c', 12], ['d', 16], ['e', 9], ['f', 5]]
tree = {}
while len(arr)>1:
# 1 根据权重排序
arr.sort(key=lambda x:x[1])
# 2 选出最小的两个节点,分别作为左子树,右子树
l = arr[0] # 较小的作为左子树
r = arr[1] # 较大者作为右子树
if len(arr)>2:
tree[l[0]+r[0]] = {'left':l, 'right':r}
# 3 用新节点置换这两个节点
arr = arr[2:]
arr.append([l[0]+r[0], l[1]+r[1]])
else:
tree['root'] = {'left':l, 'right':r}
break
print('\n哈夫曼树:',tree)
code, res = huffmanCode(tree['root'], tree)
print('哈夫曼编码:',code)
print('平均传输位数:',res/sum(w))
"""
若干字符:'a','b','c','d','e','f'
对应权重:45,13,12,16,9,5
哈夫曼树: {
'fe': {'left': ['f', 5], 'right': ['e', 9]},
'cb': {'left': ['c', 12], 'right': ['b', 13]},
'fed': {'left': ['fe', 14], 'right': ['d', 16]},
'cbfed': {'left': ['cb', 25], 'right': ['fed', 30]},
'root': {'left': ['a', 45], 'right': ['cbfed', 55]}
}
哈夫曼编码: {
'a': '0',
'c': '001',
'b': '101',
'f': '0011',
'e': '1011',
'd': '111'}
平均传输位数: 2.24
"""