Reputation: 1728
Is it possible to do an iterative in-order-traversal on a BST whose node has a parent pointer (the parent of the root is null
) without using a visited
flag or a stack
?
I googled and didn't find a reply. The point is, how can I know - at a certain node - that I've just come to it vs I've finished everything underneath it?
Upvotes: 18
Views: 20702
Reputation: 64308
Here is another way to do it. I think it is essentially equivalent to svick's answer, but avoids the extra variable. This version is implemented in Python:
node=root
if node is not None:
while node.left is not None:
node=node.left
while node is not None:
output(node)
if node.right is not None:
node=node.right
while node.left is not None:
node=node.left
else:
while node.parent is not None and node.parent.right is node:
node=node.parent
node=node.parent
Whatever node you visited last determines the next node that you need to visit. If you've just visited node X, then you need to visit the left-most node to the right of X. If X has no right child, then the next node is the first ancestor where node X didn't come from the right side.
Upvotes: 14
Reputation: 1473
Step 1 : write a function which returns the in-order successor
Step 2 : Starting with the leftmost node, find the in-order successor until there is none
public class TreeNode {
int data;
TreeNode left;
TreeNode right;
TreeNode parent;
}
public class TreeUtility {
public void inorderNoRecursion(TreeNode root) {
TreeNode current = leftmostNode(root);
while(current != null) {
System.out.println(current.data);
current = inorderSuccessor(current);
}
}
public TreeNode inorderSuccessor(TreeNode node) {
if (node.right!=null) {
return leftmostNode(node.right);
}
TreeNode p = node.parent;
TreeNode c = node;
while(p!=null && c != p.left) {
c = p;
p = p.parent;
}
return p;
}
private TreeNode leftmostNode(TreeNode node) {
while (node.left != null) {
node = node.left;
}
return node;
}
}
Upvotes: 0
Reputation: 19260
My Java solution without introducing any flag on the existing TREE. And no parent pointer as well. This approach will hold nodes up to the height of the tree. Please have a look.
https://github.com/skanagavelu/Algorithams/blob/master/src/tree/InOrderTraversalIterative.java
Upvotes: 0
Reputation: 17
public void inorderNoStack() {
if (root == null) {
return;
}
// use the previous to always track the last visited node
// helps in deciding if we are going down/up
Node prev = null;
Node curr = root;
while (curr != null) {
// going down
if (prev == null || prev.left == curr || prev.right == curr) {
if (curr.left != null) {
prev = curr;
curr = curr.left;
continue;
} else {
visitn(curr);
if (curr.right != null) {
prev = curr;
curr = curr.right;
continue;
} else {
// swap states
prev = curr;
curr = prev.parent;
}
}
}
// going up after left traversal
if (curr != null && prev == curr.left) {
visitn(curr);
if (curr.right != null) {
prev = curr;
curr = curr.right;
continue;
} else {
// swap states
prev = curr;
curr = prev.parent;
}
}
// going up after right traversal
if (curr != null && prev == curr.right) {
// swap states
prev = curr;
curr = prev.parent;
}
}
}
Upvotes: 0
Reputation: 1
This is in C++:
void InOrder(Node *r)
{
if(r==NULL)
return;
Node *t=r;
while(t!=NULL)
t=t->left;
while(t!=r)
{
if(t==(t->parent->left))
{
cout<<t->parent->data;
t=t->parent->right;
if(t!=NULL)
{
while(t!=NULL)
t=t->left;
}
if(t==NULL)
t=t->parent;
}
if(t==t->parent->right)
{
t=t->parent;
}
}
}
Upvotes: -2
Reputation: 244787
You can do that, you just need to remember the last visited node along with the current node. Doing this is not disallowed by the problem statement: both visited
flag on each node and a stack
are (worst case) O(n), remembering the last node is just O(1).
In C#, the algorithm could look like this:
static void Walk(Node node)
{
Node lastNode = null;
while (node != null)
{
if (lastNode == node.Parent)
{
if (node.Left != null)
{
lastNode = node;
node = node.Left;
continue;
}
else
lastNode = null;
}
if (lastNode == node.Left)
{
Output(node);
if (node.Right != null)
{
lastNode = node;
node = node.Right;
continue;
}
else
lastNode = null;
}
if (lastNode == node.Right)
{
lastNode = node;
node = node.Parent;
}
}
}
Upvotes: 20
Reputation: 1728
Using svick's correct idea (see his answer), this is the tested code in C++. Note that I didn't test his code or even take a look at it, I just took his idea and implemented my own function.
void in_order_traversal_iterative_with_parent(node* root) {
node* current = root;
node* previous = NULL;
while (current) {
if (previous == current->parent) { // Traversing down the tree.
previous = current;
if (current->left) {
current = current->left;
} else {
cout << ' ' << current->data;
if (current->right)
current = current->right;
else
current = current->parent;
}
} else if (previous == current->left) { // Traversing up the tree from the left.
previous = current;
cout << ' ' << current->data;
if (current->right)
current = current->right;
else
current = current->parent;
} else if (previous == current->right) { // Traversing up the tree from the right.
previous = current;
current = current->parent;
}
}
cout << endl;
}
Upvotes: 6
Reputation: 122
The key is the parent pointers (or the ability to mutate the tree), but you need a constant amount of extra state (e.g., the program counter of the following coroutine).
Upvotes: -1