94. 二叉树的中序遍历

题目描述:

给定一个二叉树的根节点 root ,返回它的 中序 遍历。

示例 1:


输入:root = [1,null,2,3]
输出:[1,3,2]
示例 2:

输入:root = []
输出:[]
示例 3:

输入:root = [1]
输出:[1]
示例 4:


输入:root = [1,2]
输出:[2,1]
示例 5:


输入:root = [1,null,2]
输出:[1,2]

提示:

树中节点数目在范围 [0, 100] 内
-100 <= Node.val <= 100
 

进阶: 递归算法很简单,你可以通过迭代算法完成吗?

来源:力扣(LeetCode)
链接:https://leetcode-cn.com/problems/binary-tree-inorder-traversal
著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。

分析:

经典递归,没啥说的,几行代码的事。代码如下:

/**
 * Definition for a binary tree node.
 * struct TreeNode {
 *     int val;
 *     TreeNode *left;
 *     TreeNode *right;
 *     TreeNode() : val(0), left(nullptr), right(nullptr) {}
 *     TreeNode(int x) : val(x), left(nullptr), right(nullptr) {}
 *     TreeNode(int x, TreeNode *left, TreeNode *right) : val(x), left(left), right(right) {}
 * };
 */
class Solution {
public:
    // 最终返回的中序遍历结果
    vector<int> res;
    vector<int> inorderTraversal(TreeNode* root) {
        // 节点为空,直接返回
        if(root==NULL) return res;
        // 遍历左子树
        inorderTraversal(root->left);
        // 根节点加入res
        res.push_back(root->val);
        // 遍历右子树
        inorderTraversal(root->right);
        // 返回结果res
        return res;
    }
};

ps:题目说还有迭代算法,将来可以试试。 

迭代算法,就是不使用递归来完成二叉树的中序遍历。根本思路在于使用栈来模拟递归操作。

递归程序,是从上往下访问的,这一点是无法改变的。即使使用迭代,访问顺序也一定是从上往下,只是我们可以在从上往下访问的过程中,让上层节点先存入栈,等到按照顺序访问到他们时再出栈。

        从根节点开始,一直沿着左节点遍历,遇到的节点全部存入栈,直到左节点为NULL。

        开始循环:从栈顶拿出第一个元素,该元素就是中序遍历访问到的第一个节点,该节点存入res。按照中序遍历的顺序,该节点的左节点已经访问过了(为NULL),根节点也访问过了(它自身),只剩下右节点没有访问过了。所以,按照顺序,该访问根节点的右子树了(不是右节点,因为按照中序遍历的顺序,下个该访问的节点是该节点右子树中最左边那个节点)。访问右节点,右节点作为根节点,一直沿着左节点遍历,遇到的节点全部存入栈,直到左节点为NULL。开始下一轮循环。

代码如下:

/**
 * Definition for a binary tree node.
 * struct TreeNode {
 *     int val;
 *     TreeNode *left;
 *     TreeNode *right;
 *     TreeNode() : val(0), left(nullptr), right(nullptr) {}
 *     TreeNode(int x) : val(x), left(nullptr), right(nullptr) {}
 *     TreeNode(int x, TreeNode *left, TreeNode *right) : val(x), left(left), right(right) {}
 * };
 */
class Solution {
public:
    vector<int> res;
    stack<TreeNode* > s;
    vector<int> inorderTraversal(TreeNode* root) {
        // 从根节点开始的左节点全部入栈
        while(root!=NULL)
        {
           s.push(root);
           root=root->left;
        }
        // 栈不为空,就进行循环
         while(!s.empty())
        {
            // 栈顶元素出栈
            if(!s.empty())
            {
                root=s.top();
                s.pop();
            }
            // 该元素进入res
            res.push_back(root->val);
            // 访问该元素的右节点
            root=root->right;
            // 右节点的左节点全部入栈
             while(root!=NULL)
            {
               s.push(root);
               root=root->left;
            }
        }
        // 返回res
        return res;
    }
   
};

同时附上二叉树的前序遍历的迭代解法(不是基于leetcode写的,是一个完整的代码):

#include <iostream>
#include "vector"
#include "stack"
using namespace std;
struct TreeNode {
    int val;
    TreeNode *left;
    TreeNode *right;
    TreeNode(int x) : val(x), left(NULL), right(NULL) {}
};

vector<int> res;
stack<TreeNode*> s;
void f(TreeNode * root);
int main()
{
//    构建一个二叉树
    TreeNode *root=new TreeNode(1);
    root->left=new TreeNode(2);
    root->right=new TreeNode(3);
    root->left->left=new TreeNode(4);
    root->left->right=new TreeNode(5);
    root->right->left=new TreeNode(6);
    root->right->right=new TreeNode(7);

    f(root);
    for(int i=0;i<res.size();i++)
    {
        cout<<res[i]<<" ";
    }
    return 0;
}
void f(TreeNode * root)
{
//    存入根节点
    s.push(root);
    while(!s.empty())
    {
//        取出栈顶节点
        TreeNode *temp=s.top();
        s.pop();
//        如果栈顶节点不为空
        if(temp)
        {
//            该节点加入res
            res.push_back(temp->val);
            //            该节点的左右子节点入栈
            s.push(temp->right);
            s.push(temp->left);
        }

    }

}









  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值