Given a node in a BST, how does one find the next higher key?
Check out here : InOrder Successor in a Binary Search Tree
In Binary Tree, Inorder successor of a node is the next node in Inorder traversal of the Binary Tree. Inorder Successor is NULL for the last node in Inoorder traversal. In Binary Search Tree, Inorder Successor of an input node can also be defined as the node with the smallest key greater than the key of input node.
we dont need parent link or stack to find the in order successor in O(log n) (assuming balanced tree). Keep a temporary variable with the most recent value encountered in the inorder traversal that is larger than the key. if inorder traversal finds that the node does not have a right child, then this would be the inorder successor. else, the leftmost descendant of the right child.
We can find the successor in O(log n) without using parent pointers (for a balanced tree).
The idea is very similar to when you have parent pointers.
We can define a recursive function that achieves this as follows:
Pseudo-code:
Key successor(Node current, Key target):
if current == null
return null
if target == current.key
if current.right != null
return leftMost(current.right).key
else
return specialKey
else
if target < current.key
s = successor(current.left, target)
if s == specialKey
return current.key
else
return s
else
return successor(current.right, target)
Node leftMost(Node current):
while current.left != null
current = current.left
return current
Live Java demo.
Every "tutorial" that I checked on google and all answers in this thread uses the following logic: "If node doesn't have a right child then its in-order successor will be one of its ancestors. Using parent link keep traveling up until you get the node which is the left child of its parent. Then this parent node will be the in-order successor."
This is the same as thinking "if my parent is bigger than me, then I am the left child" (property of a binary search tree). This means that you can simply walk up the parent chain until the above property is true. Which in my opinion results in a more elegant code.
I guess the reason why everyone is checking "am I the left child" by looking at branches instead of values in the code path that utilizes parent links comes from "borrowing" logic from the no-link-to-parent algorithm.
Also from the included code below we can see there is no need for stack data structure as suggested by other answers.
Following is a simple C++ function that works for both use-cases (with and without utilizing the link to parent).
Node* nextInOrder(const Node *node, bool useParentLink) const
{
if (!node)
return nullptr;
// when has a right sub-tree
if (node->right) {
// get left-most node from the right sub-tree
node = node->right;
while (node->left)
node = node->left;
return node;
}
// when does not have a right sub-tree
if (useParentLink) {
Node *parent = node->parent;
while (parent) {
if (parent->value > node->value)
return parent;
parent = parent->parent;
}
return nullptr;
} else {
Node *nextInOrder = nullptr;
// 'root' is a class member pointing to the root of the tree
Node *current = root;
while (current != node) {
if (node->value < current->value) {
nextInOrder = current;
current = current->left;
} else {
current = current->right;
}
}
return nextInOrder;
}
}
Node* previousInOrder(const Node *node, bool useParentLink) const
{
if (!node)
return nullptr;
// when has a left sub-tree
if (node->left) {
// get right-most node from the left sub-tree
node = node->left;
while (node->right)
node = node->right;
return node;
}
// when does not have a left sub-tree
if (useParentLink) {
Node *parent = node->parent;
while (parent) {
if (parent->value < node->value)
return parent;
parent = parent->parent;
}
return nullptr;
} else {
Node *prevInOrder = nullptr;
// 'root' is a class member pointing to the root of the tree
Node *current = root;
while (current != node) {
if (node->value < current->value) {
current = current->left;
} else {
prevInOrder = current;
current = current->right;
}
}
return prevInOrder;
}
}
With Binary Search Tree, the algorithm to find the next highest node of a given node is basically finding the lowest node of the right sub-tree of that node.
The algorithm can just be simply:
Repeat 2 and 3 until we find next highest node.
You can read additional info here(Rus lung)
Node next(Node x)
if x.right != null
return minimum(x.right)
y = x.parent
while y != null and x == y.right
x = y
y = y.parent
return y
Node prev(Node x)
if x.left != null
return maximum(x.left)
y = x.parent
while y != null and x == y.left
x = y
y = y.parent
return y