今天在LeetCode刷题的时候,遇到一个二叉树非递归后序遍历的题目。
评论区发现一位大神给的前中后序都通用的非递归模板,着实受益匪浅,因此记录一下。
原文参见:https://leetcode-cn.com/problems/binary-tree-postorder-traversal/solution/mo-fang-di-gui-zhi-bian-yi-xing-by-sonp/
用C++写的,这里我改成了Python。
二叉树结点的定义如下:
复制代码
1
2
3
4
5
6
7
8
9
10
11from typing import List # Definition for a binary tree node. class TreeNode: def __init__(self, x): self.val = x self.left = None self.right = None
后序遍历的模板代码
首先应该说清楚的是:除了前序遍历外,对结点的首次访问和对结点的处理并不是同时发生的,后两者对结点的处理发生在第二次访问时——例如中序遍历,每个结点首次访问到之后,还会去访问它的左子树,直至左子树全部访问完毕再次回到这个结点,才是对当前结点的访问/处理。
因此有必要标识清楚当前是对结点的第几次访问 ——
以上就是下面的代码中结点压入栈的时候要额外让None进栈的原因,遇到None则对其下一个结点进行处理 。
(吐槽一下,Python代码注释的字体好丑……)
复制代码
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26class Solution: def postorderTraversal(self, root: TreeNode) -> List[int]: res = [] # 储存遍历结果 stack = [] # 模拟栈 if root: stack.append(root) # 根结点进栈保证循环正常进行,同时可以处理空树 while stack: t = stack.pop() # 每一步拿出一个点 if t: # 模拟递归的压栈顺序 stack.append(t) # 顺着访问,因此逆着压栈,后序遍历是左右根,就先进根 stack.append(None) # None用来表示下个结点从栈里面弹出来已经是第二次访问了 if t.right: stack.append(t.right) # 保证非空再进右 if t.left: stack.append(t.left) # 保证非空再进左 else: # 在第二次访问的时候,弹栈,对弹出的元素进行处理 res.append(stack.pop().val) # 此处可以写对当前结点进行任何处理的代码 # 对于前序遍历,只要把根左右的遍历顺序逆向——右左根,把对应的代码顺序调整一下即可 # 中序遍历也是如此——右根左 # 最后提一句,因为前序遍历首次访问和对节点的处理是同时发生的,因此代码可以简化 return res
完整非递归后序遍历代码
下面贴一个可以直接运行的代码,方便理清思路和调试。
复制代码
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53from typing import List # Definition for a binary tree node. class TreeNode: def __init__(self, x): self.val = x self.left = None self.right = None class Solution: def postorderTraversal(self, root: TreeNode) -> List[int]: res = [] stack = [] if root: stack.append(root) while stack: t = stack.pop() if t: stack.append(t) # 1 stack.append(None) # 1 if t.right: # 2 stack.append(t.right) if t.left: # 3 stack.append(t.left) # 对于前序遍历和中序遍历,调整# 1的顺序即可 # 把#1 放在#2与#3之间就是中序遍历 # 把#1 放在#3之后就是前序遍历 else: res.append(stack.pop().val) return res if __name__ == '__main__': # 构造下面的一棵二叉树 # 1 # / # 2 3 # # 4 r = TreeNode(1) r.left = TreeNode(2) r.right = TreeNode(3) r.left.right = TreeNode(4) # 后序遍历 solution = Solution() post_order = solution.postorderTraversal(r) print(post_order)
对应的前序遍历与中序遍历
前序遍历只要将后序遍历中“根右左”的顺序调整为对应的“右左根”即可:
复制代码
1
2
3
4
5
6
7
8# 前序遍历中 if t: 内的代码调整为如下格式即可。 if t.right: stack.append(t.right) if t.left: stack.append(t.left) stack.append(t) stack.append(None)
中序遍历大家可以自己试试~
最后
以上就是高高篮球最近收集整理的关于二叉树非递归三种遍历的统一模板的全部内容,更多相关二叉树非递归三种遍历内容请搜索靠谱客的其他文章。
本图文内容来源于网友提供,作为学习参考使用,或来自网络收集整理,版权属于原作者所有。
发表评论 取消回复