二叉树遍历的三种方法(以中序为例)

二叉树遍历的三种方法

递归 简单 时间O(n) 空间O(n)
非递归+栈 中等 时间O(n) 空间O(n)
非递归、不用栈 中等 时间O(n) 空间O(1)

伪代码实现--近C++代码

方法一:递归

1 Inorder-Tree-Walk(x)
2     if(x != NULL)
3         Inorder-Tree-Walk(x->left)
4         print x->key
5         Inorder-Tree-Walk(x->right)

方法二:非递归+栈

 1 Inorder-Tree-Walk(x)
 2     stack<Node*> s //定义装二叉树节点指针的栈容器
 3         while(x != NULL || !s.empty())
 4              if(x != NULL)
 5                  s.push(x)
 6                  x = x->left
 7              else if(!s.empty())
 8                  x = s.top()
 9                  s.pop()
10                  print x->key
11                  x = x->right  

方法三:非递归,不用栈(Morris 中序遍历[1])

思想:利用线索二叉树的思想,无右子树的节点的空闲的右指针,指向此节点中序遍历的后继,以此记录在此节点之后要访问的点。要使得无右子树的节点指向后继,不直接计算其后继,而是迭代地计算所经过的节点的前驱(左子树的最右节点)。

 1 Inorder-Tree-Walk(x)
 2     Node *cur = x, *prev;
 3     while(cur != NULL)
 4         if(cur->left != NULL)  //如果左子树不为空,不应打印当前节点,需在当前节点的前驱节点记录下此节点(此节点记录在其前驱的右指针,其前驱右指针原本一定为空),方便下次找到这个节点。
 5             //试图找到当前节点的中序序列前驱,前驱在左子树的最右点
 6             prev = cur->left  //先使prev为左子树根节点
 7             while(prev->right != NULL && prev->right != cur)
 8                 prev = prev->right
 9             //第一次找到左子树最右点时,最右点的右指针肯定为空,但是此时将标记其右指针指向该节点的后继(cur 节点),那么第二次到cur时,将再次执行找到其前驱。如果在寻找其前驱的过程中发现:有一个节点指向cur。说明这是第二次访问这个节点(cur的前驱已经打印输出,该cur输出了),这也是为什么找前驱的while里需要判断“prev->right != cur”。
10             if(prev->right == NULL) //第一次找到cur的前驱prev
11                 prev->right = cur   //标记其右指针指向cur,因为cur还没有输出,在输出prev后,输出cur
12             else //   第二次找到cur的前驱,此时prev->right == cur。第二次到达cur节点,一定是从其前驱的右指针过来的,说明其前驱已经输出打印完毕,该打印cur了
13                 print cur->key
14                 cur = cur->right //往右走,其左子树和当前节点已经遍历完成
15         else  //cur->left == NULL, 如果左子树为空,打印输出当前节点
16             print cur->key
17             cur = cur->right //转向右节点,继续循环

参考资料:[1] http://www.cnblogs.com/AnnieKim/archive/2013/06/15/morristraversal.html Accessed at 2015/4/11     [2] 《算法导论》中文版 原书第三版 机械工业出版社 
				
时间: 2024-07-30 10:47:00

二叉树遍历的三种方法(以中序为例)的相关文章

HashTable集合遍历的三种方法

hashtable集合遍历可以根据key,value以及key+value 示例代码: Hashtable table = new Hashtable(); Student stu = new Student(); stu.Name = "李四"; stu.Age = 18; Student stu1 = new Student(); stu1.Name = "张三"; stu1.Age = 18; Student stu2 = new Student(); stu

清空StringBuilder的三种方法及效率

清空StringBuilder的三种方法及效率 大家知道对于字符串频繁拼接是使用stringbuilder.Append方法比使用string+=方法效率高很多,但有时需要清空stringbuilder时却不知道怎么清空,因为它没有clear或empty的方法.那用什么方法呢?在网上搜了一下大概一下三种方法. 1.Remove 例: StringBuilder val = new StringBuilder(); val.Append("...."); val.Remove(0,val

MyEclipse安装插件的三种方法和使用心得

MyEclipse安装插件的三种方法和使用心得 本文讲解MyEclipse(MyEclipse10)的三种方法,以TestNG为例 Eclipse update site URL:  http://beust.com/eclipse. 一.通过MyEclipse Configuration Center在线安装 1. 打开MyEclipse10,在菜单栏选择MyEclipse→MyEclipse Configuration Center,即可进入到MyEclipse Configuration

二叉树遍历算法——包含递归前、中、后序和层次,非递归前、中、后序和层次遍历共八种

首先,要感谢网上的参考资料. http://mengliao.blog.51cto.com/876134/1178079(作者:BlackAlpha) http://blog.csdn.net/fzh1900/article/details/14056735(作者:_云淡风轻) http://blog.csdn.net/stpeace/article/details/8138458(作者:stpeace) 二叉树是使用的比较广泛的一种数据结构,这里我写了二叉树的相关操作,包括初始化.新建.以及遍

List遍历三种方法:1.for 2.增强性for 3.迭代器

package chapter09; import java.util.ArrayList;import java.util.Iterator;import java.util.List; /* * List遍历三种方法:1.for 2.增强性for 3.迭代器 */public class TestList { public static void main(String[] args) { // 声明一个集合 List list = new ArrayList(); String aStri

ASP.NET MVC 中将数据从View传递到控制器中的三种方法(表单数据绑定)

转自:http://www.cnblogs.com/zyqgold/archive/2010/11/22/1884779.html 在ASP.NET MVC框架中,将视图中的数据传递到控制器中,主要通过发送表单实现的.具体使用中,主要使用以下三种方法. 1.通过Request.Form读取表单数据        2.通过FormCollection读取表单数据        3.直接读取表单数据对象 下边是我学习这些东西时的一点总结 1.通过Request.Form读取表单数据      首先定

cocos2dx中创建动画的三种方法

1.最最原始的方法,先创建动画帧,再创建动画打包(animation),再创建动画(animate) 第一步: 创建动画帧:CCSpriteFrame,依赖于原始的资源图片(xx.png,xx.jpg) CCSpriteFrame *frame1=CCSpriteFrame::create("1.png"); CCSpriteFrame *frame2=CCSpriteFrame::create("2.png"); CCSpriteFrame *frame3=CCS

spring在xml文件中配置bean的三种方法

一.最常见,也是缺省,是调用spring的缺省工厂类 spring缺省工厂类:org.springframework.beans.factory.support.DefaultListableBeanFactory使用其静态方法preInstantiateSingletons() 配置文件中最普通最基本的定义一个普通bean<bean id="DvdTypeDAOBean" class="com.machome.dvd.impl.DvdTypeDAO" >

Node.JS的表单提交及OnceIO中接受GET/POST数据的三种方法

OnceIO 是 OnceDoc 企业私有内容(文档)管理系统的底层Web框架,它可以实现模板文件.静态文件的全缓存,运行起来完全不需要I/O操作,并且支持客户端缓存优化,GZIP压缩等(只压缩一次),拥有非常好的性能,为您节约服务器成本.它的模块化功能,可以让你的Web进行分布式存储,在一个扩展包里即可包含前端.后端和数据库定义,只需通过添加/删除目录的方式就可实现功能删减,实现真正的模块化扩展.目前 OnceIO 已经开源,本文主要介绍node.js语言中的表单提交及OnceIO中接受GET