Binary Search Tree In-Order Traversal Iterative Solution
Given a binary search tree, print the elements in-order iteratively without using recursion.
Note:
Before you attempt this problem, you might want to try coding a pre-order traversal iterative solution first, because it is easier. On the other hand, coding a post-order iterative version is a challenge. See my post: Binary Tree Post-Order Traversal Iterative Solution for more details and an in-depth analysis of the problem.
We know the elements can be printed in-order easily using recursion, as follow:
|
1
2
3
4
5
6
|
voidin_order_traversal(BinaryTree *p){
if(!p)return;
in_order_traversal(p->left);
cout<<p->data;
in_order_traversal(p->right);
}
|
Excessive recursive function calls may cause memory to run out of stack space and extra overhead. Since the depth of a balanced binary search tree is about lg(n), you might not worry about running out of stack space, even when you have a million of elements. But what if the tree is not balanced? Then you are asking for trouble, because in the worst case the height of the tree may go up to n. If that is the case, stack space will eventually run out and your program will crash.
To solve this issue, we need to develop an iterative solution. The idea is easy, we need a stack to store previous nodes, and a visited flag for each node is needed to record if the node has been visited before. When a node is traversed for the second time, its value will be printed. After its value is printed, we push its right child and continue from there.
|
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
|
voidin_order_traversal_iterative(BinaryTree *root){
stack<BinaryTree*>s;
s.push(root);
while(!s.empty()){
BinaryTree *top=s.top();
if(top!=NULL){
if(!top->visited){
s.push(top->left);
}else{
cout<<top->data<<" ";
s.pop();
s.push(top->right);
}
}else{
s.pop();
if(!s.empty())
s.top()->visited=true;
}
}
}
|
Alternative Solution:
The above solution requires modification to the original BST data structure (ie, adding a visited flag). The other solution which doesn’t modify the original structure is with the help of a current pointer in addition of a stack.
First, the current pointer is initialized to the root. Keep traversing to its left child while pushing visited nodes onto the stack. When you reach a NULL node (ie, you’ve reached a leaf node), you would pop off an element from the stack and set it to current. Now is the time to print current’s value. Then, current is set to its right child and repeat the process again. When the stack is empty, this means you’re done printing.
|
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
|
voidin_order_traversal_iterative(BinaryTree *root){
stack<BinaryTree*>s;
BinaryTree *current=root;
booldone=false;
while(!done){
if(current){
s.push(current);
current=current->left;
}else{
if(s.empty()){
done=true;
}else{
current=s.top();
s.pop();
cout<<current->data<<" ";
current=current->right;
}
}
}
}
|
We can even do better by refactoring the above code. The refactoring relies on one important observation:
Why this is true? To prove this, we assume the opposite, that is: the last traversed node has a right child. This is certainly incorrect, as in-order traversal would have to traverse its right child next before the traversal is done. Since this is incorrect, the last traversed node must not have a right child by contradiction.
Below is the refactored code:
|
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
|
voidin_order_traversal_iterative(BinaryTree *root){
stack<BinaryTree*>s;
BinaryTree *current=root;
while(!s.empty()||current){
if(current){
s.push(current);
current=current->left;
}else{
current=s.top();
s.pop();
cout<<current->data<<" ";
current=current->right;
}
}
}
|
A threaded tree, with the special threading links shown by dashed arrows. A threaded binary tree makes it possible to traverse the values in the binary tree via a linear traversal that is more rapid than a recursive in-order traversal.
Further Thoughts:
The above solutions require the help of a stack to do in-order traversal. Is it possible to do in-order traversal without a stack?
The answer is yes, it’s possible. There’s 2 possible ways that I know of:
- By adding a parent pointer to the data structure, this allows us to return to a node’s parent (Credits to my friend who provided this solution to me). To determine when to print a node’s value, we would have to determine when it’s returned from. If it’s returned from its left child, then you would print its value then traverse to its right child, on the other hand if it’s returned from its right child, you would traverse up one level to its parent.
- By using a Threaded Binary Tree. Read the article: Threaded Binary Tree on Wikipedia for more information.
public class Solution {
public ArrayList<Integer> inorderTraversal(TreeNode root) {
Stack<TreeNode> st = new Stack<TreeNode>();
ArrayList<Integer> result = new ArrayList<Integer>();
if(root == null) return result;
boolean fin = false;
while(!fin){
if(root != null){
st.push(root);
root = root.left;
}else{
if(st.size() == 0){
fin = true;
}else{
root = st.pop();
result.add(root.val);
root = root.right;
}
}
}
return result;
}
}
这个代码是错误的:
public List<Integer> inorderTraversal(TreeNode root) {
// write your code here
LinkedList<TreeNode> stack = new LinkedList<TreeNode> (); //stack
List<Integer> result = new ArrayList<Integer> ();
if(root == null) return result;
stack.push(root);
while(!stack.isEmpty()){
TreeNode tmp = stack.peek();
if(tmp.left != null) stack.push(tmp.left);
else{
tmp = stack.pop();
result.add(tmp.val);
if(tmp.right != null) stack.push(tmp.right);
}
}
return result;
}
会在最后一个root 和其left leaf之间无限循环。
Binary Search Tree In-Order Traversal Iterative Solution的更多相关文章
- [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 ...
- [Swift]LeetCode1008. 先序遍历构造二叉树 | Construct Binary Search Tree from Preorder Traversal
Return the root node of a binary search tree that matches the given preorder traversal. (Recall that ...
- LeetCode 1008. Construct Binary Search Tree from Preorder Traversal
原题链接在这里:https://leetcode.com/problems/construct-binary-search-tree-from-preorder-traversal/ 题目: Retu ...
- 【leetcode】1008. Construct Binary Search Tree from Preorder Traversal
题目如下: Return the root node of a binary search tree that matches the given preorder traversal. (Recal ...
- 【LeetCode】 99. Recover Binary Search Tree [Hard] [Morris Traversal] [Tree]
Two elements of a binary search tree (BST) are swapped by mistake. Recover the tree without changing ...
- 【LeetCode】1008. Construct Binary Search Tree from Preorder Traversal 解题报告(Python)
作者: 负雪明烛 id: fuxuemingzhu 个人博客: http://fuxuemingzhu.cn/ 目录 题目描述 题目大意 解题方法 递归 日期 题目地址:https://leetcod ...
- leetcode@ [173] Binary Search Tree Iterator (InOrder traversal)
https://leetcode.com/problems/binary-search-tree-iterator/ Implement an iterator over a binary searc ...
- 算法与数据结构基础 - 二叉查找树(Binary Search Tree)
二叉查找树基础 二叉查找树(BST)满足这样的性质,或是一颗空树:或左子树节点值小于根节点值.右子树节点值大于根节点值,左右子树也分别满足这个性质. 利用这个性质,可以迭代(iterative)或递归 ...
- LeetCode解题报告—— Unique Binary Search Trees & Binary Tree Level Order Traversal & Binary Tree Zigzag Level Order Traversal
1. Unique Binary Search Trees Given n, how many structurally unique BST's (binary search trees) that ...
随机推荐
- 精美jQuery插件及源码 前端开发福利
jQuery是一个非常不错的javascript框架,很多前端开发者喜欢的原因不仅是因为jQuery使用起来方便,更重要的是因为它的插件很多,我们可以将这些插件应用到自己的项目中去.下面这些精美的jQ ...
- 分享7款顶级的CSS3动画特效
1.CSS3 SVG文字背景动画 超酷的文字特效 今天我们来分享一款基于CSS3和SVG的文字特效,文字的背景可以定义一些动画特效,在背景动画播放的同时,我们还可以选中文字.本示例让文字背景展示水波和 ...
- Java中浮点数能连续精确表示整数的范围
转自http://blog.csdn.net/seizef/article/details/5571783#ref_1,有删改. 先简单介绍一下浮点数在计算机中的组成,在Java中采用的浮点数表示法是 ...
- uml的关联多重度
UML中关联的多重度是指一个类的实例能够与另一个类的多少个实例相关联,这个“多少”被称为关联角色的多重度指定关联一端的多重度.也可以这样理解:在关联另一端的类的每个对象要求在本端的类必须有多 少个对象 ...
- Linux I/O模型
同步阻塞I/O 在此种方式下,用户进程在发起一个I/O操作以后,必须等待I/O操作的完成,只有当真正完成了I/O操作以后,用户进程才能运行.Java传统的I/O模型属于此种方式. 同步非阻塞I/O 在 ...
- Standford CoreNLP
Stanford CoreNLP Stanford CoreNLP提供一组自然语言处理的工具.这些工具可以把原始英语文本作为输入,输出词的基本形式,词的词性标记,判断词是否是公司名.人名等,规格化日期 ...
- Bootstrap轮播获取当前活动的焦点对象
在项目中使用了Bootstrap的轮播,需求是轮播下方有一个已读按钮,当点击已读按钮时,隐藏掉当前的焦点的轮播内容: 如图所示: 所以要获取当前的焦点是哪一条: 下方代码是在网络上找到的一个方 ...
- 编译安装HTTPD 2.4.9版本
编译安装HTTPD 2.4.9版本 服务脚本:/etc/rc.d/init.d/httpd 脚本配置文件路径:/etc/sysconfig/httpd 运行目录:/etc/httpd ...
- Assembly(程序集) 反射和缓存
using System; using System.Collections.Generic; using System.ComponentModel; using System.Data; usin ...
- Thinkphp整合最新Ueditor编辑器
说到最新的富文本编辑器的确不少(ckeditor.fkeditor.ueditor),这些富文本编辑器如果单独使用基本上很方便,不需要做额外的配置,只要把官方的插件下载下来放到一个web容器中,看看 ...