mirror of
https://github.com/youngyangyang04/leetcode-master.git
synced 2025-07-08 00:43:04 +08:00
Merge pull request #2807 from gazeldx/binary_tree_iteration
二叉树的迭代遍历.md 加入 Python 版本的后序遍历新解法
This commit is contained in:
@ -240,14 +240,14 @@ class Solution {
|
|||||||
# 前序遍历-迭代-LC144_二叉树的前序遍历
|
# 前序遍历-迭代-LC144_二叉树的前序遍历
|
||||||
class Solution:
|
class Solution:
|
||||||
def preorderTraversal(self, root: TreeNode) -> List[int]:
|
def preorderTraversal(self, root: TreeNode) -> List[int]:
|
||||||
# 根结点为空则返回空列表
|
# 根节点为空则返回空列表
|
||||||
if not root:
|
if not root:
|
||||||
return []
|
return []
|
||||||
stack = [root]
|
stack = [root]
|
||||||
result = []
|
result = []
|
||||||
while stack:
|
while stack:
|
||||||
node = stack.pop()
|
node = stack.pop()
|
||||||
# 中结点先处理
|
# 中节点先处理
|
||||||
result.append(node.val)
|
result.append(node.val)
|
||||||
# 右孩子先入栈
|
# 右孩子先入栈
|
||||||
if node.right:
|
if node.right:
|
||||||
@ -262,19 +262,23 @@ class Solution:
|
|||||||
# 中序遍历-迭代-LC94_二叉树的中序遍历
|
# 中序遍历-迭代-LC94_二叉树的中序遍历
|
||||||
class Solution:
|
class Solution:
|
||||||
def inorderTraversal(self, root: TreeNode) -> List[int]:
|
def inorderTraversal(self, root: TreeNode) -> List[int]:
|
||||||
stack = [] # 不能提前将root结点加入stack中
|
|
||||||
|
if not root:
|
||||||
|
return []
|
||||||
|
stack = [] # 不能提前将root节点加入stack中
|
||||||
|
|
||||||
result = []
|
result = []
|
||||||
cur = root
|
cur = root
|
||||||
while cur or stack:
|
while cur or stack:
|
||||||
# 先迭代访问最底层的左子树结点
|
# 先迭代访问最底层的左子树节点
|
||||||
if cur:
|
if cur:
|
||||||
stack.append(cur)
|
stack.append(cur)
|
||||||
cur = cur.left
|
cur = cur.left
|
||||||
# 到达最左结点后处理栈顶结点
|
# 到达最左节点后处理栈顶节点
|
||||||
else:
|
else:
|
||||||
cur = stack.pop()
|
cur = stack.pop()
|
||||||
result.append(cur.val)
|
result.append(cur.val)
|
||||||
# 取栈顶元素右结点
|
# 取栈顶元素右节点
|
||||||
cur = cur.right
|
cur = cur.right
|
||||||
return result
|
return result
|
||||||
```
|
```
|
||||||
@ -289,7 +293,7 @@ class Solution:
|
|||||||
result = []
|
result = []
|
||||||
while stack:
|
while stack:
|
||||||
node = stack.pop()
|
node = stack.pop()
|
||||||
# 中结点先处理
|
# 中节点先处理
|
||||||
result.append(node.val)
|
result.append(node.val)
|
||||||
# 左孩子先入栈
|
# 左孩子先入栈
|
||||||
if node.left:
|
if node.left:
|
||||||
@ -301,6 +305,44 @@ class Solution:
|
|||||||
return result[::-1]
|
return result[::-1]
|
||||||
```
|
```
|
||||||
|
|
||||||
|
#### Python 后序遍历的迭代新解法:
|
||||||
|
* 本解法不同于前文介绍的`逆转前序遍历调整后的结果`,而是采用了对每个节点直接处理。这个实现方法在面试中不容易写出来,在下一节,我将改造本代码,奉上代码更简洁、更套路化、更容易实现的统一方法。
|
||||||
|
|
||||||
|
```python
|
||||||
|
class Solution:
|
||||||
|
def postorderTraversal(self, root: Optional[TreeNode]) -> List[int]:
|
||||||
|
values = []
|
||||||
|
stack = []
|
||||||
|
popped_nodes = set() # 记录值已经被收割了的 nodes,这是关键,已经被收割的节点还在树中,还会被访问到,但逻辑上已经等同于 null 节点。
|
||||||
|
current = root
|
||||||
|
|
||||||
|
while current or stack:
|
||||||
|
if current: # 一次处理完一个节点和他的左右儿子节点,不处理孙子节点,孙子节点由左右儿子等会分别处理。
|
||||||
|
stack.append(current) # 入栈自己
|
||||||
|
|
||||||
|
if current.right:
|
||||||
|
stack.append(current.right) # 入栈右儿子
|
||||||
|
|
||||||
|
if current.left: # 因为栈是后进先出,后序是‘左右中’,所以后加左儿子
|
||||||
|
stack.append(current.left) # 入栈左儿子
|
||||||
|
|
||||||
|
current = None # 会导致后面A处出栈
|
||||||
|
continue
|
||||||
|
|
||||||
|
node = stack.pop() # A处,出的是左儿子,如果无左儿子,出的就是右儿子,如果连右儿子也没有,出的就是自己了。
|
||||||
|
|
||||||
|
# 如果 node 是叶子节点,就可以收割了;如果左右儿子都已经被收割了,也可以收割
|
||||||
|
if (node.left is None or node.left in popped_nodes) and \
|
||||||
|
(node.right is None or node.right in popped_nodes):
|
||||||
|
popped_nodes.add(node)
|
||||||
|
values.append(node.val)
|
||||||
|
continue
|
||||||
|
|
||||||
|
current = node # 不符合收割条件,说明 node 下还有未入栈的儿子,就去入栈
|
||||||
|
|
||||||
|
return values
|
||||||
|
```
|
||||||
|
|
||||||
### Go:
|
### Go:
|
||||||
|
|
||||||
> 迭代法前序遍历
|
> 迭代法前序遍历
|
||||||
|
Reference in New Issue
Block a user