Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

Commit d2f6458

Browse files
Merge pull request youngyangyang04#2807 from gazeldx/binary_tree_iteration
二叉树的迭代遍历.md 加入 Python 版本的后序遍历新解法
2 parents 872deab + 85f91e2 commit d2f6458

File tree

1 file changed

+49
-7
lines changed

1 file changed

+49
-7
lines changed

‎problems/二叉树的迭代遍历.md‎

Lines changed: 49 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -240,14 +240,14 @@ class Solution {
240240
# 前序遍历-迭代-LC144_二叉树的前序遍历
241241
class Solution:
242242
def preorderTraversal(self, root: TreeNode) -> List[int]:
243-
# 根结点为空则返回空列表
243+
# 根节点为空则返回空列表
244244
if not root:
245245
return []
246246
stack = [root]
247247
result = []
248248
while stack:
249249
node = stack.pop()
250-
# 中结点先处理
250+
# 中节点先处理
251251
result.append(node.val)
252252
# 右孩子先入栈
253253
if node.right:
@@ -262,19 +262,23 @@ class Solution:
262262
# 中序遍历-迭代-LC94_二叉树的中序遍历
263263
class Solution:
264264
def inorderTraversal(self, root: TreeNode) -> List[int]:
265-
stack = [] # 不能提前将root结点加入stack中
265+
266+
if not root:
267+
return []
268+
stack = [] # 不能提前将root节点加入stack中
269+
266270
result = []
267271
cur = root
268272
while cur or stack:
269-
# 先迭代访问最底层的左子树结点
273+
# 先迭代访问最底层的左子树节点
270274
if cur:
271275
stack.append(cur)
272276
cur = cur.left
273-
# 到达最左结点后处理栈顶结点
277+
# 到达最左节点后处理栈顶节点
274278
else:
275279
cur = stack.pop()
276280
result.append(cur.val)
277-
# 取栈顶元素右结点
281+
# 取栈顶元素右节点
278282
cur = cur.right
279283
return result
280284
```
@@ -289,7 +293,7 @@ class Solution:
289293
result = []
290294
while stack:
291295
node = stack.pop()
292-
# 中结点先处理
296+
# 中节点先处理
293297
result.append(node.val)
294298
# 左孩子先入栈
295299
if node.left:
@@ -301,6 +305,44 @@ class Solution:
301305
return result[::-1]
302306
```
303307

308+
#### Python 后序遍历的迭代新解法:
309+
* 本解法不同于前文介绍的`逆转前序遍历调整后的结果`,而是采用了对每个节点直接处理。这个实现方法在面试中不容易写出来,在下一节,我将改造本代码,奉上代码更简洁、更套路化、更容易实现的统一方法。
310+
311+
```python
312+
class Solution:
313+
def postorderTraversal(self, root: Optional[TreeNode]) -> List[int]:
314+
values = []
315+
stack = []
316+
popped_nodes = set() # 记录值已经被收割了的 nodes,这是关键,已经被收割的节点还在树中,还会被访问到,但逻辑上已经等同于 null 节点。
317+
current = root
318+
319+
while current or stack:
320+
if current: # 一次处理完一个节点和他的左右儿子节点,不处理孙子节点,孙子节点由左右儿子等会分别处理。
321+
stack.append(current) # 入栈自己
322+
323+
if current.right:
324+
stack.append(current.right) # 入栈右儿子
325+
326+
if current.left: # 因为栈是后进先出,后序是‘左右中’,所以后加左儿子
327+
stack.append(current.left) # 入栈左儿子
328+
329+
current = None # 会导致后面A处出栈
330+
continue
331+
332+
node = stack.pop() # A处,出的是左儿子,如果无左儿子,出的就是右儿子,如果连右儿子也没有,出的就是自己了。
333+
334+
# 如果 node 是叶子节点,就可以收割了;如果左右儿子都已经被收割了,也可以收割
335+
if (node.left is None or node.left in popped_nodes) and \
336+
(node.right is None or node.right in popped_nodes):
337+
popped_nodes.add(node)
338+
values.append(node.val)
339+
continue
340+
341+
current = node # 不符合收割条件,说明 node 下还有未入栈的儿子,就去入栈
342+
343+
return values
344+
```
345+
304346
### Go:
305347

306348
> 迭代法前序遍历

0 commit comments

Comments
(0)

AltStyle によって変換されたページ (->オリジナル) /