九、树及算法-上
本系列博客基于“ (北京大学)数据结构与算法python版”慕课,课程在中国大学慕课和bilibili上均可找到。
1. 内容
- 树结构的相关术语
- 树的表示方法:嵌套列表,链表
- 树的遍历(前序,中序,后序)和应用(表达式解析)
- 使用二插堆Binary Heap实现优先队列
2. 课程代码
在GitHub中下载
3. OJ作业
所有代码均可在github中下载
3.1 二叉树复原
题目内容:
给定一种序列化二叉树的方式:从根节点起始按层次遍历二叉树所有“可能”存在节点的位置:若该位置存在节点,则输出节点值,并在下一层相应增加两个可用位置;否则输出None,且不增加下一层的可用位置。
例如"[5, 4, 7, 3, None, 2, None, -1, None, 9]"是下图所示的二叉树序列化的结果:
其中红色箭头对所有的None进行了标记。
现给出一个二叉树以这种形式序列化的结果,请复原该二叉树并给出它的中序遍历。
输入格式: 一行合法的Python表达式,可解析为包含整数与None的列表
输出格式:二叉树中序遍历的整数序列,以空格分隔
输入样例:
[5, 4, 7, 3, None, 2, None, -1, None, 9]
输出样例:
-1 3 4 5 9 2 7
输入样例2:
[5,1,4,None,None,3,6]
输出样例2:
1 5 3 4 6
注:树结构如图(红色箭头对None的对应位置进行了标记):
方法:
用队列来存储树的节点,用左右flag来标记首先将根结点放入队列,每次从队首出列一个结点
如果此时列表值为none,说明当前节点没有子节点
如果左右标志均=0,把左标志设为1,表示插入none,结点插回队首
如果左标志=0右标志=1,把右标志设为1,表示插入none,结点插回队首
如果此时列表值不为none,说明当前节点有子节点
如果左右标志=0,把列表值变为当前结点左子树,左标志=1,结点插回队首,左子节点跟在队尾
如果左=1,右=0,把列表值变为当前结点右子树,右标志=1,结点插回队首,右子节点跟在队尾
因此,队列当中结点的顺序是 a, b…, a.left_child, a.right_child, b.left_child。顺序和逐层遍历一致
class BinaryTree:
"""
A recursive implementation of Binary Tree
Using links and Nodes approach.
"""
def __init__(self, rootObj):
self.key = rootObj
self.leftChild = None
self.rightChild = None
self.leftFlag = 0 #
self.rightFlag = 0 #
def seq2tree(seq):
# 将列表反序列化为树
queue = [] # 队列储存树
current_tree = BinaryTree(seq[0])
whole_tree = current_tree
queue.append(current_tree)
i = 1 # 从1开始遍历
while i < len(seq) and len(queue) > 0:
current_tree = queue.pop(0)
if seq[i] == None: # 当前点没有子节点 相当于是判断current_tree的子节点是否插入
if current_tree.left