@@ -227,7 +227,8 @@ public:
227227## 其他语言版本
228228
229229### Java:
230- 迭代法前序遍历代码如下:
230+
231+ 迭代法前序遍历(空指针标记法)代码如下:
231232
232233``` java
233234class Solution {
@@ -239,11 +240,10 @@ class Solution {
239240 TreeNode node = st. peek();
240241 if (node != null ) {
241242 st. pop(); // 将该节点弹出,避免重复操作,下面再将右左中节点添加到栈中(前序遍历-中左右,入栈顺序右左中)
242- if (node. right!= null ) st. push(node. right); // 添加右节点(空节点不入栈)
243- if (node. left!= null ) st. push(node. left); // 添加左节点(空节点不入栈)
244- st. push(node); // 添加中节点
243+ if (node. right != null ) st. push(node. right); // 添加右节点(空节点不入栈)
244+ if (node. left != null ) st. push(node. left); // 添加左节点(空节点不入栈)
245+ st. push(node); // 添加中节点
245246 st. push(null ); // 中节点访问过,但是还没有处理,加入空节点做为标记。
246-
247247 } else { // 只有遇到空节点的时候,才将下一个节点放进结果集
248248 st. pop(); // 将空节点弹出
249249 node = st. peek(); // 重新取出栈中元素
@@ -256,34 +256,34 @@ class Solution {
256256}
257257```
258258
259- 迭代法中序遍历代码如下:
259+ 迭代法中序遍历(空指针标记法)代码如下:
260260``` java
261261class Solution {
262- public List<Integer > inorderTraversal (TreeNode root ) {
262+ public List<Integer > inorderTraversal (TreeNode root ) {
263263 List<Integer > result = new LinkedList<> ();
264- Stack<TreeNode > st = new Stack<> ();
265- if (root != null ) st. push(root);
266- while (! st. empty()) {
267- TreeNode node = st. peek();
268- if (node != null ) {
269- st. pop(); // 将该节点弹出,避免重复操作,下面再将右中左节点添加到栈中(中序遍历-左中右,入栈顺序右中左)
270- if (node. right!= null ) st. push(node. right); // 添加右节点(空节点不入栈)
271- st. push(node); // 添加中节点
272- st. push(null ); // 中节点访问过,但是还没有处理,加入空节点做为标记。
273- if (node. left!= null ) st. push(node. left); // 添加左节点(空节点不入栈)
274- } else { // 只有遇到空节点的时候,才将下一个节点放进结果集
275- st. pop(); // 将空节点弹出
276- node = st. peek(); // 重新取出栈中元素
277- st. pop();
278- result. add(node. val); // 加入到结果集
264+ Stack<TreeNode > st = new Stack<> ();
265+ if (root != null ) st. push(root);
266+ while (! st. empty()) {
267+ TreeNode node = st. peek();
268+ if (node != null ) {
269+ st. pop(); // 将该节点弹出,避免重复操作,下面再将右中左节点添加到栈中(中序遍历-左中右,入栈顺序右中左)
270+ if (node. right != null ) st. push(node. right); // 添加右节点(空节点不入栈)
271+ st. push(node); // 添加中节点
272+ st. push(null ); // 中节点访问过,但是还没有处理,加入空节点做为标记。
273+ if (node. left != null ) st. push(node. left); // 添加左节点(空节点不入栈)
274+ } else { // 只有遇到空节点的时候,才将下一个节点放进结果集
275+ st. pop(); // 将空节点弹出
276+ node = st. peek(); // 重新取出栈中元素
277+ st. pop();
278+ result. add(node. val); // 加入到结果集
279+ }
279280 }
281+ return result;
280282 }
281- return result;
282- }
283283}
284284```
285285
286- 迭代法后序遍历代码如下:
286+ 迭代法后序遍历(空指针标记法)代码如下:
287287``` java
288288class Solution {
289289 public List<Integer > postorderTraversal (TreeNode root ) {
@@ -294,11 +294,10 @@ class Solution {
294294 TreeNode node = st. peek();
295295 if (node != null ) {
296296 st. pop(); // 将该节点弹出,避免重复操作,下面再将中右左节点添加到栈中(后序遍历-左右中,入栈顺序中右左)
297- st. push(node); // 添加中节点
297+ st. push(node); // 添加中节点
298298 st. push(null ); // 中节点访问过,但是还没有处理,加入空节点做为标记。
299299 if (node. right!= null ) st. push(node. right); // 添加右节点(空节点不入栈)
300- if (node. left!= null ) st. push(node. left); // 添加左节点(空节点不入栈)
301-
300+ if (node. left!= null ) st. push(node. left); // 添加左节点(空节点不入栈)
302301 } else { // 只有遇到空节点的时候,才将下一个节点放进结果集
303302 st. pop(); // 将空节点弹出
304303 node = st. peek(); // 重新取出栈中元素
@@ -311,6 +310,150 @@ class Solution {
311310}
312311```
313312
313+ 迭代法前序遍历(boolean 标记法)代码如下:
314+
315+ ``` java
316+ // LeetCode提交时注意添加导包语句
317+ import java.util.AbstractMap.SimpleEntry ;
318+
319+ class Solution {
320+ public List<Integer > preorderTraversal (TreeNode root ) {
321+ List<Integer > result = new ArrayList<> ();
322+ if (root == null )
323+ return result;
324+ Stack<SimpleEntry<TreeNode , Boolean > > stack = new Stack<> ();
325+ stack. push(new SimpleEntry<> (root, false ));
326+
327+ while (! stack. isEmpty()) {
328+ TreeNode node = stack. peek(). getKey();
329+ // 多加一个visited参数,使“迭代统一写法”成为一件简单的事
330+ boolean visited = stack. peek(). getValue();
331+ stack. pop();
332+
333+ // visited为True,表示该节点和两个儿子位次之前已经安排过了,现在可以收割节点了
334+ if (visited) {
335+ result. add(node. val);
336+ continue ;
337+ }
338+
339+ // visited当前为false, 表示初次访问本节点,此次访问的目的是“把自己和两个儿子在栈中安排好位次”
340+
341+ // 前序遍历是'中左右',右儿子最先入栈,最后出栈
342+ if (node. right != null ) {
343+ stack. push(new SimpleEntry<> (node. right, false ));
344+ }
345+
346+ // 左儿子位置居中
347+ if (node. left != null ) {
348+ stack. push(new SimpleEntry<> (node. left, false ));
349+ }
350+
351+ // 节点自己最后入栈,最先出栈
352+ // 同时,设置 visited 为 true,表示下次再访问本节点时,允许收割
353+ stack. push(new SimpleEntry<> (node, true ));
354+ }
355+
356+ return result;
357+ }
358+ }
359+ ```
360+
361+ 迭代法中序遍历(boolean 标记法)代码如下:
362+
363+ ``` java
364+ // LeetCode提交时注意添加导包语句
365+ import java.util.AbstractMap.SimpleEntry ;
366+
367+ class Solution {
368+ public List<Integer > inorderTraversal (TreeNode root ) {
369+ List<Integer > result = new ArrayList<> ();
370+ if (root == null )
371+ return result;
372+ Stack<SimpleEntry<TreeNode , Boolean > > stack = new Stack<> ();
373+ stack. push(new SimpleEntry<> (root, false ));
374+
375+ while (! stack. isEmpty()) {
376+ TreeNode node = stack. peek(). getKey();
377+ // 多加一个visited参数,使“迭代统一写法”成为一件简单的事
378+ boolean visited = stack. peek(). getValue();
379+ stack. pop();
380+
381+ // visited为True,表示该节点和两个儿子位次之前已经安排过了,现在可以收割节点了
382+ if (visited) {
383+ result. add(node. val);
384+ continue ;
385+ }
386+
387+ // visited当前为false, 表示初次访问本节点,此次访问的目的是“把自己和两个儿子在栈中安排好位次”
388+
389+ // 中序遍历是'左中右',右儿子最先入栈,最后出栈
390+ if (node. right != null ) {
391+ stack. push(new SimpleEntry<> (node. right, false ));
392+ }
393+
394+ // 把自己加回到栈中,位置居中
395+ // 同时,设置 visited 为 true,表示下次再访问本节点时,允许收割
396+ stack. push(new SimpleEntry<> (node, true ));
397+
398+ // 左儿子最后入栈,最先出栈
399+ if (node. left != null ) {
400+ stack. push(new SimpleEntry<> (node. left, false ));
401+ }
402+ }
403+
404+ return result;
405+ }
406+ }
407+ ```
408+
409+ 迭代法后序遍历(boolean 标记法)代码如下:
410+
411+ ``` java
412+ // LeetCode提交时注意添加导包语句
413+ import java.util.AbstractMap.SimpleEntry ;
414+
415+ class Solution {
416+ public List<Integer > postorderTraversal (TreeNode root ) {
417+ List<Integer > result = new ArrayList<> ();
418+ if (root == null )
419+ return result;
420+ Stack<SimpleEntry<TreeNode , Boolean > > stack = new Stack<> ();
421+ stack. push(new SimpleEntry<> (root, false ));
422+
423+ while (! stack. isEmpty()) {
424+ TreeNode node = stack. peek(). getKey();
425+ // 多加一个visited参数,使“迭代统一写法”成为一件简单的事
426+ boolean visited = stack. peek(). getValue();
427+ stack. pop();
428+
429+ // visited为True,表示该节点和两个儿子位次之前已经安排过了,现在可以收割节点了
430+ if (visited) {
431+ result. add(node. val);
432+ continue ;
433+ }
434+
435+ // visited当前为false, 表示初次访问本节点,此次访问的目的是“把自己和两个儿子在栈中安排好位次”
436+
437+ // 后序遍历是'左右中',节点自己最先入栈,最后出栈
438+ // 同时,设置 visited 为 true,表示下次再访问本节点时,允许收割
439+ stack. push(new SimpleEntry<> (node, true ));
440+
441+ // 右儿子位置居中
442+ if (node. right != null ) {
443+ stack. push(new SimpleEntry<> (node. right, false ));
444+ }
445+
446+ // 左儿子最后入栈,最先出栈
447+ if (node. left != null ) {
448+ stack. push(new SimpleEntry<> (node. left, false ));
449+ }
450+ }
451+
452+ return result;
453+ }
454+ }
455+ ```
456+
314457### Python:
315458
316459> 迭代法前序遍历(空指针标记法):
0 commit comments