Morris InOrder Traverse Binary Tree 无需使用递归和栈
今天在切leetcode的时候看到一个Morris算法,用来中序遍历二叉树,非递归,O(1)空间。觉得很强大。记录一下。
基本思想是利用了Threaded Binary Tree。
步骤如下:
- current节点设置为root。如果current不为空,到2,否则返回;
- 如果current没有左子树,输出current的值,current等于current.right;
- 如果current有左子树,首先找到current节点的precedent,也就是该节点左子树中最最右边那个节点。然后把最最右边这个节点的右link指向当前节点。如下图。

e.g. 当current是7的时候,我们找到4,并人为地添加一个link到current(绿色的link)。
current等于current.left;回到2.
有同学说,如果遍历到结点4,按照算法(4没有左子树),不是就又回到了7么,然后循环怎么结束呢?假设如果通过4回到了7,再找寻找7的precendent的过程中,我们会发现环,7->3->4->7(7的左子树中最最右边的节点是自己),那么我们知道7的左子树已经遍历完成,输出7,然后继续遍历7的右子树。
我们的代码如下:
首先假设有一个TreeNode数据结构是这样的。
public class TreeNode {
int val;
TreeNode left;
TreeNode right;
TreeNode(int x) { val = x; }
}
然后是遍历:
public ArrayList<Integer> inorderMorrisTraversal(TreeNode root){
sequence = new ArrayList<Integer>();
TreeNode current = root;
TreeNode pre = null;
while(current != null){
if(current.left == null){
sequence.add(current.val);
current = current.right;
}else {
pre = current.left;
//找到当前节点的前任,也就是它左子树的最右节点
while(pre.right != null && pre.right != current){
pre = pre.right;
}
if(pre.right == null){//我们遇到的左子树
pre.right = current;
current = current.left;
}else {//说明pre.right == current,构成了一个环,说明之前已经遍历过了current的左子树,可以输出current了。
pre.right = null;
sequence.add(current.val);
current = current.right;
}
}
}
return sequence;
我们以上面的例子track一下这个过程,首先current指向root节点7. root节点左子树非空,通过一路向右,找到7的前任4,建立绿色的link。

然后继续到3,在左子树中一路向右,找到2.

继续current = current.left,发现2没有左子树了,输出2.

然后current = current.right,current指向3. 注意到这是第二次指向3. 然后按照算法去寻找3的前任,当然这一回就不是2了,而是3本身。那么,我们需要删除掉这个环,也就2->3的link。并且输出current 的值3.

然后继续current到3的左子树。剩下的过程如下图。

总结下:
首先发明这个算法的人肯定是对那个什么Threaded Binary Tree烂熟于心啊;其次,对inorder遍历也是理解透彻啊。。。
再次,这人思维肯定特清晰。
Reference: http://www.geeksforgeeks.org/inorder-tree-traversal-without-recursion-and-without-stack/
Morris InOrder Traverse Binary Tree 无需使用递归和栈的更多相关文章
- CSharp Algorithm - How to traverse binary tree by breadth (Part II)
/* Author: Jiangong SUN */ Here I will introduce the breadth first traversal of binary tree. The pri ...
- Post Order traverse binary tree using non-recursive way
Process analysis Stack = 5, Push 3, Stack = 5, 3. Pre = 5 Current = 3, Pre = 5, Push 2 to the st ...
- [LeetCode] Binary Tree Preorder Traversal 二叉树的先序遍历
Given a binary tree, return the preorder traversal of its nodes' values. For example:Given binary tr ...
- [LeetCode] Binary Tree Postorder Traversal 二叉树的后序遍历
Given a binary tree, return the postorder traversal of its nodes' values. For example: Given binary ...
- [Algorithm] Construct a Binary Tree and Binary Search
function createNode(value) { return { value, left: null, right: null }; } function BinaryTree(val) { ...
- [LeetCode] 145. Binary Tree Postorder Traversal 二叉树的后序遍历
Given a binary tree, return the postorder traversal of its nodes' values. For example: Given binary ...
- [Leetcode][JAVA] Recover Binary Search Tree (Morris Inorder Traversal)
Two elements of a binary search tree (BST) are swapped by mistake. Recover the tree without changing ...
- (二叉树 递归) leetcode94. Binary Tree Inorder Traversal
Given a binary tree, return the inorder traversal of its nodes' values. Example: Input: [1,null,2,3] ...
- (二叉树 递归) leetcode 105. Construct Binary Tree from Preorder and Inorder Traversal
Given preorder and inorder traversal of a tree, construct the binary tree. Note:You may assume that ...
随机推荐
- yuv420格式分析
http://blog.csdn.net/liuhongxiangm/article/details/9135791 http://blog.csdn.net/bluesky_sunshine/art ...
- CentOS 7修改MySQL 5.6字符集为UTF-8
MySQL编码原因会导致数据库出现中文乱码 解决办法: 修改MySQL数据库字符编码为UTF-8,UTF-8包含全世界所有国家需要用到的字符,是国际编码. 具体操作: 1.进入MySQL控制台 mys ...
- Python中tab键自动补全功能的配置
新手学习Python的时候,如何没有tab键补全功能,我感觉那将是一个噩梦,对于我们这种菜鸟来说,刚接触python,对一切都不了解,还好有前辈们的指导,学习一下,并记录下来,还没有学习这个功能小伙伴 ...
- EF中修改对象的值的问题。。。(字段超级多的时候)
一般EF中修改单个对象的值,我是这样处理的. 如:DBEntities db=new DBEntities(); student stu = db.student.firstOrdefault(m=& ...
- Windows 上 GitHub Desktop 的操作[转]
第1章 上传开源代码至GitHub 1 1.1 git Windows 客户端 1 1.2 注册GitHub账户 2 1.3 登录 2 1.4 创建本地代码仓库 2 1. ...
- Mysql中Innodb大量插入数据时SQL语句的优化
innodb优化后,29小时入库1300万条数据 参考:http://blog.51yip.com/mysql/1369.html 对于Myisam类型的表,可以通过以下方式快速的导入大量的数据: A ...
- Making the iPhone vibrate (iPhone 振动)
from: http://stackoverflow.com/a/4725039 There are two seemingly similar functions that take a param ...
- ssm框架搭建并演示获取json字符串
为方便起见,使用oracle自带的scott账户中的emp表作为数据源. 预期效果: 1.输入URL:http://localhost:8888/ssm/getEmp?empno=7369 2.返回结 ...
- C#委托和事件详解
委托Delegate delegate是C#中的一种类型,它实际上是一个能够持有对某个方法的引用的类.与其它的类不同,delegate类能够拥有一个签名(signature),并且它"只能持 ...
- CUGBACM Codeforces Tranning 1 题解
链接:http://acm.hust.edu.cn/vjudge/contest/view.action?cid=61581#overview 描写叙述:非常老的CF题,题不错,拿来训练正好. 做的时 ...