python代码——树和二叉树
python代码——树和二叉树
原理可参考链接:https://blog.csdn.net/qq_32640443/article/details/109812861
生成二叉树:
"""构建结点类""" class BTNode(object): def __init__(self, val=None, lchild=None, rchild=None): self.val = val self.lchild = lchild self.rchild = rchild """构建二叉树类""" class BiTree(object): def __init__(self, data_list): #初始化,即将传入的列表的迭代器 self.it = iter(data_list) """ iter函数和next函数共同使用 next函数返回迭代器中的下一个项目,即遍历玩迭代器中的元素 """ def createBiTree(self, bt=None): """创建二叉树""" try: #获取下一个元素 next_data = next(self.it) #如果当前列表元素为'#', 则认为其为 None if next_data == "#": bt = None else: bt = BTNode(next_data) bt.lchild = self.createBiTree(bt.lchild) bt.rchild = self.createBiTree(bt.rchild) # 异常处理 except Exception as e: print(e) return bt def preOrderTrave(self, bt): """递归前序遍历""" if bt is not None: print(bt.val, end=" ") self.preOrderTrave(bt.lchild) self.preOrderTrave(bt.rchild) def preOrder_non_recursive(self, bt): """借助栈非递归前序遍历""" if bt == None: return stack = [] while bt or len(stack) > 0: if bt: stack.append(bt) print(bt.val, end=' ') bt = bt.lchild else: bt = stack[-1] stack.pop() bt = bt.rchild def inOrderTrave(self, bt): """递归中序遍历""" if bt is not None: self.inOrderTrave(bt.lchild) print(bt.val, end=" ") self.inOrderTrave(bt.rchild) def inOrder_non_recursive(self, bt): """借助栈非递归中序遍历""" if bt == None: return stack = [] while bt or len(stack) > 0: if bt: stack.append(bt) bt = bt.lchild else: bt = stack.pop() print(bt.val, end=' ') bt = bt.rchild def postOrderTrave(self, bt): """递归后序遍历""" if bt is not None: self.postOrderTrave(bt.lchild) self.postOrderTrave(bt.rchild) print(bt.val, end=" ") def postOrder_non_recursive(self, bt): """借助栈非递归后序遍历""" if bt == None: return stack1 = [] stack2 = [] stack1.append(bt) while stack1: node = stack1.pop() if node.lchild: stack1.append(node.lchild) if node.rchild: stack1.append(node.rchild) stack2.append(node) while stack2: print(stack2.pop().val, end=' ') return def tree_deep(self, root): """二叉树的深度""" if not root: return 0 left = self.tree_deep(root.lchild)+1 right = self.tree_deep(root.rchild)+1 return left if left>right else right def leave(self,root): """递归求二叉树结点数目""" if root == None: return 0 else: a = (1+self.leave(root.lchild)+self.leave(root.rchild)) return a def copy(self,root): """复制一棵树""" if not root: return NewTree = BTNode(root.val) NewTree.left = self.copy(root.lchild) NewTree.right = self.copy(root.rchild) return NewTree # 综合打印 def printTrave(self, bt): print("先序遍历: ", end="") self.preOrderTrave(bt) print('\n') print("先序遍历: ", end="") self.preOrder_non_recursive(bt) print('\n') print("中序遍历: ", end="") self.inOrderTrave(bt) print('\n') print("中序遍历: ", end="") self.inOrder_non_recursive(bt) print('\n') print("后序遍历: ", end="") self.postOrderTrave(bt) print('\n') print("后序遍历: ", end="") self.postOrder_non_recursive(bt) print('\n') print("二叉树的深度:",end="") print(self.tree_deep(bt)) print("二叉树的结点数:",end="") print(self.leave(bt)) print("复制该二叉树:",end="") print(self.copy(bt)) data = input("Please input the node value: ") data_list = list(data) btree = BiTree(data_list) root = btree.createBiTree() btree.printTrave(root)
中序线索化二叉树:
"""构建结点类""" class TreeNode(object): def __init__(self, val): self.val = val self.left = None self.right = None # 如果left_label==0 表示指向的是左子树,如果是1 则表示指向前驱结点 # 如果right_label==0 表示指向的是右子树,如果是1 怎表示指向后继结点 self.left_label = 0 # 注意这里必须写0,不能写空值 self.right_label = 0 """构建线索二叉树的类""" class ThreadedBinaryTree(object): def __init__(self): self.root = None # 在递归进行线索化,总是保留前一个结点 self.pre = None # 为实现线索化,需要创建给指向当前结点的前驱结点指针 def in_order(self, node): """二叉树中序遍历""" if node is None: return self.in_order(node.left) print(node.val, end=' ') self.in_order(node.right) def threaded_node(self, node): # node: 就是当前需要线索化的结点 """二叉树进行中序线索化""" #线索化的过程就是在遍历的过程中修改空指针的过程 if node is None: return # 先线索化左子树 self.threaded_node(node.left) # 线索化当前结点 # 处理当前结点的前驱结点 if node.left is None: # 如果当前结点左子结点为空 node.left = self.pre # 让当前结点的左指针指向前驱结点 node.left_label = 1 # 修改当前结点的左指针类型 为 前驱结点 # 处理当前结点的后继结点 if self.pre and self.pre.right is None: self.pre.right = node # 让前驱结点的右指针指向当前结点 self.pre.right_label = 1 # 修改前驱结点的右指针类型 self.pre = node # 每处理一个结点后,让当前结点是下一个结点的前驱结点 # 线索化右子树 self.threaded_node(node.right) def threaded_in_order(self, node): """中序遍历线索化二叉树""" if node is None: return temp_node = node while temp_node: # 循环的找到left_label=1的结点,第一个找到就是值为8的结点 # 后面随着遍历而变化,因为当left_label=1时,说明该结点是按照线索化处理后的有效结点 while temp_node.left_label == 0: # 从根结点开始向左找,找到第一个1停止 temp_node = temp_node.left # 打印当前这个结点 print(temp_node.val, end=" ") # 如果当前结点的右指针指向的是后继结点,就一直输出 while temp_node.right_label == 1: # 获取到当前结点的后继结点 temp_node = temp_node.right print(temp_node.val, end=" ") # 如果不等于1了,就替换这个遍历的结点 temp_node = temp_node.right """测试代码""" if __name__ == '__main__': t = ThreadedBinaryTree() # 手动创建结点--只是为了更好测试线索化有没有成功 t1 = TreeNode(1) t2 = TreeNode(3) t3 = TreeNode(6) t4 = TreeNode(8) t5 = TreeNode(10) t6 = TreeNode(14) t1.left = t2 t1.right = t3 t2.left = t4 t2.right = t5 t3.left = t6 print("原来的二叉树中序遍历为:") t.in_order(t1) # 线索化二叉树 t.threaded_node(t1) # 测试:以值为10 的结点来测试 left_node = t5.left print() print("10 的前驱结点是:%d" % left_node.val) # 3 right_node = t5.right print("10 的后继结点是:%d" % right_node.val) # 1 print("线索化二叉树的中序遍历结果为:") t.threaded_in_order(t1)
后序线索化二叉树:
class Node(object): def __init__(self, data): self.data = data self.left = None self.right = None self.is_left_thread = False self.is_right_thread = False self.parent = None def add(self, node): if self.data > node.data: if self.left is None: self.left = node node.parent = self else: self.left.add(node) else: if self.right is None: self.right = node node.parent = self else: self.right.add(node) class ThreadBinaryTree(object): def __init__(self): self.pre = None self.root = None def add(self, node): if self.root is None: self.root = node else: self.root.add(node) def post_order_thread(self, node): """ 后续线索化 :return: """ if node is None: return self.post_order_thread(node.left) self.post_order_thread(node.right) """ 1. left指向左子树或者指向前驱节点 2. right指向右子树或者后继节点 """ if node.left is None: node.left = self.pre node.is_left_thread = True if self.pre is not None and self.pre.right is None: self.pre.right = node self.pre.is_right_thread = True; self.pre = node def threaded_post_order(self): """ 后续遍历 :return: """ temp = self.root # 定位到树最左端 while temp.left is not None and temp.left.is_left_thread is False: temp = temp.left while temp is not None: # temp right 是后继节点 if temp.is_right_thread: print(temp.data, end='->') self.pre = temp temp = temp.right else: # 后继节点之后的那一颗 子树需要特殊处理 必须拿到该子树的父节点然后继续 if temp.right is self.pre: print(temp.data, end='->') self.pre = temp temp = temp.parent else: temp = temp.right while temp.left is not None and temp.is_left_thread is False: temp = temp.left if __name__ == '__main__': binary_tree = ThreadBinaryTree() for i in range(1, 8): binary_tree.add(Node(i)) binary_tree.post_order_thread(binary_tree.root) print('线索二叉树的后序遍历为:') binary_tree.threaded_post_order()
普通树转二叉树:
'''构造队列类''' class Queue(): # 初始化 def __init__(self): self.array = [] # 判断队列是否为空 def QueueEmpty(self): return self.array == [] # 入队,添加元素到队尾 def EnQueue(self, item): self.array.append(item) # 出队,删除队头元素 def DeQueue(self): return self.array.pop(0) # pop(0):删除第一个元素 # 清空队列 def clear(self): self.array = [] print("清空队列完成!")
'''普通树结点''' class CSNode(): def __init__(self, data, children): self.data = data # 结点中携带的数据 self.children = children # 当前结点的所有孩子集合 ## 二叉树结点 class BiNode(): def __init__(self): self.data = None # 结点中的数据 self.left = None # 左结点 self.right = None # 右结点 ## 创建普通树转为二叉树的类 class Tree(): # 初始化函数:普通树根结点,二叉树根结点,二叉树根结点数据 def __init__(self, root): self.root = root # 普通树的根结点 self.biroot = BiNode() # 初始化二叉树的根节点为空结点 self.biroot.data = self.root.data # 把普通树根结点的数据赋予二叉树根结点的数据 # 普通树转二叉树函数,结点之间的转换 def transform(self): queue = Queue() # 创建队列,存储普通树的结点 bqueue = Queue() # 创建队列,存储二叉树的结点 queue.EnQueue(self.root) # 先把普通树根结点放入普通树队列中 bqueue.EnQueue(self.biroot) # 把二叉树根结点放入二叉树队列中 former = BiNode() # former结点变量主要控制兄弟结点转为孩子结点 # 比如A结点有三个孩子BCD,上一步已经把A结点放入queue队列中,然后取出queue队列中的首元素,遍历孩子结点,然后将孩子结点放入队列中,再依次遍历孩子结点,直到没有结点遍历为止; # 每次都是先从队列中取结点,看是否有孩子结点,如果有,那就加进queue队列中,如果没有就不执行下面for循环,直到所有队列中的结点都取出完时,while循环停止! while not queue.QueueEmpty(): node = queue.DeQueue() # 目前队列中普通树根结点 bTreenode = bqueue.DeQueue() # 二叉树根结点 # 根据当前结点的孩子数,来进行遍历,如果i==0,表示为左侧第一个孩子,则作为二叉树的左结点,如果有i>0的兄弟结点,则依次作为上一结点的右结点 for i in range(len(node.children)): bnode = BiNode() # 创建空二叉树结点 bnode.data = node.children[i].data # 新结点数据等于普通树孩子结点数据 if i == 0: #i==0时,即把普通树的第一个孩子作为二叉树的左孩子 bTreenode.left = bnode else: # i>0时,后面的孩子结点作为前面结点的右孩子 former.right = bnode former = bnode # 将former结点表示为新结点所在位置 queue.EnQueue(node.children[i]) # 将普通树中的结点放入普通树队列中 bqueue.EnQueue(bnode) # 将新生成的二叉树结点放入二叉树队列中 return self.biroot # 当普通树所有结点都依次遍历完时,返回二叉树根结点,通过根结点依次遍历 # 前序遍历 def pre(self, node): #前序遍历、NLR、根左右 if node == None: return #print(node.data) print("结点:{}, 左结点:{}, 右结点:{}".format(node.data, None if node.left == None else node.left.data, None if node.right == None else node.right.data)) self.pre(node.left) self.pre(node.right)
''' 测试代码 ''' # 先创建普通树的结点 nodeG = CSNode('G', []) nodeF = CSNode('F', []) nodeE = CSNode('E', []) nodeD = CSNode('D', [nodeG]) nodeC = CSNode('C', []) nodeB = CSNode('B', [nodeE, nodeF]) nodeA = CSNode('A', [nodeB, nodeC, nodeD]) # 生成普通树转换为二叉树的一个类对象 bitree = Tree(nodeA) root = bitree.transform() # 普通树转二叉树函数 bitree.pre(root) # 二叉树的前序遍历
森林转二叉树:(类比普通树转二叉树)
## 普通树结点 class CSNode(): def __init__(self, data, children): self.data = data # 结点中携带的数据 self.children = children # 当前结点的所有孩子集合 ## 二叉树结点 class BiNode(): def __init__(self): self.data = None # 结点中的数据 self.left = None # 左结点 self.right = None # 右结点 ## 创建普通树转为二叉树的类 class Tree(): # 初始化函数:普通树根结点,二叉树根结点,二叉树根结点数据 def __init__(self, root): self.root = root # 普通树的根结点 self.biroot = BiNode() # 初始化二叉树的根节点为空结点 self.biroot.data = self.root.data # 把普通树根结点的数据赋予二叉树根结点的数据 # 普通树转二叉树函数,结点之间的转换 def transform(self): queue = Queue() # 创建队列,存储普通树的结点 bqueue = Queue() # 创建队列,存储二叉树的结点 queue.EnQueue(self.root) # 先把普通树根结点放入普通树队列中 bqueue.EnQueue(self.biroot) # 把二叉树根结点放入二叉树队列中 former = BiNode() # former结点变量主要控制兄弟结点转为孩子结点 # 比如A结点有三个孩子BCD,上一步已经把A结点放入queue队列中,然后取出queue队列中的首元素,遍历孩子结点,然后将孩子结点放入队列中,再依次遍历孩子结点,直到没有结点遍历为止; # 每次都是先从队列中取结点,看是否有孩子结点,如果有,那就加进queue队列中,如果没有就不执行下面for循环,直到所有队列中的结点都取出完时,while循环停止! while not queue.QueueEmpty(): node = queue.DeQueue() # 目前队列中普通树根结点 bTreenode = bqueue.DeQueue() # 二叉树根结点 # 根据当前结点的孩子数,来进行遍历,如果i==0,表示为左侧第一个孩子,则作为二叉树的左结点,如果有i>0的兄弟结点,则依次作为上一结点的右结点 for i in range(len(node.children)): bnode = BiNode() # 创建空二叉树结点 bnode.data = node.children[i].data # 新结点数据等于普通树孩子结点数据 if i == 0: #i==0时,即把普通树的第一个孩子作为二叉树的左孩子 bTreenode.left = bnode else: # i>0时,后面的孩子结点作为前面结点的右孩子 former.right = bnode former = bnode # 将former结点表示为新结点所在位置 queue.EnQueue(node.children[i]) # 将普通树中的结点放入普通树队列中 bqueue.EnQueue(bnode) # 将新生成的二叉树结点放入二叉树队列中 return self.biroot # 当普通树所有结点都依次遍历完时,返回二叉树根结点,通过根结点依次遍历 # 前序遍历 def pre(self, node): #前序遍历、NLR、根左右 if node == None: return print("结点:{}, 左结点:{}, 右结点:{}".format(node.data, None if node.left == None else node.left.data, None if node.right == None else node.right.data)) self.pre(node.left) self.pre(node.right) # 森林转二叉树函数 def forest_to_biTree(self, biroot_list): forest_root = self.root former = forest_root for i in range(1, len(biroot_list)): former.right = biroot_list[i] former = biroot_list[i] return forest_root # 当普通树所有结点都依次遍历完时,返回二叉树根结点,通过根结点依次遍历
二叉排序树:
"""定义结点""" class BiTreeNode: def __init__(self,data): self.data = data self.lchild = None # 左孩子 self.rchild = None # 右孩子 self.parent = None class BST: def __init__(self, li=None): self.root = None if li: for val in li: self.insert_no_rec(val) def insert(self, node, val): """递归插入""" if not node: node = BiTreeNode(val) elif val < node.data: node.lchild = self.insert(node.lchild, val) node.lchild.parent = node elif val > node.data: node.rchild = self.insert(node.rchild,val) node.rchild.parent = node return node def insert_no_rec(self, val): """非递归插入""" p = self.root if not p: # 如果p为空,特殊处理 self.root = BiTreeNode(val) return while True: if val < p.data: if p.lchild: p = p.lchild else: # 左孩子不存在 p.lchild = BiTreeNode(val) p.lchild.parent = p return elif val > p.data: if p.rchild: p = p.rchild else: p.rchild = BiTreeNode(val) p.rchild.parent = p else: return def query(self, node, val): """递归查询""" if not node: # 空树 return None if node.data < val: return self.query(node.rchild, val) elif node.data > val: return self.query(node.lchild, val) else: return node def query_no_rec(self, val): """非递归查询""" p = self.root while p: if p.data < val: p = p.rchild elif p.data > val: p = p.lchild else: return p return None """ 1、删除的节点是叶子节点:直接删除,即没有孩子 2、删除的节点只有一个孩子:将此节点的父亲与孩子连接,然后删除该节点 3、删除的节点有两个孩子:将其右子树的最小节点(该节点最多有一个右孩子)删除,并替换当前节点 """ def __remove_node_1(self, node): # 情况1:node是叶子节点 if not node.parent: # 表明树里就一个节点 self.root = None if node == node.parent.lchild: # node是它父亲的左孩子 node.parent.lchild = None # node.parent = None 因为断连了所以写不写这一句都可 else: #node是他父亲的右孩子 node.parent.rchild = None def __remove_node_21(self, node): # 情况2.1:node只有一个左孩子 if not node.parent: # node为根节点 self.root = node.lchild node.lchild.parent = None elif node == node.parent.lchild: # node为它父亲的左节点 node.parent.lchild = node.lchild # 它父亲的左孩子等于它的左孩子 node.lchild.parent = node.parent # 它左孩子的父亲等于它的父亲 else: # node为它父亲的右节点 node.parent.rchild =node.lchild node.lchild.parent = node.parent def __remove_node_22(self, node): # 情况2.2:node只有一个右孩子 if not node.parent: self.root = node.rchild elif node == node.parent.lchild: node.parent.lchild = node.rchild node.rchild.parent = node.parent else: node.parent.rchild = node.rchild node.rchild.parent = node.parent def delete(self,val): if self.root: # 不是空树 node = self.query_no_rec(val) # 找到该节点 if not node: #删的元素不存在 return False if not node.lchild and not node.rchild: # 没有孩子 self.__remove_node_1(node) elif not node.rchild: # 只有一个左孩子 self.__remove_node_21(node) elif not node.lchild: # 只有一个右孩子 self.__remove_node_22(node) else: """两个孩子都有""" min_node = node.rchild while min_node.lchild: min_node = min_node.lchild node.data = min_node.data # 删除min_node if min_node.rchild: self.__remove_node_22(min_node) else: self.__remove_node_1(min_node) def pre_order(self, root): """前序遍历""" if root: # 如果root不是空 print(root.data, end=',') # 访问根节点 self.pre_order(root.lchild) # 访问左子树 self.pre_order(root.rchild) # 访问右子树 def in_order(self,root): """中序遍历""" if root: self.in_order(root.lchild) print(root.data, end=',') self.in_order(root.rchild) def post_order(self, root): """后序遍历""" if root: self.post_order(root.lchild) self.post_order(root.rchild) print(root.data, end=',') def level_order(self,root): """层次遍历""" queue = deque() queue.append(root) while len(queue) > 0: # 只要队不空 node = queue.popleft() # 出队 print(node.data, end=",") if node.lchild: queue.append(node.lchild) if node.rchild: queue.append(node.rchild)
平衡二叉树:
class Bbtree(): #平衡二叉树 def __init__(self,item): self.item=item self.par=None self.l=None self.r=None def llink(self,other): self.l=other if other!=None: other.par=self def rlink(self,other): self.r=other if other!=None: other.par=self def plink(self,other): #向上连接父节点 if other!=None: if self.item<other.item: other.llink(self) elif self.item>other.item: other.rlink(self) else: raise ValueError("节点值相同,无法连接") else: self.par=None def get_depth(self): if self.l==None: l_depth=0 else: l_depth=self.l.get_depth() if self.r==None: r_depth=0 else: r_depth=self.r.get_depth() return max(l_depth,r_depth)+1 def get_bf(self): #获取平衡指数即左树深度-右树深度 if self.l!=None: l_depth=self.l.get_depth() else: l_depth=0 if self.r!=None: r_depth=self.r.get_depth() else: r_depth=0 return l_depth-r_depth def show_mid(self,action=print): if self.l !=None: self.l.show_mid() action(self) if self.r !=None: self.r.show_mid() def add_rec(self,value):#递归添加元素,与排序二叉树类似,增加了path作为返回值 new=Bbtree(value) path_list=[self] #path_list用于记录经过的节点 if value<self.item: path='L' #path记录每次添加元素时,从根节点到新增节点的路径,作为返回值,在每次递归时累加 if self.l==None: self.llink(new) else: path_,path_list_=self.l.add_rec(value) path=path+path_ path_list.extend(path_list_) elif value>self.item: path='R' if self.r==None: self.rlink(new) else: path_,path_list_=self.r.add_rec(value) path=path+path_ path_list.extend(path_list_) else: pass path='' path_list=[] return path,path_list def add_nrec(self,value): new=Bbtree(value) tmp=self while value !=tmp.item: if value<tmp.item and tmp.l==None: tmp.llink(new) return elif value<tmp.item and tmp.l!=None: tmp=tmp.l elif value>tmp.item and tmp.r ==None: tmp.rlink(new) return else: tmp=tmp.r def search_rec(self,value): if value<self.item: if self.l==None: print("树中没有此值,最接近的为%d"%int(self.item)) return False else: return self.l.search_rec(value) elif value>self.item: if self.r==None: print("树中没有此值,最接近的为%d"%int(self.item)) return False else: return self.r.search_rec(value) else: return self def search_nrec(self,value): tmp=self while value !=tmp.item: if value<tmp.item and tmp.l==None: print("树中没有此值,最接近的为%d"%int(tmp.item)) return False elif value<tmp.item and tmp.l!=None: tmp=tmp.l elif value>tmp.item and tmp.r ==None: print("树中没有此值,最接近的为%d"%int(tmp.item)) return False else: tmp=tmp.r return tmp def __repr__(self): if self.l==None: litem=None else: litem=self.l.item if self.r==None: ritem=None else: ritem=self.r.item return '节点: '+str(self.item)+',左节点: '+str(litem)+', 右节点: '+str(ritem)+', 平衡因子: '+str(self.get_bf()) ####四种类型的旋转 def LL(self): A=self B=self.l tmp=A.par A.llink(B.r) B.rlink(A) B.plink(tmp) def RR(self): A=self B=self.r tmp=A.par A.rlink(B.l) B.llink(A) B.plink(tmp) def LR(self): A=self B=A.l C=B.r tmp=A.par A.llink(C.r) B.rlink(C.l) C.llink(B) C.rlink(A) C.plink(tmp) def RL(self): A=self B=A.r C=B.l tmp=A.par A.rlink(C.l) B.llink(C.r) C.rlink(B) C.llink(A) C.plink(tmp) def add_bbt(root,tree_list): #给定根节点,子节点序列,创建平衡二叉树 for i in tree_list: path,path_list=root.add_rec(i) #依次插入节点 print('-'*25+'插入%d后'% i+'-'*25 ) root.show_mid() for ix,j in enumerate(path_list):#对根节点到插入节点路径上的节点,调整平衡因子 if abs(j.get_bf())>1: #如果节点失衡 exec('j.%s()'%path[ix:ix+2]) #根据节点后的2次方向,确定旋转模式,进行旋转 while root.par!=None: #调整root指针到旋转后的根节点 root=root.par print('-'*25+'%s旋转后'% path[:2]+'-'*25 ) root.show_mid()
'''测试''' A=Bbtree(5) #根节点 tree_list=[3,2,100,43,23,89,99,110,112] #插入数据 add_bbt(A,tree_list)
哈夫曼树:
""" 【问题描述】使用贪心算法求解Huffman编码问题,具体来说就是,根据每个字符的出现频率, 构造出字符的最优二进制表示,即前缀码。 在程序开始说明部分,简要描述使用贪心算法求解Huffman编码问题的算法过程。 【输入形式】在屏幕上输入字符个数和每个字符的频率。 【输出形式】每个字符的Huffman编码。 """ import numpy as np class node: # 结点类:结点,权值,左右子树 def __init__(self, name=None, value=None): self._name = name self._value = value self._left = None self._right = None class huff_man_tree: """ 根据哈夫曼算法,以叶子结点为基础,反向建立哈夫曼树: 1、生成叶子结点;包括字符,权值 2、对所有结点以权值进行从大到小排序 3、取出最小的两个结点,即最后两个结点(并且删除两个结点) 4、权值相加,生成一个结点 5、在将这个生成的结点加入到结点中 """ def __init__(self, char_weights): self.a = [node(part[0], part[1]) for part in char_weights] # 生成叶子结点 while len(self.a) != 1: self.a.sort(key=lambda node: node._value, reverse=True) # 以权值进行从大到小排序 c = node(value=(self.a[-1]._value + self.a[-2]._value)) c._left = self.a.pop(-1) c._right = self.a.pop(-1) self.a.append(c) self.root = self.a[0] self.b = np.zeros(self.root.__sizeof__(), dtype=np.int) # self.b用于保存每个叶子节点的哈夫曼编码 """递归的思想生成编码,从根结点开始,左子树为0,右子树为1,依次存储在以结点为键、编码为值的字典中。""" def set_code(self, tree, length, code): node = tree s = "" if not node: return elif node._name: for i in range(length): s = s + str(self.b[i]) code[node._name] = s # 哈夫曼编码字典 return self.b[length] = 0 self.set_code(node._left, length + 1, code) # 递归左子树 self.b[length] = 1 self.set_code(node._right, length + 1, code) # 递归右子树 '''输出哈夫曼编码,对哈夫曼编码字典以键进行排序,依次输出哈夫曼编码''' def get_code(self): code = {} self.set_code(self.root, 0, code) code_name = sorted(code, key=lambda code: code[0]) # 哈夫曼编码字典以键进行排序 for temp in code_name: print(temp, end=' ') print(code.get(temp)) def main(): """ 【样例输入】 6 45 13 12 16 9 5 """ ch = ['a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n'] char_weights = [] n = int(input()) weight = [int(i) for i in input().split()] for i in range(n): char_weights.append((ch[i], weight[i])) # 结点与权值 """ 【样例输出】 a 0 b 101 c 100 d 111 e 1101 f 1100 """ tree = huff_man_tree(char_weights) tree.get_code() """ 【样例说明】 输入:字符个数为6,a至f每个字符的频率分别为:45, 13, 12, 16, 9, 5。 输出:每个字符对应的Huffman编码。 """ if __name__ == '__main__': main()

浙公网安备 33010602011771号