94. 二叉树的中序遍历
最开始的代码,用了递归,虽然通过了,但是很别扭。
vector<int> ans;
class Solution {
public:
vector<int> inorderTraversal(TreeNode* root) {
ans.clear();
inorder(root);
return ans;
}
void inorder(TreeNode* root){
if(root==NULL)return;
inorder(root->left);
ans.push_back(root->val);
inorder(root->right);
}
};
我的代码有两点问题:
- 没有用迭代的方式解决,而是用了简单的递归。
- 我在递归里用了类似全局变量的东西,很别扭。
先解决递归怎么写的问题。可以把 ans 作为引用参数传入需要递归的函数里。
class Solution {
private:
void rec(TreeNode* root,vector<int> &ret){
if(root != NULL){
rec(root->left,ret);
ret.push_back(root->val);
rec(root->right,ret);
}
}
public:
vector<int> postorderTraversal(TreeNode* root) {
vector<int> ret;
rec(root,ret);
return ret;
}
};
再说迭代怎么解决。这篇文章解释的比较清楚。
选择栈的原因:中序遍历,原则是先走到的结点后访问,后走到的结点先访问,这显然是栈的结构。
具体步骤:
- 找到最左节点:如果当前节点有左子树,则把该节点入栈,接着把左子树的根节点作为当前节点。直到当前节点没有左子树为止。
- 如果当前节点没有左子树时,则访问(输出)该节点。
- 此时再判断,如果当前节点有右子树,则把右子树的根节点作为当前节点。重复第1步。
- 如果没有右子树,则让此时的栈顶元素出栈,访问(输出)该节点,并作为当前节点。
- 重复1、2,直到栈空。
图示如下:
原理的代码如下:
BiTNode *GoFarLeft(BiTNode *T, stack<BiTNode *> &s)//一直向左走函数
{
if (T == NULL)
{
return NULL;
}
//如果T有左孩子 入栈
while (T->lchild)
{
s.push(T);
T= T->lchild;//一直往左走
}
return T; //找到一个没有左孩子的节点,就是中序遍历的起点
}
void InOrder2(BiTNode *T)
{
stack<BiTNode *>s;
BiTNode *t = GoFarLeft(T, s); //中序遍历的起点
while(t)
{
printf("%d ", t->data);
if (t->rchild) //如果有右孩子 重复12步骤
{
t = GoFarLeft(T->rchild, s);
}
else if (!s.empty()) //如果没有右孩子,说明该节点的树放完毕,需要返回。
{
t = s.top(); //非空就从栈顶拿元素
s.pop();
}
else //如果没有右孩子,并且栈为空 t = NULL;
{
t = NULL;
}
}
}
根据原理,解答本题的简化后的代码如下:
vector<int> ans;
class Solution {
public:
vector<int> inorderTraversal(TreeNode* root) {
stack<TreeNode*> s;
vector<int> ans;
while(root||!s.empty()){
//找到最左节点
while(root){
s.push(root);
root=root->left;
}
//访问该节点
root=s.top();
s.pop();
ans.push_back(root->val);
//把右子树根节点作为当前节点。
root=root->right;
}
return ans;
}
};
题目:
给定一个二叉树,返回它的中序 遍历。
示例:
输入: [1,null,2,3]
1
2
/
3
输出: [1,3,2]
进阶: 递归算法很简单,你可以通过迭代算法完成吗?