题目地址:https://leetcode-cn.com/problems/binary-tree-inorder-traversal/
给定一个二叉树,返回它的中序 遍历。
示例:
输入: [1,null,2,3]
1
\
2
/
3
输出: [1,3,2]
进阶: 递归算法很简单,你可以通过迭代算法完成吗?
我们看一个例子:
4
/ \
2 6
/ \ / \
1 3 5 7
步骤 | 判断条件 | 操作 | 栈 | 弹出数字 | 队列 |
---|---|---|---|---|---|
1 | 节点4不空 | 压入4 | 4 | ||
2 | 节点2不空 | 压入2 | 4,2 | ||
3 | 节点1不空 | 压入1 | 4,2,1 | ||
4 | 节点1左孩子空,栈不空 | 退栈,记录栈顶元素1的右孩子 | 4,2 | 1 | 1 |
5 | 节点1的右孩子为空 | 退栈,记录栈顶元素2的右孩子3 | 4 | 2 | 1,2 |
6 | 右孩子3不空 | 压入3 | 4,3 | 1,2 | |
7 | 节点3左孩子空,栈不空 | 退栈,记录栈顶元素3的右孩子 | 4 | 3 | 1,2,3 |
8 | 节点3右孩子空 | 退栈,记录栈顶元素4的右孩子 | 4 | 1,2,3,4 | |
9 | 栈空,节点4右孩子6不空 | 压入6 | 6 | 1,2,3,4 | |
10 | 节点5不空 | 压入5 | 6,5 | 1,2,3,4 | |
11 | 节点5左孩子空 | 退栈,记录栈顶元素5的右孩子 | 6 | 5 | 1,2,3,4,5 |
12 | 节点5右孩子空 | 退栈,记录栈顶元素6的右孩子 | 6 | 1,2,3,4,5,6 | |
13 | 节点6的右孩子7不空 | 压入7 | 7 | 1,2,3,4,5,6 | |
14 | 节点7的左孩子空 | 退栈,记录栈顶元素7的右孩子 | 7 | 1,2,3,4,5,6,7 | |
14 | 节点7的右孩子空,栈空 | 结束 | 1,2,3,4,5,6,7 |
思路
- 栈不空或者root不空时,继续2,否则终止
- 沿着root左孩子遍历,依次入栈,直到节点为空
- 记录栈顶top,栈pop,将top的右孩子设为root,继续1
难点:
利用迭代遍历树时,都要用到栈来辅助解决回溯到父节点的问题。
此解法中的一个trick:栈顶元素的右孩子节点为空,就继续退栈。
参考代码
/**
* Definition for a binary tree node.
* struct TreeNode {
* int val;
* TreeNode *left;
* TreeNode *right;
* TreeNode(int x) : val(x), left(NULL), right(NULL) {}
* };
*/
class Solution {
public:
vector<int> inorderTraversal(TreeNode* root) {
vector<int> result;
stack<TreeNode *> s;
TreeNode *p = root;
while (!s.empty() || p) {
if (p) {
s.push(p);
p = p->left;
continue;
}
TreeNode *q = s.top();
s.pop();
result.push_back(q->val);
p = q->right;
}
return result;
}
};