|
4 | 4 |
|
5 | 5 | ### 二叉树遍历
|
6 | 6 |
|
7 |
| -**前序遍历**:**先访问根节点**,再前序遍历左子树,再前序遍历右子树 |
8 |
| -**中序遍历**:先中序遍历左子树,**再访问根节点**,再中序遍历右子树 |
9 |
| -**后序遍历**:先后序遍历左子树,再后序遍历右子树,**再访问根节点** |
| 7 | +- **前序遍历**:**先访问根节点**,再前序遍历左子树,再前序遍历右子树 |
| 8 | +- **中序遍历**:先中序遍历左子树,**再访问根节点**,再中序遍历右子树 |
| 9 | +- **后序遍历**:先后序遍历左子树,再后序遍历右子树,**再访问根节点** |
10 | 10 |
|
11 |
| -注意点 |
| 11 | +注意点: |
12 | 12 |
|
13 | 13 | - 以根访问顺序决定是什么遍历
|
14 | 14 | - 左子树都是优先右子树
|
@@ -45,7 +45,10 @@ def postorder_rec(root):
|
45 | 45 |
|
46 | 46 | #### [前序非递归](https://leetcode-cn.com/problems/binary-tree-preorder-traversal/)
|
47 | 47 |
|
48 |
| -- 本质上是图的DFS的一个特例,因此可以用栈来实现 |
| 48 | +- 本质上是图的DFS的一个特例,因此可以用栈来实现。前中后序遍历都是DFS的一种。 |
| 49 | +- 理解的时候,左右指的不是左右节点,而是左右子树。 |
| 50 | +- 递归的实现方法都可以使用栈来实现。递归在编程语言中的实现本身也是基于栈的“函数调用栈”。 |
| 51 | +- 参考:[关于二叉树,你该了解这些!| 二叉树理论基础一网打尽,二叉树的种类、二叉树的存储方式、二叉树节点定义、二叉树的遍历顺序](https://www.bilibili.com/video/BV1Hy4y1t7ij) |
49 | 52 |
|
50 | 53 | ```Python
|
51 | 54 | class Solution:
|
@@ -133,6 +136,45 @@ class Solution:
|
133 | 136 |
|
134 | 137 | > DFS 深度搜索(从上到下) 和分治法区别:前者一般将最终结果通过指针参数传入,后者一般递归返回结果最后合并
|
135 | 138 |
|
| 139 | +#### 非递归二叉树通用遍历模板 |
| 140 | + |
| 141 | +[颜色标记法,一种通用且简明的树遍历方法](https://leetcode.cn/problems/binary-tree-inorder-traversal/solutions/25220/yan-se-biao-ji-fa-yi-chong-tong-yong-qie-jian-ming) |
| 142 | +[迭代的核心思想是采用栈模拟递归](https://leetcode.cn/problems/binary-tree-inorder-traversal/solutions/25220/yan-se-biao-ji-fa-yi-chong-tong-yong-qie-jian-ming/comments/2347570) |
| 143 | +[方法还可以优化](https://leetcode.cn/problems/binary-tree-inorder-traversal/solutions/25220/yan-se-biao-ji-fa-yi-chong-tong-yong-qie-jian-ming/comments/204119) |
| 144 | + |
| 145 | +迭代的核心思想是采用栈模拟递归。对于任意一棵树,都将其抽象为(左子树,中节点,右子树),也可以简称为左-中-右三个 "节点"。 |
| 146 | + |
| 147 | +遍历一棵树时,按照递归的思路理解,分为 进入 和 回溯 两个阶段,用栈模拟可以理解为 "两次入栈"。 以中序遍历为例: |
| 148 | + |
| 149 | +- 第一次入栈时是以当前节点为根节点的**整棵子树**入栈; |
| 150 | +- 通过栈中序遍历该子树,就要对其进行**展开**,第二次入栈代表展开。对于任意一棵树,中序遍历都是先递归左子树,因此需要按照**右子树-中节点-左子树**的顺序入栈展开; |
| 151 | + |
| 152 | +两次入栈就同样对应着两次出栈: |
| 153 | + |
| 154 | +- 第一次出栈是展开前将代表子树的栈顶节点出栈; |
| 155 | +- 第二次出栈是展开后栈顶的中节点加入遍历序列; |
| 156 | + |
| 157 | +具体地说,采用变量 flag 标记节点两次入栈的过程,flag = 0 代表第一次入栈,flag = 1 代表第二次入栈。首先根节点标记为 0 入栈,迭代取出栈顶节点时: |
| 158 | + |
| 159 | +- 当栈顶节点的 flag = 0 时,代表子树递归进入的过程,先将栈顶节点出栈,然后按照 右子树-中节点-左子树 的顺序将该子树展开入栈,其中右子树和左子树标记为 0,中节点标记为 1 |
| 160 | +- 当 flag = 1 时,代表递归回溯的过程,将栈顶节点加入到中序遍历序列 |
| 161 | + |
| 162 | +对于python,不需要使用标记。如果栈中是树,则传入节点,如果是值,则传入值。出栈时判断元素类型。 |
| 163 | + |
| 164 | +前序遍历的具体代码,其他遍历方式倒着更改入栈顺序就好: |
| 165 | + |
| 166 | +```python |
| 167 | +def preorderTraversal(self, root: Optional[TreeNode]) -> List[int]: |
| 168 | + stack, values = [root], [] |
| 169 | + while stack: |
| 170 | + node = stack.pop() |
| 171 | + if isinstance(node, TreeNode): |
| 172 | + stack.extend([node.right, node.left, node.val, ]) |
| 173 | + elif isinstance(node, int): |
| 174 | + values.append(node) |
| 175 | + return values |
| 176 | +``` |
| 177 | + |
136 | 178 | #### [BFS 层次遍历](https://leetcode-cn.com/problems/binary-tree-level-order-traversal/)
|
137 | 179 |
|
138 | 180 | ```Python
|
|
0 commit comments