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