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

二叉树中序遍历_二叉树的中序序列二叉树是一种重要的数据结构,对于二叉树的遍历也很重要。这里通过三种方法简单介绍一下二叉树的中序遍历。中序遍历就是先遍历二叉树的左子树,然后遍历根节点,最后遍历右子树。例如下面的二叉树,中序遍历的结果如下:[5,10,6,15,2]对于中序遍历,直观上的结果就是将二叉树所有节点投影到下面的一条直线上,得到的顺序就是二叉树的中序遍历结果。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)
全栈程序员-站长的头像全栈程序员-站长

相关推荐

  • css漂浮广告代码_html浮动窗口怎么做

    css漂浮广告代码_html浮动窗口怎么做1.html部分复制代码代码如下:blog_floatdiv.html我是浮动的div浮动的div浮动的div浮动的div浮动的div浮动的div浮动的div浮动的div浮动的div浮动的div浮动的div浮动的div浮动的div浮动的div浮动的div浮动的div浮动的div浮动的div浮动的div浮动的div浮动的div浮动的div浮动的div浮动的div浮动的div浮动的div浮动的div…

    2022年9月16日
  • 粒子群算法(PSO)的Python实现(求解多元函数的极值)

    粒子群算法(PSO)的Python实现(求解多元函数的极值)PSO是寻优算法中比较简单的一种,本文用Python简单实现了PSO算法,用来求解一个五元函数的最大值,并与MATLAB的fmincon函数的运行结果做比较。

    2022年4月29日
  • ROS安装教程|从零开始[通俗易懂]

    ROS安装教程|从零开始[通俗易懂]前两天把自己的ROS搞坏了,不知道咋修复了,只好重装一次。想到大家可能还有从来没接触过ROS的,不知道怎么安装,我就记录一下这次的重装过程安装VMware,这个我已经装了,就不细说了,管家公众号上有安装教程 下载ubuntu镜像文件Indexof/ubuntu-releases/18.04.6/|清华大学开源软件镜像站|TsinghuaOpenSourceMirrorIndexof/ubuntu-releases/18.04.6/|清华大学开源软件镜像站,致力于为国内和校

    2022年9月3日
  • 【云原生 • Kubernetes】搭建 k8s 集群(Kubeadm 方式)[通俗易懂]

    【云原生 • Kubernetes】搭建 k8s 集群(Kubeadm 方式)[通俗易懂]kubeadm方式搭建k8s集群,包含详细步骤及解析。

    2022年10月15日
  • potplayer设置快捷键[通俗易懂]

    potplayer设置快捷键[通俗易懂]引言potplayer是一款非常好用的播放器,功能齐全,且无广告,但是我在使用中按错快捷键ctrl+spotplayer就开启了一个叫采集器的东西,非常难受.话说和ctrl+s这么高频使用的快捷键冲突也太令人恼火了吧解决方法在播放区域右键鼠标打开菜单,找到选项按钮按钮????找到快捷键选项卡????添加快捷键,输入ctrl+s,然后选择未定义指令,确定,大功告成!…

    2022年5月22日
  • oncontextmenu属性_360兼容模式

    oncontextmenu属性_360兼容模式公司的网站内容都是一些专业性很强的内容,而且内容都是花钱买来的,所以不想让别人轻而易举的复制过去,就尝试使用js控制一下,但是找了很多js代码,都是不支持firefox,如下取消选取、防止复制ie支持firefox不支持oncontextmenu="window.event.returnValue=false"ie支持firefox出错window.event…

    2022年8月14日

发表回复

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

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