最近数据结构课布置的作业:
用python实现哈夫曼树与哈夫曼编码,并撰写该大作业的实验报告。报告要求说明算法原理、算法的实现、测试案例说明、测试结果与分析。测试案例要求来源于日常生活或专业应用。
看了一些文章发现编码有点奇奇怪怪,于是就按自己的理解写了一遍。过程中曾试图用树遍历的方式进行哈夫曼编码,但是好像挺麻烦,还不如给结点加个parent属性,自底向上编码。
简单回顾下思路——
首先是树的构建,从一堆叶结点中找出俩权值最小的,同时创建新结点,新结点是俩叶结点的父结点,权值为俩权之和。然后从这堆叶结点中删去这俩,加入新结点,重复操作,直到只剩俩结点,然后将这俩结点连到树的根结点上,至此树的创建完毕。
其次是编码,从这堆叶结点里再次取出一个又一个叶结点p,初始编码code=’’,并且检测p.parent是不是root,如果不是,那么就检测p是p.parent的左还是右子结点,左就code = ‘0’ +code,右就code = ‘1’ + code,然后p = p.parent,继续重复上述检测;如果p.parent是root,那么输出code。
最后是应用,我用来存储DNA或RNA序列,具体可以看代码。
代码如下——
class node(object): #创建霍夫曼树结点类
def __init__(self):
self.name = None
self.weight = None
self.leftchild = None
self.rightchild = None
self.parent = None
class code_node(object): #创建编码结点类
def __init__(self, code, name, weight):
self.code = code
self.name = name
self.weight = weight
class HaffumanTree(object): #哈夫曼树类
def __init__(self):
self.root = node()
def buildtree(self, name_set, weight_set): #创建哈夫曼树
self.nodes = [] #以降序存储新结点
while len(name_set) > 0:
max_weight = max(weight_set)
max_pos = weight_set.index(max_weight)
max_name = name_set[max_pos]
newnode = node()
newnode.name = max_name
newnode.weight = int(max_weight) #权值为整型
self.nodes.append(newnode)
name_set.remove(max_name)
weight_set.remove(max_weight) #创建新结点,填入name和weight属性,且按降序入列
self.nodes_copy = self.nodes[:]
#备份self.nodes,用于自底向上编码,不能使用self.nodes_copy = self.nodes,这会导致两者始终同步
while len(self.nodes) > 2:
l = self.nodes.pop()
r = self.nodes.pop()
newnode = node()
newnode.weight = l.weight + r.weight
newnode.leftchild = l
newnode.rightchild = r
l.parent = newnode
r.parent = newnode
self.insert(newnode) #将新结点根据weight大小插入self.nodes
left = self.nodes.pop