I need an algorithm for returning the successor node of some arbitrary node of the
given binary search tree.
To give you an answer with the same level of detail as your question: Go up until going right is possible, and then left until you reach a leaf.
There are two general approaches:
If your binary tree nodes have pointers to their parent node, then you can traverse directly from the node to the successor node. You will have to determine how to use the parent pointers to do the traversal.
If your binary tree nodes do not have parent pointers, then you will have to do an inorder traversal of the tree starting at the root (presumably you have a root node pointer) and return the next node after the given node.
You need to maintain a zipper as you descend the tree. A zipper is simply a list of the nodes you have traversed, and for each an indication of whether you next went left or right.
It allows you to travel back up in the tree even if there aren't any pointers from children to parents.
The algorithm for successor is to go back (up in the zipper) as long as you were coming from the left, then go right once, and then descend to the leftmost child.
It's easier with a figure...
The successor of a node implies you are looking for an inorder successor.
The following method helps you determine the inorder successor WITHOUT ANY PARENT NODE OR EXTRA SPACE NON-RECURSIVELY
struct node * inOrderSuccessor(struct node *root, struct node *n)
{
//*If the node has a right child, return the smallest value of the right sub tree*
if( n->right != NULL )
return minValue(n->right);
//*Return the first ancestor in whose left subtree, node n lies*
struct node *succ=NULL;
while(root)
{
if(n->datadata < root->data)
{
succ=root; root=root->left;
}
else if(n->data > root->data)
root=root->right;
else break;
}
return succ;
}
I'm quite certain this is right. Do correct me if I am wrong. Thanks.
Related
Okay, so in-order traversal of threaded binary tree by using threads goes something like this:
Start at leftmost node and print it
Follow thread to right and print it
Follow link to right go to leftmost node and print it
Follow thread to right and print it
(repeat)
But how can I make pre- and post-order traversals using threads?
A threaded tree node typically has a flag that tells you whether the right and left pointers in the node are references to children, or threads to the inorder/preorder successor. That's the only way you can tell if the node is a leaf.
The nice thing about a threaded tree is that inorder or reverse inorder traversals can be done quickly without recursion. But a threaded tree doesn't help you with postorder or preorder traversals. If you want to do one of those, you have to use the recursive algorithm, taking the threads into account. For example:
preorder(node)
print node
if (node.left is not a thread link)
preorder(node.left)
if (node.right is not a thread link)
preorder(node.right)
postorder(node)
if (node.left is not a thread link)
preorder(node.left)
if (node.right is not a thread link)
preorder(node.right)
print node
we can able to do inorder traversal in threaded binary tree as provided above but also we can able to do preorder traversal without using any extra space also .
this is c++ code
//code is here
//////////////////////////////////////////
void preorder(node*root)
{
if (root==NULL)
{
cout <<"tree is empty \n";
}
else
{
while(root!=NULL)
{
cout <<root->data;
if (root->lthread==false)
{
root=root->lptr;
}
else if (root->rthread==false)
{
root=root->rptr;
}
else
{
while(root!=NULL&&root->rthread==true)
{
root=inorder_succesor(root);
}
if (root!=NULL)
{
root=root->rptr;
}
}
}
}
}
///////////////////////////////////////////////////////
as we know in preorder traversal we first print the node where we are and then go to left subtree and then rightsubtree then here we able to do this
1.print the node at which we are .
2.if this node has left subtree then go to it and print its node and go to step 1
3.is node has no left subtree check is it has right subtree , if yes go to right subtree and go to step 1
we reach to this step when we have node having no left subtree and no right subtree then we go to its inorder succesor which has right subtree and go to right subtree and go to step 1 is we get is can not get any inorder successor having right subtree then stop .
I was trying to find inorder successor for a node in a BST. And below is my sample code.
public TreeNode getInorderSuccesor(TreeNode t)
{
if(t == null)
{
return null;
}
if(t.getRight()!=null)
{
t = t.getRight();
while(t.getLeft()!=null)
{
t = t.getLeft();
}
return t;
}
else
{
TreeNode parent = t.getParent();
while(parent!=null && parent.getLeft() != t)
{
t = parent;
parent = t.getParent();
}
return parent;
}
}
Please let me know if any condition it will fail. And one more thing if some can share algo/ code/ sudocode for find the inorder successor without parent node. thanks!!!
Here is the basic logic for the successor function; the predecessor function is similar, but reversed. A recursive function descends the tree searching for the requested key, keeping track of the current tree as the possible successor every time if follows the left sub-tree. If it finds the key, its successor is the minimum element of the right sub-tree, found by chasing left sub-trees until reaching a null node. If the search reaches a null node and hence fails to find the key, the next largest key in the tree is the successor, found in the possible successor that was saved at each recursive call. I recently implemented this algorithm at my blog.
If the nodes in the tree have unique values, then it is quite simple. You just need to find:
The node with largest number that is smaller than or equal to the value of the node whose successor needs to be determined
The node with the smallest number that is strictly larger than the value of the node whose successor needs to be determined.
The latter node will be the answer. The first node can be used to check whether the input node is a valid node in the tree.
Pseudo-code:
function inOrderSuccessor(val, tree):
(left, right) = findRange(val, tree.rootnode, null, null)
if (left.val != val):
throw Error("No node with specified value")
return right
function findRange(val, currnode, left, right):
if (currnode == null):
return (left, right)
if (currnode.val <= val):
return findRange(val, currNode.right, currnode, right)
else:
return findRange(val, currNode.right, left, currnode)
If the nodes in the tree may have duplicate value, the in-order successor is not very well-defined. It is necessary to know when you are given a node, how do you differentiate between different nodes with the same value. Are you given a real reference to the node in the tree?
In the tricky case where you are simply given a reference to a node, and there are other nodes with the same value in the tree, then there are 2 cases:
Case 1: The node has right subtree, then you only need to find the smallest element in the right subtree.
Case 2: The node doesn't have right subtree. You need to check reference equality with all the nodes which has the same value. When you have found the node in the tree, traverse upward from the node back to root (you have this in the stack), and find the first node that does a left-turn.
Just wanted to know how efficient is the below algorithm to find the lowest common ancestor of two nodes in a binary search tree.
Node getLowestCommonAncestor (Node root, Node a, Node b) {
Find the in-order traversal of Node root.
Find temp1 = the in-order successor of Node a.
Find temp2 = the in-order successor of Node b.
return min (temp1, temp2);
}
Searching for the lowest common ancestor in a binary search tree is simpler than that: observe that the LCA is the node where the searches for item A and item B diverge for the first time.
Start from the root, and search for A and B at the same time. As long as both searches take you in the same direction, continue the search. Once you arrive at the node such that searching for A and B take you to different subtrees, you know that the current node is the LCA.
A node at the bottom of a large binary search trees can have an in-order successor close to it, for instance if it is the left child of a node, its in-order successor is its parent.
Two nodes descending from different children of the root will have the root as their least common ancestor, no matter where they are, so I believe that your algorithm gets this case wrong.
This is a discussion of efficient LCA algorithms (given time to build a preparatory data structure) at http://en.wikipedia.org/wiki/Lowest_common_ancestor, with pointers to code.
An inefficient but simple way of finding the LCA is as follows: in the tree keep pointers from children to parents and a note of the depth of each node. Given two nodes, move up from the deepest one until the depth if the same. If you are pointing at the other node, it is the LCA. Otherwise move up one step from each node and check again, and so on, until you meet at the LCA.
Finding LCA of BST is straight:
Find the node for which node1 and node2 are present on different
sides. But if the node1 is an ancestor of node2 than also we will
have to return node1. Below code implements this algo.
TreeNode<K> commonAncestor(TreeNode t, K k1, K k2){
if(t==null) return null;
while(true)
{
int c1=t.k.compareTo(k1);
int c2=t.k.compareTo(k2);
if(c1*c2<=0)
{
return t;
}
else
{
if(c1<0)
{
t = t.right;
}
else
{
t = t.left;
}
}
}
}
I need help in understanding this interview question:
Q: Find an algorithm to find the next node (e.g., inorder successor) of a given node in a binary search tree where each node has a link to its parent.
Does parent mean the in-order predecessor or just the immediate parent? How would one create a tree where the nodes have a link to the root node or inorder predecessor? Any help in understanding the data structure and the program below would be appreciated...
the solution (As posted in a form) is shown below:
public static TreeNode inorderSucc(TreeNode e) {
if (e != null) {
TreeNode p;
// Found right children -> return 1st inorder node on right
if (e.parent == null || e.right != null) {
p = leftMostChild(e.right);
} else {
// Go up until we’re on left instead of right (case 2b)
while ((p = e.parent) != null) {
if (p.left == e) {
break;
}
e = p;
}
}
return p;
}
return null;
}
public static TreeNode leftMostChild(TreeNode e) {
if (e == null) return null;
while (e.left != null) e = e.left;
return e;
}
When nodes store pointers to their parents, it almost always maeans their immediate parents and not their successors. The question in this interview is then how to navigate the tree to find the inorder successor.
The way to find an in order successor is to think about what would happen if you were to recursively do an in order walk of the tree, then to mimic what would happen next. In particular, the logic for an in order traversal always visits all of a node's left subtree, then the node itself, and then the right subtree. To find the in order successor, you need to see what case you're in.
If the node you're currently at has a right subtree, then the in order successor of that tree must be the very first node that would be visited in that subtree during an in order traversal, which is the smallest element of that tree. You can find this by descending into the right subtree, then marching down the left spine of the tree until you find the leftmost node.
If the node does not have a right subtree, then it's the largest node in some subtree. If you think about how the recursion works, the next step in an in order traversal would be to have all the recursive calls that just finished expanding their right subtrees return. Once this last frame returns, you'll visit the node of the first tree that expanded just its left subtree. Consequently, the in order successor of the node can be found by walking up the tree until you reach a node that's a left child. The parent of this node is then your successor. Alternatively, as an edge case, if you hit the root of the tree, that would also be your successor.
Hope this helps!
What is the easiest way, preferably using recursion, to find the shortest root-to-leaf path in a BST (Binary Search Tree). Java prefered, pseudocode okay.
Thanks!
General description:
Use a Breadth-first search (BFS) as opposed to a Depth-first search (DFS). Find the first node with no children.
Using a DFS you might get lucky on some input trees (but there is no way to know you got lucky so you still need to search the whole tree), but using the BFS method is much faster and you can find a solution without touching all nodes.
To find the root to leaf path, you could follow the first found childless node all the way back up to the root using the parent reference. If you have no parent reference stored in each node, you can keep track of the parent nodes as you recurse down. If you have your list in reverse order you could push it all on a stack and then pop it off.
Pseudo-code:
The problem is very simple; here is pseudo code to find the smallest length:
Put the root node on the queue.
Repeat while the queue is not empty, and no result was found:
Pull a node from the beginning of the queue and check if it has no children. If it has no children you
are done you found the shortest path.
Otherwise push all the children (left, right) onto the queue.
Finding all shortest paths:
To find all shortest paths you can store the depth of the node along with node inside the queue. Then you would continue the algorithm for all nodes in the queue with the same depth.
Alternative:
If instead you decided to use a DFS, you would have to search the entire tree to find the shortest path. But this could be optimized by keeping a value for the shortest so far, and only checking the depth of future nodes up until you find a new shortest, or until you reach the shortest so far. The BFS is a much better solution though.
This is in C++, but it is so simple you can convert it easily. Just change min to max to get the maximum tree depth.
int TreeDepth(Node* p)
{
return (p == NULL) ? 0 : min(TreeDepth(p->LeftChild), TreeDepth(p->RightChild)) + 1;
}
Just to explain what this is doing, it is counting from the leaf node (it returns 0 when it finds a leaf) and counts up back to the root. Doing this for the left and right hand sides of the tree and taking the minimum will give you the shortest path.
Breadth first search is exactly optimal in terms of the number of vertices visited. You have to visit every one of the vertices you'd visit in a breadth first search just in order to prove you have the closest leaf!
However, if you have a mandate to use recursion, Mike Thompson's approach is almost the right one to use -- and is slightly simpler.
TD(p) is
0 if p is NULL (empty tree special case)
1 if p is a leaf (p->left == NULL and p->right == NULL)
min(TD(p->left), TD(p->right)) if p is not a leaf
static int findCheapestPathSimple(TreeNode root){
if(root==null){
return 0;
}
return root.data+Math.min(findCheapestPathSimple(root.left), findCheapestPathSimple(root.right));
}
shortestPath(X)
if X == NIL
return 0
else if X.left == NIL and X.right == NIL //X is a leaf
return 1
else
if X.left == NIL
return 1 + shortestPath(X.right)
else if X.right == NIL
return 1 + shortestPath(X.left)
else
return 1 + min(shortestPath(X.left), shortestPath(X.right))