This question already has answers here:
In Order Successor in Binary Search Tree
(19 answers)
Closed 5 years ago.
The successor of an element in a BST is the element's successor in the sorted order determined by the inorder traversal. Finding the successor when each node has a pointer to its parent node is presented in CLRS's algorithm textbook (Introduction to Algorithms by MIT press).
The idea to find the successor here is - if the right subtree of node x is nonempty, the successor of x is the minimum element in the right subtree. Otherwise, the successor is the lowest ancestor of x whose left child is also an ancestor of x (assuming a node is an ancestor of itself).
Can we find the successor without using the pointer to the parent node?
Sometimes our tree node does not have this pointer. I struggled a couple of hours but cannot write the correct code.
Inspired by Sheldon's solution ,this is the non-recursive version of the solution.
if (right[x] != NIL)
return min(right[x]);
else
{
candidate = NIL;
y = root;
while (y!= x) // y is used as a probe
if (key[x] < key[y])
{
candidate = y;
y = y ->left;
}
else
y = y->right;
}
return candidate;
If candidate == NIL, x is the max in the tree and does not have a successor.
This should work:
TREE-SUCCESSOR(T, x)
if right[x] != NIL
return TREE-MINIMUM(right[x])
else
return FIND-TREE-SUCCESSOR(root[T], x, NIL)
FIND-TREE-SUCCESSOR(y, x, c)
if y = x
return c
if key[x] < key[y]
return FIND-TREE-SUCCESSOR(left[y], x, y)
else
return FIND-TREE-SUCCESSOR(right[y], x, c)
FIND-TREE-SUCCESSOR keeps in c (of candidate) the last node in which we turned left.
I found an elegant solution for in-order successor without parent pointer here -> http://www.geeksforgeeks.org/archives/9999
Idea is
1.If the node has right sub-tree, then its successor is the least element in the right sub-tree
If the node's right sub-tree is empty, then its successor is one of its ancestors, which can be found top-down without parent pointer, with the following algorithm:
let initially current_node be root, succ_node = null;
case1: If the search element is less than current_node, then the current element is a potential successor - place succ_node at the current_node and move the current_node to its left node(because the search element is in the left subtree)
case2: If the search element is greater then current_node, its not a potential successor (How can a lesser element be the successor?). So no need to place the succ_node here, but move the current_node to right.
keep repeating the process until you reach null or the element itself and return the succ_node.
If you don't have access to the pointer to the parent node then you need to know who the father is. If you don't know it, how could you go up in the tree ?
A recursive Java solution could look the following way:
public Integer successor(Integer value) {
Node n = succ(root, value, null);
if (null != n) {
return n.value;
}
return null;
}
private Node succ(Node n, Integer x, Node p) {
if (null == n) {
return null;
}
if (x < n.value) {
return succ(n.left, x, n);
} else if (x > n.value) {
return succ(n.right, x, p);
}
if (null != n.right) {
return min(n.right);
}
return p;
}
As a client we simply pass in the value of the node from which we want to know the successor. Then we start searching from the root until we found the value we were looking for. Now there are two cases:
If the current node has a right child, then the successor the smallest element in the current node's right subtree
Otherwise, it was the node p (parent pointer), which was only updated when we went left within the tree
Related
A problem from CLRS ,3ed.
12.3-5
Suppose that instead of each node x keeping the attribute x.p, pointing to x’s parent, it keeps x.succ, pointing to x’s successor. Give pseudocode for SEARCH,INSERT, and DELETE on a binary search tree T using this representation. These procedures should operate in time O(h), where h is the height of the tree T . (Hint:You may wish to implement a subroutine that returns the parent of a node.)
I know how to implement a subroutine that returns the parent of a node in O(h) time.
To find the parent of node x, we should find the maximum key M in the subtree rooted at x first. Then, we go downward to the right from M.succ.left. When we reach x, the node we encounter before x is x's parent.
See the code.
typedef struct TREE{
struct TREE* left,right,succ;
}*BST;
PARENT(BST x)
{
if(x==root) return NULL;
BST max=TREE_MAXIMUM(x);
BST parent=max->succ,t;
if(parent) t=parent->left;
else t=root;
while(t!=x){parent=t;t=t->right;}
return parent;
}
When DELETE x, the succ of x's predecessor should be modified to point to x.succ, no longer x. So now comes the problem--how to find the predecessor of x in O(h) time?
When the left subtree of x is nonempty, it's the rightmost node in x's left subtree. However, when the left subtree of x is empty, the predecessor is x's ancestor, to find which calls O(h) times of PARENT. Does that needs O(h*h) time? Or should we search downward from the root?
Notice that the operation INSERT, also needs to find a node's predecessor.
There comes a question--what if all the keys share the same value? Then we cannot find x's predecessor using comparison, for the key a, which equals to key x, may appears in x's left subtree or right subtree.
In case the left subtree of x is empty, the predecessor of x is not just its ancestor, it's the direct parent of x. So you only need a single call to the parent subroutine, making the over all runtime O(h)+O(h)=O(h).
P.S
Even if it wasn't the direct parent, you still don't have to call parent repeatedly to get all ancestors, you can just start searching for x from the root of the tree as you normally would, saving all of the nodes along the path to x in a single traversal of length O(h). All of the nodes you pass through when searching for x, and only those nodes, are by definition the ancestors of x.
If keys are discrete, the predecessor of x has key that is <= key(x)-1 right? And if you search the tree for key(x)-1 what happens? Don't you necessarily run into pred(x) during that traverse? You'd have to double-check me on that. And of course non-discrete keys (e.g. floating point) could be problematic (as to -1).
Note : O(h) is only possible if the root is directly available.(which should be the case)
Changing your data structure a bit.
typedef struct TREE{
int key;
struct TREE* left,right,succ;
}*BST;
If the left sub-tree is non-empty we use TREE_MAXIMUM, otherwise we search for x in the BST starting the search from root and maintain(in variable goal) the last(i.e latest) node encountered with a right child. At the end of the search, goal is the predecessor.
Predecessor function
BST PRE(BST x)
{
if(x->left!=NULL)
return TREE_MAXIMUM(x->left);
if(x== root)
return NULL;
BST goal = NULL, y = root;
while(1)
{
if(x->key <= y->key)
y=y->left;
else
{
goal=y;
y=y->right;
}
if(x==y)
{
return goal;
}
}
}
This question already has answers here:
How do you validate a binary search tree?
(33 answers)
Closed 8 years ago.
Today I had an interview where I was asked to write a program which takes a Binary Tree and returns true if it is also a Binary Search Tree otherwise false.
My Approach1: Perform an in-order traversal and store the elements in O(n) time. Now scan through the array/list of elements and check if element at ith index is greater than element at (i+1)th index. If such a condition is encountered, return false and break out of the loop. (This takes O(n) time). At the end return true.
But this gentleman wanted me to provide an efficient solution. I tried but I was unsuccessful, because to find if it is a BST I have to check each node.
Moreover he was pointing me to think over recursion.
My Approach 2: A BT is a BST if for any node N N->left is < N and N->right > N , and the in-order successor of left node of N is less than N and the in-order successor of right node of N is greater than N and the left and right subtrees are BSTs.
But this is going to be complicated and running time doesn't seem to be good. Please help if you know any optimal solution.
It's a pretty well-known problem with the following answer:
public boolean isValid(Node root) {
return isValidBST(root, Integer.MIN_VALUE,
Integer.MAX_VALUE);
}
private boolean isValidBST(Node node, int l, int h) {
if(node == null)
return true;
return node.value > l
&& node.value < h
&& isValidBST(node.left, l, node.value)
&& isValidBST(node.right, node.value, h);
}
The recursive call makes sure that subtree nodes are within the range of its ancestors, which is important. The running time complexity will be O(n) since every node is examined once.
The other solution would be to do an inorder traversal and check if the sequence is sorted, especially since you already know that a binary tree is provided as an input.
The answer provided by #Dhruv is a good one. In addition to that here is one another solution that works in O(n) time.
We need to keep track of the previous node in this approach. In each recursive call we check the previous node data with the current node data. If current node data is less than previous we return false
int isBST(node* root) {
static node* prev = NULL;
if(root==NULL)
return 1;
if(!isBST(root->left))
return 0;
if(prev!=NULL && root->data<=prev->data)
return 0;
prev = root;
return isBST(root->right);
}
boolean b = new Sample().isBinarySearchTree(n1, Integer.MIN_VALUE, Integer.MAX_VALUE);
.......
.......
.......
public boolean isBinarySearchTree(TreeNode node, int min, int max){
if(node == null){
return true;
}
boolean left = isBinarySearchTree(node.getLeft(), min, node.getValue());
boolean right = isBinarySearchTree(node.getRight(), node.getValue(), max);
return left && right && (node.getValue()<max) && (node.getValue()>=min);
}
Comments are invited. Thanks.
I think that the second approach is right. The tree can be traversed in a recursive manner. On each iteration lower and upper bounds of current subtree can be stored. If we want to check subtree with root x, and bounds for the subtree are l and h, then all we need is to check that l <= x <= h and to check the left subtree with bounds l and x, and the right one with bounds x and h.
This will have O(n) complexity, because we start from the root and each node is checked only once as root of some subtree. Also, we need O(h) memory for recursive calls, where h is the height of the tree.
There are some examples above using INTEGER.MAX AND MIN
I cant see a reason to pass them and the significance of it,
correct me if I am wrong in anyway or explain me the reason.
More over binary search tree may have objects which are compared by compareTo method or Coperator.. ( hence Integer.MIN and Integer.MAX dont fit on that model)
I am writing a code where it returns true or false
one has to call (root_node,true) and it will return true if it is a bst else false
void boolean isBSt( node root_node, boolean passed_root)
{
if ( node==null){
if ( passed_root)
return false;
// you have passed null pointer as
//root of the tree , since there is no
// valid start point we can throw an exception or return false
return true;
}
if( node.right !=null )
if ( node.right.data <= node.data)
return false;
if ( node.left !=null )
if ! ( node.left.data <= node.data)
return false;
return ( isBST( node.right , false) && isBST( node.left, false ) )
}
Have a look at this solution:
http://preparefortechinterview.blogspot.com/2013/09/am-i-bst.html
It explains different ways and gives you a generic and efficient method too. Hope it helps.
Here is another Solution which uses 2 helper functions to calculate for each node the min and max value in the subtree using the helper function minValue and maxValue
int isBST(struct node* node)
{
if (node == NULL)
return(true);
/* false if the max of the left is > than us */
if (node->left!=NULL && maxValue(node->left) > node->data)
return(false);
/* false if the min of the right is <= than us */
if (node->right!=NULL && minValue(node->right) < node->data)
return(false);
/* false if, recursively, the left or right is not a BST */
if (!isBST(node->left) || !isBST(node->right))
return(false);
/* passing all that, it's a BST */
return(true);
}
Consider a binary search tree, where all keys are unique. Nodes haven't parent pointers.
We have up to n/2 marked nodes.
I can delete all of them at O(n2) time ( using postorder traversal and when encounter a marked node delete each at O(n)). But it is inappropriate.
I need an algorithm to delete all marked nodes at O(n) time.
Thanks.
EDIT After deletion I need to have nodes order unchanged.
EDIT-2 So it should look like I have deleted each marked node using the typical deletion (finding the rightmost node at the left subtree and exchanging it with the node to delete).
There are many ways, but here is one that should be easy to get right, and give you a perfectly balanced tree as a side effect. It requires linear extra space, however.
Create an array of size N minus the number of marked nodes (or N, if you don't know how many are marked and don't want to check it).
Place the elements in order in the array, by inorder traversal, skipping the marked elements. This takes linear time, and stack space proportional to the height of the tree.
Rebuild the tree top-down using the array. The mid element in the array becomes the new root, the mid element of the left subarray its new left child, and the mid element of the right subarray its new right subchild. Repeat recursively. This takes linear time and logarithmic stack space.
Update: forgot to say skipping the marked elements, but that was obvious, right? ;)
I have found how to do it!
We use an inorder traversal.
We check if node need to be deleted before recursive calls of the function.
When we find a node to delete we stand flag toFindMax and searching the rightmost node in the left subtree.
If we encounter another node to delete we push all our variables to the stack and pop them when the node was deleted.
When we find the maximum in the left subtree we save reference to it and to it's parent.
And then, when we recursively return to the initial node to delete, we delete it (exchange it with the maximum).
static class LinearDeletion {
public static Node MIN_VALUE = new Node(Integer.MIN_VALUE);;
boolean toFindMax = false;
Node parentOfMax = null;
Node max = MIN_VALUE;
Stack<Object> stack = new Stack<>();
public void perform(Node x, Node parent) {
if (x.isToDelete) {
stack.push(toFindMax);
stack.push(parentOfMax);
stack.push(max);
toFindMax = true;
parentOfMax = null;
max = MIN_VALUE;
if (x.left != null) {
perform(x.left, x);
}
if (x.left == null) { //deletion of the node
if (parent.left == x) {
parent.left = x.right;
} else {
parent.right = x.right;
}
} else {
if (x.right == null) {
if (parent.left == x) {
parent.left = x.left;
} else {
parent.right = x.left;
}
} else {
x.key = max.key;
x.isToDelete = max.isToDelete;
if (parentOfMax != x) {
parentOfMax.right = max.left;
} else {
x.left = max.left;
}
}
} // end of deletion
max = (Node) stack.pop();
parentOfMax = (Node) stack.pop();
toFindMax = (boolean) stack.pop();
if (toFindMax) { // check if the current node is the maximum
if (x.key > max.key) {
max = x;
parentOfMax = parent;
}
}
if (x.right != null) {
perform(x.right, x);
}
} else {
if (x.left != null) {
perform(x.left, x);
}
if (toFindMax) {
if (x.key > max.key) {
max = x;
parentOfMax = parent;
}
}
if (x.right != null) {
perform(x.right, x);
}
}
}
}
I don't see why a postorder traversal would be O(n2). The reason that deleting a single node is O(n) is that you need to traverse the tree to find the node, which is an O(n) operation. But once you find a node, it can be deleted in O(1) time.* Thus, you can delete all O(n) marked nodes in a single traversal in O(n) time.
* Unless you need to maintain a balanced tree. However, you don't list that as a requirement.
EDIT As #njlarsson correctly points out in his comment, a delete operation is not normally O(1) even after the node is found. However, since the left and right subtrees are being traversed before visiting a node to be deleted, the minimum (or maximum) elements of the subtrees can be obtained at no additional cost during the subtree traversals. This enables an O(1) deletion.
This question already has answers here:
How do you validate a binary search tree?
(33 answers)
Closed 8 years ago.
I wanted to know if a given binary tree is a binary search tree or not.
I don't know How to do that?
The only thing I know is that the inorder traversal of BST will gives you ascending order output.
So, is this the only condition we need to verify or is there anything else we are suppose to check.
In case if there are some other necessary conditions to be checked, What are they? and why those conditions are necessary to be checked? Because, I think, INORDER traversal itself can tell you easily if the given tree is BST or not.
Yes, if inorder traversal of the tree gives you a strictly monotonic list of values that is sufficient to determine that the tree is a BST.
By definition of Binary search tree, if every node of the binary tree satisfy the following conditions then it is a Binary Search Tree:
The left subtree of a node should contain only nodes with keys less than the node’s key
The right subtree of a node should contain only nodes with keys greater than the node’s key
Both the left and right subtrees must also be binary search trees.
All the above conditions are verified if the inorder traversal is in ascending order.
Actually - it is not enough to just do an in order traversal - you also need to verify that each node's value follows the rules of the tree. In the case of a BST, the left child value is less than the node value and the right child value is greater than the node value. Here is a recursive example in Java.
private static boolean isBST(Node current, Comparable more, Comparable less) {
if (current == null)
return true;
if (less != null && current.value.compareTo(less) > 0)
return false;
if (more != null && current.value.compareTo(more) < 0)
return false;
return isBST(current.left, more, current.value) &&
isBST(current.right, current.value, less);
}
public static boolean isBST(BinarySearchTree tree) {
return isBST(tree.getRoot(), null, null);
}
While doing In-Order traversal, we can keep track of previously visited node
Code:
bool isBST(struct node* root)
{
static struct node *prev = NULL;
// traverse the tree in inorder fashion and keep track of prev node
if (root)
{
if (!isBST(root->left))
return false;
// Allows only distinct valued nodes
if (prev != NULL && root->data <= prev->data)
return false;
prev = root;
return isBST(root->right);
}
return true;
}
A simple but elegant recursive solution in Java:
public static boolean isBST(TreeNode node, int leftData, int rightData)
{
if (node == null) return true;
if (node.getData() > leftData || node.getData() <= rightData) return false;
return (isBST(node.left, node.getData(), rightData)
&& isBST(node.right, leftData, node.getData()));
}
The initial call to this function can be something like this:
if (isBST(root, Integer.MAX_VALUE, Integer.MIN_VALUE))
System.out.println("This is a BST.");
else
System.out.println("This is NOT a BST!");
Essentially we keep creating a valid range (starting from [ MIN_VALUE, MAX_VALUE]) and keep shrinking it down foe each node as we go down recursively.
Source: http://exceptional-code.blogspot.com/2011/08/binary-search-trees-primer.html
This question already has answers here:
How do you validate a binary search tree?
(33 answers)
Closed 8 years ago.
Given a simple binary tree, how can we prove that tree is a binary search tree? When we traverse a binary tree, how do we know if the node we are on is the left or right child of its parent? I came up with one solution where i would pass some flag in recursive function call which could keep track of whether the node is left or right child of its parent as well as we need one parent node pointer through which we can compare :-
if(flag == 'L' && node->value < node->parent->value)
then continue recursion;
else{
print "not a binary search tree"
exit;
}
In the same way one if condition is needed for R. Apart from this can you think any other efficient way?
Thanks in advance :)
I would just check:
currentNode.Left.max() < currentNode.Value and currentNode.Left.isBinarySearchTree(). If both are fulfilled, it's a binary search tree.
Edit:
The above does traverse the left tree twice (once for the max() and once for isBinarySearchTree. However, it can be done using just one traversal:
Store the minimum and maximum element in your tree class. Updates, etc. of course can be done in O(1) space and time.
Then, instead of using max(), make a method isInRange(m,M), that checks, whether a (sub)tree contains only elements in the range (m,m+1,...,M).
Define isInRange(m,M) as follows:
bool isInRange(m,M){
if (m < currentNode.Value <= M){
return (currentNode.Left.isInRange(m, currentNode.Value) && currentNode.Right.isInrange(currentNode.Value+1, M));
}
return false;
}
Then, the initial call would be root.isInRange(globalmin, globalmax).
Didn't test it so I don't know if it matters in performance.
The simple answer is to do an in-order depth-first tree traversal and check that the nodes are in order.
Example code (Common Lisp):
(defun binary-search-tree-p (node)
(let ((last-value nil))
(labels ((check (value)
(if (or (null last-value) ; first checked value
(>= value last-value))
(setf last-value value)
nil))
(traverse (node)
(if (null node)
t
(and (traverse (left node)) ; \
(check (value node)) ; > in-order traversal
(traverse (right node)))))) ; /
(traverse node))))
Do you already have a way to iterate/traverse over the elements of the tree? Then you can simply traverse the tree and check that each element is greater than the previous one
You can do a depth-first search over the tree without needing to cache the minimum and maximum values for each subtree in a single pass, but you have to be careful, as comparing the values between and parent and its children is not enough. For example, in the tree:
(10
(7
nil
(20 nil nil)
)
nil
)
The left child (7) of the root (10) satisfy the inequalty (7 <= 10), as does the right child (20) of 7 (20 >= 7). However, the tree is not a BST (Binary Search Tree), because 20 should not be in the left subtree of 10.
To fix this, you may do a traversal passing to extra arguments specifying the valid interval for the subtree.
// The valid interval for the subtree root's value is (lower_bound, upper_bound).
bool IsBST(const node_t* tree, int lower_bound, int upper_bound) {
if (tree == NULL) return true; // An empty subtree is OK.
if (tree->value <= lower_bound) return false; // Value in the root is too low.
if (tree->value >= upper_bound) return false; // Value in the root is too high.
// Values at the left subtree should be strictly lower than tree->value
// and be inside the root valid interval.
if (!IsBST(tree->left, lower_bound, tree->value))
return false;
// Values at the left subtree should be strictly greater than tree->value
// and be inside the root valid interval.
if (!IsBST(tree->right, tree->value, upper_bound))
return false;
// Everything is OK, it is a valid BST.
return true;
}
Notice that by keeping the original valid interval, the function will detect that 20 is invalid at that position, as it is not inside (7, 10). The first call should be done with an infinite interval, like:
IsBST(tree, INT_MIN, INT_MAX);
Hope this helps.