# 导入队列库
from collections import deque
class BiTreeNode:
def __init__(self, data):
self.data = data
self.l_child = None
self.r_child = None
# 前序遍历
def pre_order(root):
"""
传入根节点,前序遍历,根据中左右的原则去走。
:param root:
:return:
"""
if root:
print(root.data, end=' ')
pre_order(root.l_child)
pre_order(root.r_child)
# 中序遍历
def mid_order(root):
"""
根据左中右原则去遍历。
:param root:
:return:
"""
if root:
mid_order(root.l_child)
print(root.data, end=' ')
mid_order(root.r_child)
# 后续遍历
def post_order(root):
"""
:param root:
:return:
"""
if root:
post_order(root.l_child)
post_order(root.r_child)
print(root.data, end=' ')
# 层次遍历
def level_order(root):
"""
利用队列实现层次遍历。
:param root:
:return:
"""
que = deque()
que.append(root)
while len(que) > 0:
node = que.popleft()
print(node.data, end=' ')
if node.l_child:
que.append(node.l_child)
if node.r_child:
que.append(node.r_child)
# 根据前序和中序遍历顺序生成树
def buildTree(pre_order_list, in_order_list):
"""
传入两个列表,前者为前序遍历,后者为中序遍历。前序找根,中序找左右子树。递归生成,函数内写函数
:param pre_order_list:
:param in_order_list:
:return:
"""
hash = {
val: i for i, val in enumerate(in_order_list)}
def create_recur(root_index, left, right):
if left > right:
return None
# 获取当前需要的根节点
root = BiTreeNode(data=pre_order_list[root_index])
# 获取根节点在中序中的位置,确定左子树和右子树,这里明显需要一个记录中序遍历节点位置的hash
in_index = hash[root.data]
root.l_child = create_recur(root_index + 1, left, in_index - 1)
root.r_child = create_recur(root_index + 1 + in_index - left, in_index + 1, right)
return root
return create_recur(0, 0, len(in_order_list) - 1)
今天主要是看到一道力扣的中等题,还原二叉树,因为最近面试,所以就刷一些算法,想着顺便把二叉树这块的东西复习了,结果复习了一会,看到了一些已经遗忘的,像类似于二叉搜索树这类,就暂时先把代码记录着。等后期整理到一个类中。
这道题目说是中等题其实也不过如此吧,解法还是很多的。应该主要考验思路,有几个点还是需要清楚的。
题目思路:
- 利用递归分而治之,树既然可以递归遍历,那就可以递归生成,这个思路也不难想到,前序遍历遵循《根左右》的规律,中序遍历遵循《左根右的结构》,那么前序的序列就是寻找根节点的序列,中序的序列就是确定左右子树的序列,通过前序确定的跟节点,到中序这里进行分治递归即可,代码在上面很容易看懂。
- 这里唯一值得一提的点是,利用切片同样的思路,整体效率会差很多,个人思考是切片在不断的递归中本身占据太多的缓存,其空间和速度都远远不如游标的写法,所以个人建议非特别情况下还是用游标去写类似算法,切片固然对程序员方便,但是对cpu确实不方便。