二叉树中序遍历的三种方法

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

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

二叉树中序遍历的三种方法


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

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

二叉树中序遍历的三种方法


1、递归法

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

//recursive class Solution1 { public: vector 
  
    inorderTraversal(TreeNode* root) { vector 
   
     ret; if(root==NULL)return ret; inorderHelper(ret,root); return ret; } private: void inorderHelper(vector 
    
      & 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 
   
     inorderTraversal(TreeNode* root) { vector 
    
      ret; if(root==NULL)return ret; TreeNode *curr=root; stack 
     
       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 
   
     inorderTraversal(TreeNode* root) { vector 
    
      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/216539.html原文链接:https://javaforall.net

(0)
上一篇 2026年3月18日 上午11:37
下一篇 2026年3月18日 上午11:38


相关推荐

  • 【PyCharm】安装第三方库

    【PyCharm】安装第三方库在使用 PyCharm 过程中 会遇到库缺失问题 那么该如何安装第三方库呢 本文是对该问题的处理

    2026年3月26日
    3
  • 三阶魔方还原 – 只需7步6个公式

    三阶魔方还原 – 只需7步6个公式三阶魔方的初级还原法 也就是本篇文章要讲解的还原方法是很多魔方还原的基础 二阶魔方的还原可以完全按照三阶魔方的公式 待填入网址 四阶魔方的初级还原方式是先降为三阶 再按照三阶魔方进行还原 待填入网址 所以个人认为三阶魔方是还原 n 阶魔方的基础 首先要对三阶魔方有一个整体的理解 就是三阶魔方的轴是固定的 也就是说

    2026年3月26日
    3
  • NVIC设置

    NVIC设置NVIC终端优先级分组(NestVectorInterruptControl嵌套式向量中断控制器)CM4内核支持256个中断,其中包含了16个内核中断和240个外部中断,并且具有256级的可编程中断设置。STM32F4只是使用了其中的一部分。STM32F40xx/STM32F41xx的92个中断里面,包括10个内核中断,82个可屏蔽中断(常用)“`分组寄存器SCB->…

    2022年5月28日
    95
  • JavaScript数组-冒泡排序

    JavaScript数组-冒泡排序数组的冒泡排序算法也算一道经典面试题了,这里也给大家分享一下JavaScript中关于数组的冒泡排序的写法和思路:先给大家上代码:<script>//冒泡排序:将数组中的数字按照从大到小或从小到大的顺序排序vararr=[2,4,5,1,3];for(vari=0;i<arr.length-1;i++){//外层循环管趟数,即数组的全部项数都排好一共需要比较多少次一趟排好一个,注意趟

    2022年5月18日
    40
  • 最详细的ensp安装及使用「建议收藏」

    最详细的ensp安装及使用「建议收藏」步骤一:ensp安装1:在华为官网下载全套的ensp(网址如下)2:输入链接后点击ensp最新版本如图·:3:具体软件安装见下图的软件安装指南:4.关于在ensp中使用几个特殊的设备时操作如下:(1).只要用到以下设备,都需要去官网下载相应的镜像文件(2).例如在ensp中选用usg6000v后,右键点击启动:(3).启动设备后会弹出导入设备包的对话框:(4),点击浏览————找到·从官网上下载到的镜像文件即可。步骤二:…

    2022年10月14日
    6
  • vue调用js文件_vue调用其他js文件中的方法

    vue调用js文件_vue调用其他js文件中的方法本文主要介绍了vue引用js文件的多种方式,本文大家介绍的非常详细,具有一定的参考借鉴价值,需要的朋友可以参考下 1、vue-cliwebpack全局引入jquery(1)首先npminstalljquery–save(–save的意思是将模块安装到项目目录下,并在package文件的dependencies节点写入依赖。)(2)在webpack.base.conf.js里加入varwebpack=require(“webpack”)(3)在module

    2022年10月8日
    3

发表回复

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

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