1. 定义
class TreeNode:
def __init__(self, val=None, left=None, right=None):
self.val = val
self.left = left
self.right = right
2. 遍历
2.1 先序遍历
2.1.1 递归
def pre(node):
if node is None:
return
print(node.val)
pre(node.left)
pre(node.right)
2.1.2 非递归
def pre1(node):
if node is None:
return
stack = [node]
while stack:
# 取出栈顶元素
node = stack.pop()
# node = stack.pop(-1)
print(node.val)
if node.right:
stack.append(node.right)
if node.left:
stack.append(node.left)
或(不如上面的简单)
def pre2(node):
if node is None:
return
stack = []
while (node is not None) or (len(stack) > 0):
if node:
stack.append(node)
# yield node.val
print(node.val)
node = node.left
else:
node = stack.pop()
node = node.right
2.3 中序遍历
2.3.1 递归
def mid(node):
if node is None:
return
mid(node.left)
print(node.val)
mid(node.right)
2.3.2 非递归
def mid1(node):
if node is None:
return
stack = []
while node or (len(stack) > 0):
if node:
stack.append(node)
node = node.left
else:
node = stack.pop()
print(node.val)
node = node.right
2.3 后序遍历
2.3.1 递归
def post(node):
if node is None:
return
post(node.left)
post(node.right)
print(node.val)
2.3.2 非递归
stack1 入(根左右) --> stack1出(根右左) --倒置--> stack2(左右根)
def post1(node):
if node is None:
return
stack1, stack2 = [], []
stack1.append(node)
while stack1:
node = stack1.pop()
stack2.append(node)
if node.left:
stack1.append(node.left)
if node.right:
stack1.append(node.right)
while stack2:
node = stack2.pop()
print(node.val)
2.4 测试
# 定义结点
node1 = TreeNode(1)
node2 = TreeNode(2)
node3 = TreeNode(3)
node4 = TreeNode(4)
node5 = TreeNode(5)
node6 = TreeNode(6)
node7 = TreeNode(7)
# 构建树
root = node1
root.left = node2
root.right = node3
node2.left = node4
node2.right = node5
node3.left = node6
node3.right = node7
print(------先序遍历(递归)------)
pre(root)
pre1(root)
# 1 2 4 5 3 6 7
print(------中序遍历(递归)------)
mid(root)
# 4 2 5 1 6 3 7
print(------后序遍历(递归)------)
post(root)
# 4 5 2 6 7 3 1
3. 重建二叉树
只能由前中序或后中序才能重建二叉树(必须有中序遍历找到根结点所在位置)。
3.1 由前、中序遍历重建二叉树
def tree_by_pre_mid(pre, mid):
if (len(pre) == 0) or (len(mid) == 0) or (len(pre) != len(mid)):
return
root = TreeNode(pre[0])
# 在中序遍历中找到根结点位置
i = mid.index(pre[0])
root.left = tree_by_pre_mid(pre[1:i+1], mid[:i])
root.right = tree_by_pre_mid(pre[i+1:], mid[i+1:])
return root
3.2 由后、中序遍历重建二叉树
def tree_by_post_mid(post, mid):
if (len(post) == 0) or (len(mid) == 0) or (len(post) != len(mid)):
return
root = TreeNode(post[-1])
# 在中序遍历中找到根结点位置
i = mid.index(post[-1])
root.left = tree_by_post_mid(post[:i], mid[:i])
# -1 不能省,否则结果不对
root.right = tree_by_post_mid(post[i:-1], mid[i+1:])
return root
3.3 测试
pre_order_list = [1, 2, 4, 5, 3, 6, 7]
mid_order_list = [4, 2, 5, 1, 6, 3, 7]
post_order_list = [4, 5, 2, 6, 7, 3, 1]
root = tree_by_pre_mid(pre_order_list, mid_order_list)
post(root)
# 4 5 2 6 7 3 1
root = tree_by_post_mid(post_order_list, mid_order_list)
pre(root)
# 1 2 4 5 3 6 7
4. 广度优先与深度优先遍历
4.1 广度优先遍历BFS(层次遍历)
依次将根、左、右子树入队列。
def level(node):
if node is None:
return
queue = [node]
while queue:
# 取出队头元素
node = queue.pop(0)
print(node.val)
if node.left:
queue.append(node.left)
if node.right:
queue.append(node.right)
4.2 深度优先遍历(DFS)
二叉树的深度优先遍历与先序遍历是一样的!!!
4.3 测试
node1 = TreeNode(1)
node2 = TreeNode(2)
node3 = TreeNode(3)
node4 = TreeNode(4)
node5 = TreeNode(5)
node6 = TreeNode(6)
node7 = TreeNode(7)
root = node1
root.left = node2
root.right = node3
node2.right = node4
node3.left = node5
node3.right = node6
node5.left = node7
level(root)
# 1 2 3 4 5 6 7
5. 之字形遍历(锯齿形层次遍历)
二叉树宽度也是这个思路:先求按层遍历的数组,再求数组内子数组长度最大的那层既是。
def zigzag_level_order(root):
if not root:
return []
queue = [root]
result = []
# 相邻层flag取反
flag = 1
while queue:
# 存储当前层遍历的结果
temp_list = []
for i in range(len(queue)):
temp = queue.pop(0)
temp_list.append(temp.val)
if temp.left:
queue.append(temp.left)
if temp.right:
queue.append(temp.right)
if flag == -1:
temp_list = temp_list[::-1]
result.extend(temp_list)
# result.append(temp_list)
flag *= -1
print(result)
测试
node1 = TreeNode(1)
node2 = TreeNode(2)
node3 = TreeNode(3)
node4 = TreeNode(4)
node5 = TreeNode(5)
node6 = TreeNode(6)
node7 = TreeNode(7)
root = node4
root.left = node2
root.right = node6
# node2.left = node1
node2.right = node3
# node3.right = node7
node6.left = node5
zigzag_level_order(root)
# [4, 6, 2, 3, 5]