过年不卷、随便写点。
二叉树的遍历主要分为前中后序遍历加一个层序遍历。
前序遍历:中左右
中序遍历:左中右
后续遍历:左右中
层序遍历:从上到下,从左到右
前序遍历
两种方法:1.递归,简单 2.迭代,难一点
递归写法
# Definition for a binary tree node.
# class TreeNode:
# def __init__(self, val=0, left=None, right=None):
# self.val = val
# self.left = left
# self.right = right
class Solution:
def preorderTraversal(self, root: Optional[TreeNode]) -> List[int]:
# 递归终止条件
if not root:
return []
# 左
left = self.preorderTraversal(root.left)
# 右
right = self.preorderTraversal(root.right)
# 中左右,前序
return [root.val] + left + right
迭代写法
# Definition for a binary tree node.
# class TreeNode:
# def __init__(self, val=0, left=None, right=None):
# self.val = val
# self.left = left
# self.right = right
class Solution:
def preorderTraversal(self, root: Optional[TreeNode]) -> List[int]:
# 如果为空直接返回空列表
if not root:
return []
# 栈
stack = [root]
# 保存结果
res = []
while stack:
# 出栈
node = stack.pop()
if node:
# 如果不为空,值入res
res.append(node.val)
# 栈先进后出,因为是前序,中左右,右子树先入栈,然后左子树入栈
if node.right:
stack.append(node.right)
if node.left:
stack.append(node.left)
return res
中序遍历
递归写法94. 二叉树的中序遍历
# Definition for a binary tree node.
# class TreeNode:
# def __init__(self, val=0, left=None, right=None):
# self.val = val
# self.left = left
# self.right = right
class Solution:
def inorderTraversal(self, root: Optional[TreeNode]) -> List[int]:
# 终止条件
if not root:
return []
# 左
left = self.inorderTraversal(root.left)
# 右
right = self.inorderTraversal(root.right)
# 中序,左中右
return left + [root.val] + right
迭代写法
# Definition for a binary tree node.
# class TreeNode:
# def __init__(self, val=0, left=None, right=None):
# self.val = val
# self.left = left
# self.right = right
class Solution:
def inorderTraversal(self, root: Optional[TreeNode]) -> List[int]:
cur = root
stack = []
res = []
while cur or stack:
# 先迭代访问左子树最底层的结点
if cur:
stack.append(cur)
cur = cur.left
# 到达最左结点后处理栈顶结点
else:
cur = stack.pop()
res.append(cur.val)
# 向右迭代
cur = cur.right
return res
后序遍历
左右中
递归没什么好说的,和前面几乎一样
# Definition for a binary tree node.
# class TreeNode:
# def __init__(self, val=0, left=None, right=None):
# self.val = val
# self.left = left
# self.right = right
class Solution:
def postorderTraversal(self, root: Optional[TreeNode]) -> List[int]:
if not root:
return []
left = self.postorderTraversal(root.left)
right = self.postorderTraversal(root.right)
return left + right + [root.val]
迭代写法
# Definition for a binary tree node.
# class TreeNode:
# def __init__(self, val=0, left=None, right=None):
# self.val = val
# self.left = left
# self.right = right
class Solution:
def postorderTraversal(self, root: Optional[TreeNode]) -> List[int]:
res = []
stack = []
if root:
stack.append(root)
while stack:
node = stack.pop()
if node != None:
stack.append(node) #中
# 中节点未处理,加入None作为标记
stack.append(None)
if node.right: #右,空节点不入栈
# 添加右节点
stack.append(node.right)
if node.left: #左,空节点不入栈
# 添加左节点
stack.append(node.left)
else:
# 空的弹出
node = stack.pop()
# 加入结果集
res.append(node.val)
return res
层序遍历
从上到下,从左到右,广搜
# Definition for a binary tree node.
# class TreeNode:
# def __init__(self, val=0, left=None, right=None):
# self.val = val
# self.left = left
# self.right = right
class Solution:
def levelOrder(self, root: Optional[TreeNode]) -> List[List[int]]:
if root is None:
return []
res = []
cur = [root]
while cur:
# 初始化下一层
next_level = []
vals = []
for node in cur:
vals.append(node.val)
# 从左到右
if node.left:
next_level.append(node.left)
if node.right:
next_level.append(node.right)
# 下一层
cur = next_level
# 加入结果
res.append(vals)
return res
过年一直是二叉树!!另一种层序遍历(从下到上)
层序遍历变体
和层序遍历类似,返回的时候翻转顺序即可
# Definition for a binary tree node.
# class TreeNode:
# def __init__(self, val=0, left=None, right=None):
# self.val = val
# self.left = left
# self.right = right
class Solution:
def levelOrderBottom(self, root: Optional[TreeNode]) -> List[List[int]]:
if not root:
return []
stack = [root]
res = []
while stack:
next_level = []
vals = []
for node in stack:
vals.append(node.val)
if node.left:
next_level.append(node.left)
if node.right:
next_level.append(node.right)
stack = next_level
res.append(vals)
# 返回时反转顺序
return res[::-1]
垂序遍历
这是真的听的少,就做题时候看到的
# Definition for a binary tree node.
# class TreeNode:
# def __init__(self, val=0, left=None, right=None):
# self.val = val
# self.left = left
# self.right = right
class Solution:
def verticalTraversal(self, root: Optional[TreeNode]) -> List[List[int]]:
# 队列,根节点
queue = collections.deque([[root, 0, 0]])
hashmap = collections.defaultdict(list)
# 遍历队列先进先出,j=列 i=行 先列后行是因为垂序遍历的顺序是从左列到右列,从上行到下行
while queue:
node, j, i = queue.popleft()
# 对应位置(j,i)加入当前节点值
hashmap[(j, i)].append(node.val)
# 判断有无左孩子
if node.left:
queue.append([node.left, j-1, i+1])
# 判断有无右孩子
if node.right:
queue.append([node.right, j+1, i+1])
res = []
temp = []
# j_flag 是初始化值,在节点数范围外
j_flag = -1001
for j, i in sorted(hashmap.keys()):
# 不同列
if j != j_flag:
res.append(temp)
temp = []
j_flag = j
# 将排完序的hashmap扩展到temp中,
temp.extend(sorted(hashmap[(j, i)]))
# 第一个是空的弹出
res.pop(0)
# 最后一个temp没加入,最后加入
res.append(temp)
return res
N叉树的层序遍历
之前都是二叉,现在是N叉的层序遍历
"""
# Definition for a Node.
class Node:
def __init__(self, val=None, children=None):
self.val = val
self.children = children
"""
class Solution:
def levelOrder(self, root: 'Node') -> List[List[int]]:
if not root:
return []
res = []
queue = deque([root])
while queue:
vals = []
for _ in range(len(queue)):
node = queue.popleft()
vals.append(node.val)
queue.extend(node.children)
res.append(vals)
return res
和二叉树的层序遍历没有什么区别。
N叉树的前序遍历
"""
# Definition for a Node.
class Node:
def __init__(self, val=None, children=None):
self.val = val
self.children = children
"""
class Solution:
def preorder(self, root: 'Node') -> List[int]:
stack = []
res = []
if root:
stack.append(root)
while stack:
node = stack.pop()
if node:
res.append(node.val)
for child in node.children[::-1]:
stack.append(child)
return res
N叉树的后序遍历
"""
# Definition for a Node.
class Node:
def __init__(self, val=None, children=None):
self.val = val
self.children = children
"""
class Solution:
def postorder(self, root: 'Node') -> List[int]:
res = []
stack = []
if root:
stack.append(root)
while stack:
p = stack.pop()
stack.extend(p.children)
res.append(p.val)
return res[::-1]
当你了解了什么是前序遍历,什么是中序遍历,什么是后续遍历,任何根据遍历生成树呢?
生成二叉树
根据前序中序构造二叉树
# Definition for a binary tree node.
# class TreeNode:
# def __init__(self, val=0, left=None, right=None):
# self.val = val
# self.left = left
# self.right = right
class Solution:
def buildTree(self, preorder: List[int], inorder: List[int]) -> Optional[TreeNode]:
# 105/106类似
# 第一步: 特殊情况讨论: 树为空. 或者说是递归终止条件
if not preorder:
return None
# 第二步: 前序遍历的第一个就是当前的中间节点.
root_val = preorder[0]
root = TreeNode(root_val)
# 第三步: 找切割点.
separator_idx = inorder.index(root_val)
# 第四步: 切割inorder数组. 得到inorder数组的左,右半边.
inorder_left = inorder[:separator_idx]
inorder_right = inorder[separator_idx + 1:]
# 第五步: 切割preorder数组. 得到preorder数组的左,右半边.
# 中序数组大小一定跟前序数组大小是相同的.
preorder_left = preorder[1:1 + len(inorder_left)]
preorder_right = preorder[1 + len(inorder_left):]
# 第六步: 递归
root.left = self.buildTree(preorder_left, inorder_left)
root.right = self.buildTree(preorder_right, inorder_right)
# 第七步: 返回答案
return root
106. 从中序与后序遍历序列构造二叉树
# Definition for a binary tree node.
# class TreeNode:
# def __init__(self, val=0, left=None, right=None):
# self.val = val
# self.left = left
# self.right = right
class Solution:
def buildTree(self, inorder: List[int], postorder: List[int]) -> Optional[TreeNode]:
if not postorder:
return None
root_val = postorder[-1]
root = TreeNode(root_val)
mid_index = inorder.index(root_val)
inorder_left = inorder[:mid_index]
inorder_right = inorder[mid_index+1:]
postorder_left = postorder[:len(inorder_left)]
postorder_right = postorder[len(inorder_left):-1]
root.left = self.buildTree(inorder_left, postorder_left)
root.right = self.buildTree(inorder_right, postorder_right)
return root
根据前序后续构造二叉树
# Definition for a binary tree node.
# class TreeNode:
# def __init__(self, val=0, left=None, right=None):
# self.val = val
# self.left = left
# self.right = right
class Solution:
def constructFromPrePost(self, preorder: List[int], postorder: List[int]) -> Optional[TreeNode]:
if not preorder:
return None
if len(preorder) == 1:
return TreeNode(preorder[0])
root_val = preorder[0]
root = TreeNode(root_val)
pos_index = postorder.index(preorder[1]) + 1
preorder_left = preorder[1:1+pos_index]
preorder_right = preorder[1+pos_index:]
postorder_left = postorder[:len(preorder_left)]
postorder_right = postorder[len(preorder_left):-1]
root.left = self.constructFromPrePost(preorder_left, postorder_left)
root.right = self.constructFromPrePost(preorder_right, postorder_right)
return root
思路和之前一样,终止条件:1.如果前序为空,return None 2. 如果前序长度为1,则直接返回节点,preorder的第一个,postorder的最后一个为根节点。pos_index 为左子树的长度,分割preorder的左子树和右子树,分割postorder的左子树和右子树,然后分别左子树递归,右子树递归,返回根节点。