前序遍历:leetcode:144题 二叉树的前序遍历
解题:
前序遍历:中左右的方式进行遍历元素。据说二叉树的底层实现是通过 stack (栈)来实现的,所以我们需要创建一个 stack 来进行辅助操作。
在遍历元素的进栈的时候,要先遍历右节点,再遍历左节点。因为 stack 的特性是先入后出,先进 stack 的后进行操作,所以整个遍历的顺序由原本应该的 中左右 变成 中右左。
代码:
迭代法:
def preorder(root):
# 判读 二叉树 是否为 空,如果为空则直接返回 []
if not root:
return []
# 创建stack、res
stack = [root] # 直接将root根节点放入到stack(栈)中
res = [] # 存储结果
# 当stack非空的时候,就需要继续对二叉树进行遍历
# 以下循环 假设为第一次循环的时候,便于理解
while stack:
# 先将 stack 中的根节点放入到res中,但需要先将 根节点存储起来,因为需要通过它来判断左右节点
node = stack.pop()
res.append(node.val)
# 判断 ‘根节点’ 的右节点是否为空,(为什么是右节点,上面有解释),如果非空就加入到 stack 中
if node.right:
stack.append(node.right)
# 判断 ‘根节点’ 的左节点是否为空,
if node.left:
stack.append(node.left)
return res
递归法:
递归相较于迭代法 更容易记忆(不一定更容易理解),前序遍历的遍历顺序是 中左右,直接开整
递归法三大步骤:
- 确定参数及返回值
- 确定终止条件
- 确定单层递归逻辑
中序、后序的递归法都很相似。
def preoder(root):
# 存储最终结果
res = []
# 递归函数
# 1、确定参数及返回值,参数是root
def traversal(root):
# 2、确定终止条件
# 当节点为空的时候就停止递归
if root == None:
return []
# 3、确定单层递归逻辑
res.append(root.val) # 中
traversal(root.left) # 左
traversal(root.right) # 右
# 调用递归函数
traversal(root)
return res
后序遍历:
解题:
二叉树的后序遍历顺序:左右中。没法或者直接进行遍历,换个思维将某个遍历逆序输出后的遍历顺序式左右中这个遍历顺序。那我们先将 左右中 进行逆序操作,就变成了 中右左 的遍历顺序。我们现在只需要进行 中右左 的遍历顺序来遍历二叉树就可以了。
中右左 这个遍历顺序与前序遍历(中左右很相似,中都在首位,所以可以用相同的代码结构)
代码:
迭代法:
def postorder(root):
# 进行边界的判断
if not root:
return []
# 创建栈 stack
stack = [root] # 将根节点先放入stack中
res = []
# 遍历二叉树
while stack:
node = stack.pop()
res.append(node.val) # 中
if node.left: # 右
stack.append(node.left)
if node.right: # 左
stack.append(node.right)
# 逆序输出
return res[::-1]
递归法:
def postorder(root):
# 存储最后的结果
res = []
# 确定参数及返回值
def traversal(root):
# 确定终止条件
if not root:
return
# 确定单层递归逻辑
traversal(root.left)
traversal(root.right)
res.append(root.val)
traversal(root)
return res
前序遍历与后序遍历比较相似,所以放在一起比较方便理解。中序遍历与前序、后序有所略微不同。
中序遍历:
解题:
二叉树的中序遍历的遍历顺序:左中右,与前序、后序不同。根节点并没有在stack创建的开始就直接放入到stack中,而是将 root 通过 一个节点进行存储,进行元素的遍历。
代码:
迭代法:
def inorder(root):
# 确定边界
if not root:
return []
# 创建stack
stack = []
res = []
# 将root存储起来
cur = root
# 当 stack非空 或 cur 不为空的时候继续
while stack or cur:
# cur 不为空,就继续向二叉树的左节点方向进行遍历下去
# 如果 cur 为空,就将cur 不为空的时候放到stack中的元素pop出来,并且返回到pop出来元素的位置
# 并将元素的值添加到res中,然后遍历右节点元素
if cur:
# 将cur加入到 stack 中
stack.append(cur)
cur = cur.left
else:
cur = stack.pop()
res.append(cur.val)
cur = cur.right
return res
递归法:
中序递归与前序、后序遍历差别不大。只需要明确清楚二叉树的遍历顺序就可以了。
def inorder(root):
# 存储结果
res = []
# 确定参数及返回值
def traversal(root):
# 确定终止条件
if not root:
return []
# 确定单层递归逻辑
traversal(root.left)
res.append(root.val)
traversal(root.right)
# 调用递归函数
traversal(root)
return res
层序遍历:
解题:
层序遍历与前序、中、后序遍历,不同。在图论中层序遍历的遍历形式属于广度搜索,而前序、中、后序遍历属于是深度搜索。
层序遍历是通过队列来辅助实现整个遍历过程。
代码:
迭代法:
# 导入库
from collections import deque
def levelOrder(root):
# 层序遍历
# 最后结果
res_S = []
que = deque([root]) # 将root 根节点 添加到队列中
# 边界
if not root:
return res_S
# 遍历元素
while que:
size = len(que)
res = []
while size:
cur = que.popleft()
res.append(cur.val)
if cur.left:
que.append(cur.left)
if cur.right:
que.append(cur.right)
size -= 1
res_S.append(res)
return res_S
递归法:
def levelOrder(root):
res = []
def helper(root, depth):
if not root: return []
if len(res) == depth: res.append([]) # start the current depth
res[depth].append(root.val) # fulfil the current depth
if root.left: helper(root.left, depth + 1) # process child nodes for the next depth
if root.right: helper(root.right, depth + 1)
helper(root, 0)
return res