二叉树中序遍历_二叉树的中序序列

二叉树中序遍历_二叉树的中序序列二叉树是一种重要的数据结构,对于二叉树的遍历也很重要。这里通过三种方法简单介绍一下二叉树的中序遍历。中序遍历就是先遍历二叉树的左子树,然后遍历根节点,最后遍历右子树。例如下面的二叉树,中序遍历的结果如下:[5,10,6,15,2]对于中序遍历,直观上的结果就是将二叉树所有节点投影到下面的一条直线上,得到的顺序就是二叉树的中序遍历结果。1、递归法递归方法是最容易想到的方法。递归调用遍历方法先遍历左子

大家好,又见面了,我是你们的朋友全栈君。如果您正在找激活码,请点击查看最新教程,关注关注公众号 “全栈程序员社区” 获取激活教程,可能之前旧版本教程已经失效.最新Idea2022.1教程亲测有效,一键激活。

Jetbrains全系列IDE使用 1年只要46元 售后保障 童叟无欺

二叉树是一种重要的数据结构,对二叉树的遍历也很重要。这里简单介绍三种二叉树中序遍历的方法。二叉树的中序遍历就是首先遍历左子树,然后访问当前节点,最后遍历右子树。对于下面的二叉树,中序遍历结果如下:

二叉树中序遍历_二叉树的中序序列

结果:[5,10,6,15,2]

直观来看,二叉树的中序遍历就是将节点投影到一条水平的坐标上。如图:

二叉树中序遍历_二叉树的中序序列

1、递归法

这是思路最简单的方法,容易想到并且容易实现。递归的终止条件是当前节点是否为空。首先递归调用遍历左子树,然后访问当前节点,最后递归调用右子树。代码如下:

//recursive
class Solution1 {
public:
    vector<int> inorderTraversal(TreeNode* root) {
        vector<int> ret;
        if(root==NULL)return ret;
        inorderHelper(ret,root);
        return ret;
    }
private:
    void inorderHelper(vector<int>& ret,TreeNode* root)
    {
        if(root==NULL)return;
        inorderHelper(ret,root->left);
        ret.push_back(root->val);
        inorderHelper(ret,root->right);
    }
};

2、迭代法

在迭代方法中,从根节点开始找二叉树的最左节点,将走过的节点保存在一个栈中,找到最左节点后访问,对于每个节点来说,它都是以自己为根的子树的根节点,访问完之后就可以转到右儿子上了。代码如下:

//iterate,using a stack
class Solution2 {
public:
    vector<int> inorderTraversal(TreeNode* root) {
        vector<int> ret;
        if(root==NULL)return ret;
        TreeNode *curr=root;
        stack<TreeNode*> st;
        while(!st.empty()||curr!=NULL)
        {
            while(curr!=NULL)
            {
                st.push(curr);
                curr=curr->left;
            }
            curr=st.top();
            st.pop();
            ret.push_back(curr->val);
            curr=curr->right;
        }
        return ret;
    }
};

这种方法时间复杂度是O(n),空间复杂度也是O(n)。

3、Morris法

这种方法是Morris发明的,看完之后感觉精妙无比。这种方法不使用递归,不使用栈,O(1)的空间复杂度完成二叉树的遍历。这种方法的基本思路就是将所有右儿子为NULL的节点的右儿子指向后继节点(对于右儿子不为空的节点,右儿子就是接下来要访问的节点)。这样,对于任意一个节点,当访问完它后,它的右儿子已经指向了下一个该访问的节点。对于最右节点,不需要进行这样的操作。注意,这样的操作是在遍历的时候完成的,完成访问节点后会把树还原。整个循环的判断条件为当前节点是否为空。例如上面的二叉树,遍历过程如下(根据当前节点c的位置):

(1)当前节点为10,因为左儿子非空,不能访问,找到c的左子树的最右节点p:

二叉树中序遍历_二叉树的中序序列

结果:[]

(2)找节点c的左子树的最右节点有两种终止条件,一种右儿子为空,一种右儿子指向当前节点。下面是右儿子为空的情况,这种情况先要构造,将节点p的右儿子指向后继节点c,然后c下移:

二叉树中序遍历_二叉树的中序序列

结果:[]

(3)当前节点c的左儿子为空,进行访问。访问后将c指向右儿子(即后继节点):

二叉树中序遍历_二叉树的中序序列

结果:[5]

(4)继续寻找左子树的最右节点,这次的终止条件是最右节点为当前节点。这说明当前节点的左子树遍历完毕,访问当前节点后,还原二叉树,将当前节点指向后继节点:

二叉树中序遍历_二叉树的中序序列

结果:[5,10]

(5)重复上述过程,直到c指向整棵二叉树的最右节点:

二叉树中序遍历_二叉树的中序序列

左儿子为空,进行访问,c转到右儿子。右儿子为空,不满足判断条件,循环结束,遍历完成。结果如下:

[5,10,6,15,2]

这就是Morris方法,时间复杂度为O(n),空间复杂度是O(1)。代码如下:

//Morris traversal,without a stack
class Solution3 {
public:
    vector<int> inorderTraversal(TreeNode* root) {
        vector<int> ret;
        if(root==NULL)return ret;
        TreeNode *curr=root;
        TreeNode *pre;
        while(curr)
        {
            if(curr->left==NULL)
            {
                ret.push_back(curr->val);
                curr=curr->right;
            }
            else
            {
                pre=curr->left;
                while(pre->right&&pre->right!=curr)
                    pre=pre->right;
                if(pre->right==NULL)
                {
                    pre->right=curr;
                    curr=curr->left;
                }
                else
                {
                    ret.push_back(curr->val);
                    pre->right=NULL;
                    curr=curr->right;
                }
            }
        }
        return ret;
    }
};

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请联系我们举报,一经查实,本站将立刻删除。

发布者:全栈程序员-站长,转载请注明出处:https://javaforall.net/193806.html原文链接:https://javaforall.net

(0)
全栈程序员-站长的头像全栈程序员-站长


相关推荐

  • 如何去除IDEA中xml文件的屎黄色背景

    点击上方“全栈程序员社区”,星标公众号 重磅干货,第一时间送达 作者:翟凤玺 blog.csdn.net/u010318957/article/details/72459183 导…

    2021年6月25日
    78
  • 软件设计——UML类图详解「建议收藏」

    一:UML类图思维导图 思维导图地址:http://naotu.baidu.com/file/df1cb03489378d2a541d3d8d181399da?token=2eb1feb8006fa607 密码:33bZ二:详细分析和介绍下面就从上面的思维导图开始,详细的介绍UML类图! 在讲解之前请看关系线条图(一定要牢记): 1、 什么是UML,概念是什么? 统一建模语言

    2022年2月25日
    75
  • c++反编译工具_pc下载软件

    c++反编译工具_pc下载软件  昨天在逆向某App的时候,发现有个加密工具类中的native方法是用C语言编写的,隐藏在so文件中。某大佬推荐逆向工具unidbg,能在pc端直接调用so文件中的函数,最终成功解决了问题。逆向工具之unidbg目录一、`unidbg`引入二、`unidbg`概述三、`unidbg`使用姿势1、下载`unidbg`项目2、导入到IDEA中①、解压压缩包②、打开`IDEA`,导入解压的项目3、测试`unidbg`4、运行自己的`so`文件①、编写`EncryptUtilsJni`类②、参数说明③、执行结果

    2022年9月18日
    4
  • 完整软件研发流程「建议收藏」

    完整软件研发流程「建议收藏」软件产品开发流程:下图所示的是一个软件产品开发大体上所需要经历的全部流程:1、启动在项目启动阶段,主要确定项目的目标及其可行性。我们需要对项目的背景、干系人、解决的问题等等进行了解。并编制项目章程和组建项目团队,包括:产品经理、架构工程师、UI工程师、开发工程师、测试工程师等。完成以上准备工作之后,召开项目启动会,启动会结束则进入下一步的工作。2、规划…

    2022年6月16日
    31
  • 使用python创建数组的方法[通俗易懂]

    使用python创建数组的方法[通俗易懂]本文介绍两种在python里创建数组的方法。第一种是通过字典直接创建,第二种是通过转换列表得到数组。方法1.字典创建(1)导入功能(2)创立字典(3)将字典带上索引转换为数组代码示例如下:importnumpyasnpimportpandasaspddata={“name”:[‘xiaozhang’,‘xiaoli’,‘lily’,‘tony’],“sex”:[‘bo…

    2022年5月2日
    53
  • RestFul风格详解

    RestFul风格详解文章目录一、前言二、什么是RestFul风格三、传统风格与RestFul风格对比1.传统方式操作资源2.RestFul方式操作资源四、RestFul代码演示1.代码展示2.拓展情景五、使用method属性指定请求类型六、总结一、前言该技术博客总结与狂神说SpringMVC课程二、什么是RestFul风格Restful就是一个资源定位、资源操作的风格。不是标准也不是协议,只是一种风格。基于这个风格设计的软件可以更简洁,更有层次,更易于实现缓存等机制。资源:互联网所有的事物都可以被抽象为资源资源

    2022年6月16日
    23

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注

关注全栈程序员社区公众号