Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Update 二叉树的统一迭代法.md #2906

Open
wants to merge 1 commit into
base: master
Choose a base branch
from
Open
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
199 changes: 171 additions & 28 deletions problems/二叉树的统一迭代法.md
Original file line number Diff line number Diff line change
@@ -227,7 +227,8 @@ public:
## 其他语言版本

### Java:
迭代法前序遍历代码如下:

迭代法前序遍历(空指针标记法)代码如下:

```java
class Solution {
@@ -239,11 +240,10 @@ class Solution {
TreeNode node = st.peek();
if (node != null) {
st.pop(); // 将该节点弹出,避免重复操作,下面再将右左中节点添加到栈中(前序遍历-中左右,入栈顺序右左中)
if (node.right!=null) st.push(node.right); // 添加右节点(空节点不入栈)
if (node.left!=null) st.push(node.left); // 添加左节点(空节点不入栈)
st.push(node); // 添加中节点
if (node.right != null) st.push(node.right); // 添加右节点(空节点不入栈)
if (node.left != null) st.push(node.left); // 添加左节点(空节点不入栈)
st.push(node); // 添加中节点
st.push(null); // 中节点访问过,但是还没有处理,加入空节点做为标记。

} else { // 只有遇到空节点的时候,才将下一个节点放进结果集
st.pop(); // 将空节点弹出
node = st.peek(); // 重新取出栈中元素
@@ -256,34 +256,34 @@ class Solution {
}
```

迭代法中序遍历代码如下:
迭代法中序遍历(空指针标记法)代码如下:
```java
class Solution {
public List<Integer> inorderTraversal(TreeNode root) {
public List<Integer> inorderTraversal(TreeNode root) {
List<Integer> result = new LinkedList<>();
Stack<TreeNode> st = new Stack<>();
if (root != null) st.push(root);
while (!st.empty()) {
TreeNode node = st.peek();
if (node != null) {
st.pop(); // 将该节点弹出,避免重复操作,下面再将右中左节点添加到栈中(中序遍历-左中右,入栈顺序右中左)
if (node.right!=null) st.push(node.right); // 添加右节点(空节点不入栈)
st.push(node); // 添加中节点
st.push(null); // 中节点访问过,但是还没有处理,加入空节点做为标记。
if (node.left!=null) st.push(node.left); // 添加左节点(空节点不入栈)
} else { // 只有遇到空节点的时候,才将下一个节点放进结果集
st.pop(); // 将空节点弹出
node = st.peek(); // 重新取出栈中元素
st.pop();
result.add(node.val); // 加入到结果集
Stack<TreeNode> st = new Stack<>();
if (root != null) st.push(root);
while (!st.empty()) {
TreeNode node = st.peek();
if (node != null) {
st.pop(); // 将该节点弹出,避免重复操作,下面再将右中左节点添加到栈中(中序遍历-左中右,入栈顺序右中左)
if (node.right != null) st.push(node.right); // 添加右节点(空节点不入栈)
st.push(node); // 添加中节点
st.push(null); // 中节点访问过,但是还没有处理,加入空节点做为标记。
if (node.left != null) st.push(node.left); // 添加左节点(空节点不入栈)
} else { // 只有遇到空节点的时候,才将下一个节点放进结果集
st.pop(); // 将空节点弹出
node = st.peek(); // 重新取出栈中元素
st.pop();
result.add(node.val); // 加入到结果集
}
}
return result;
}
return result;
}
}
```

迭代法后序遍历代码如下:
迭代法后序遍历(空指针标记法)代码如下:
```java
class Solution {
public List<Integer> postorderTraversal(TreeNode root) {
@@ -294,11 +294,10 @@ class Solution {
TreeNode node = st.peek();
if (node != null) {
st.pop(); // 将该节点弹出,避免重复操作,下面再将中右左节点添加到栈中(后序遍历-左右中,入栈顺序中右左)
st.push(node); // 添加中节点
st.push(node); // 添加中节点
st.push(null); // 中节点访问过,但是还没有处理,加入空节点做为标记。
if (node.right!=null) st.push(node.right); // 添加右节点(空节点不入栈)
if (node.left!=null) st.push(node.left); // 添加左节点(空节点不入栈)

if (node.left!=null) st.push(node.left); // 添加左节点(空节点不入栈)
} else { // 只有遇到空节点的时候,才将下一个节点放进结果集
st.pop(); // 将空节点弹出
node = st.peek(); // 重新取出栈中元素
@@ -311,6 +310,150 @@ class Solution {
}
```

迭代法前序遍历(boolean 标记法)代码如下:

```java
// LeetCode提交时注意添加导包语句
import java.util.AbstractMap.SimpleEntry;

class Solution {
public List<Integer> preorderTraversal(TreeNode root) {
List<Integer> result = new ArrayList<>();
if (root == null)
return result;
Stack<SimpleEntry<TreeNode, Boolean>> stack = new Stack<>();
stack.push(new SimpleEntry<>(root, false));

while (!stack.isEmpty()) {
TreeNode node = stack.peek().getKey();
// 多加一个visited参数,使“迭代统一写法”成为一件简单的事
boolean visited = stack.peek().getValue();
stack.pop();

// visited为True,表示该节点和两个儿子位次之前已经安排过了,现在可以收割节点了
if (visited) {
result.add(node.val);
continue;
}

// visited当前为false, 表示初次访问本节点,此次访问的目的是“把自己和两个儿子在栈中安排好位次”

// 前序遍历是'中左右',右儿子最先入栈,最后出栈
if (node.right != null) {
stack.push(new SimpleEntry<>(node.right, false));
}

// 左儿子位置居中
if (node.left != null) {
stack.push(new SimpleEntry<>(node.left, false));
}

// 节点自己最后入栈,最先出栈
// 同时,设置 visited 为 true,表示下次再访问本节点时,允许收割
stack.push(new SimpleEntry<>(node, true));
}

return result;
}
}
```

迭代法中序遍历(boolean 标记法)代码如下:

```java
// LeetCode提交时注意添加导包语句
import java.util.AbstractMap.SimpleEntry;

class Solution {
public List<Integer> inorderTraversal(TreeNode root) {
List<Integer> result = new ArrayList<>();
if (root == null)
return result;
Stack<SimpleEntry<TreeNode, Boolean>> stack = new Stack<>();
stack.push(new SimpleEntry<>(root, false));

while (!stack.isEmpty()) {
TreeNode node = stack.peek().getKey();
// 多加一个visited参数,使“迭代统一写法”成为一件简单的事
boolean visited = stack.peek().getValue();
stack.pop();

// visited为True,表示该节点和两个儿子位次之前已经安排过了,现在可以收割节点了
if (visited) {
result.add(node.val);
continue;
}

// visited当前为false, 表示初次访问本节点,此次访问的目的是“把自己和两个儿子在栈中安排好位次”

// 中序遍历是'左中右',右儿子最先入栈,最后出栈
if (node.right != null) {
stack.push(new SimpleEntry<>(node.right, false));
}

// 把自己加回到栈中,位置居中
// 同时,设置 visited 为 true,表示下次再访问本节点时,允许收割
stack.push(new SimpleEntry<>(node, true));

// 左儿子最后入栈,最先出栈
if (node.left != null) {
stack.push(new SimpleEntry<>(node.left, false));
}
}

return result;
}
}
```

迭代法后序遍历(boolean 标记法)代码如下:

```java
// LeetCode提交时注意添加导包语句
import java.util.AbstractMap.SimpleEntry;

class Solution {
public List<Integer> postorderTraversal(TreeNode root) {
List<Integer> result = new ArrayList<>();
if (root == null)
return result;
Stack<SimpleEntry<TreeNode, Boolean>> stack = new Stack<>();
stack.push(new SimpleEntry<>(root, false));

while (!stack.isEmpty()) {
TreeNode node = stack.peek().getKey();
// 多加一个visited参数,使“迭代统一写法”成为一件简单的事
boolean visited = stack.peek().getValue();
stack.pop();

// visited为True,表示该节点和两个儿子位次之前已经安排过了,现在可以收割节点了
if (visited) {
result.add(node.val);
continue;
}

// visited当前为false, 表示初次访问本节点,此次访问的目的是“把自己和两个儿子在栈中安排好位次”

// 后序遍历是'左右中',节点自己最先入栈,最后出栈
// 同时,设置 visited 为 true,表示下次再访问本节点时,允许收割
stack.push(new SimpleEntry<>(node, true));

// 右儿子位置居中
if (node.right != null) {
stack.push(new SimpleEntry<>(node.right, false));
}

// 左儿子最后入栈,最先出栈
if (node.left != null) {
stack.push(new SimpleEntry<>(node.left, false));
}
}

return result;
}
}
```

### Python:

> 迭代法前序遍历(空指针标记法):