Discover how to find the 'just before' item in a tree without checking every node!
Why BST Inorder Predecessor in DSA C++?
Imagine you have a family tree drawn on paper, and you want to find the person who comes just before a given person when you list everyone in order. Doing this by hand means checking each name carefully and remembering who came before whom.
Manually searching through the tree is slow and confusing. You might miss someone or get lost in the branches. It's easy to make mistakes and waste time flipping back and forth.
The BST Inorder Predecessor method helps you quickly find the person just before any given person by following simple rules. It uses the tree's structure to jump directly to the right spot without checking everyone.
Node* findPredecessor(Node* root, int key) {
// Search entire tree manually
// Keep track of last smaller value
// Return that value
}Node* findPredecessor(Node* root, int key) {
// Use BST properties
// If left child exists, go left then rightmost
// Else track ancestor
// Return predecessor node
}This lets you quickly find the previous item in order, enabling fast updates, deletions, or queries in sorted data.
When managing a sorted list of appointments, finding the appointment just before a given time helps to schedule new ones without conflicts.
Manual search is slow and error-prone.
BST Inorder Predecessor uses tree rules to find the previous node efficiently.
This operation helps in fast data updates and queries in sorted structures.
Practice
Solution
Step 1: Understand inorder traversal in BST
Inorder traversal visits nodes in ascending order of their values.Step 2: Define inorder predecessor
The inorder predecessor of a node is the node visited just before it in inorder traversal, which means it has the largest value smaller than the current node.Final Answer:
The node with the largest value smaller than the given node -> Option BQuick Check:
Inorder predecessor = largest smaller value [OK]
- Confusing predecessor with successor
- Thinking predecessor is always left child
- Assuming predecessor is the parent node
Node* root and Node* target?Solution
Step 1: Analyze parameter types
The function needs the root pointer and the target node pointer to find the predecessor.Step 2: Analyze return type
The predecessor is a node pointer, so return type should beNode*.Final Answer:
Node* findInorderPredecessor(Node* root, Node* target); -> Option AQuick Check:
Correct parameters and return type [OK]
- Using int return type instead of Node*
- Passing target as int instead of Node*
- Passing nodes by value instead of pointer
struct Node {
int val;
Node* left;
Node* right;
};
Node* findMax(Node* root) {
while (root->right) root = root->right;
return root;
}
Node* inorderPredecessor(Node* root, Node* target) {
if (target->left) return findMax(target->left);
Node* predecessor = nullptr;
while (root) {
if (target->val > root->val) {
predecessor = root;
root = root->right;
} else if (target->val < root->val) {
root = root->left;
} else break;
}
return predecessor;
}
// BST structure:
// 20
// / \
// 10 30
// \ \
// 15 40
Node* root = ...; // root of above BST
Node* target = root->left->right; // node with value 15
Node* pred = inorderPredecessor(root, target);
std::cout << pred->val << std::endl;
What is the output?Solution
Step 1: Check if target has left subtree
Node 15 has no left child, so we skip findMax on left subtree.Step 2: Traverse from root to find predecessor
Start at root (20). Since 15 < 20, go left to 10. Since 15 > 10, set predecessor = 10 and go right to 15. Found target, stop.Final Answer:
10 -> Option AQuick Check:
Largest smaller value than 15 is 10 [OK]
- Returning target node itself
- Returning root node 20 incorrectly
- Confusing predecessor with successor
Node* inorderPredecessor(Node* root, Node* target) {
if (target->left) {
Node* temp = target->left;
while (temp->left) temp = temp->left;
return temp;
}
Node* predecessor = nullptr;
while (root) {
if (target->val > root->val) {
predecessor = root;
root = root->right;
} else if (target->val < root->val) {
root = root->left;
} else break;
}
return predecessor;
}
Solution
Step 1: Check left subtree max search
To find inorder predecessor in left subtree, we must find the maximum node, which is the rightmost node, but code goes left repeatedly.Step 2: Confirm other parts are correct
The rest of the code correctly handles cases without left subtree and initializes predecessor.Final Answer:
The loop to find max in left subtree incorrectly goes left instead of right -> Option DQuick Check:
Max in left subtree requires right traversal [OK]
- Going left instead of right to find max
- Not checking if target->left is null
- Confusing predecessor with successor
Solution
Step 1: Locate node 31
Node 31 is the left child of 35 and has no left subtree.Step 2: Traverse from root to find predecessor
Start at root 25 (31 > 25, predecessor=25, go right to 50). 31 < 50, go left to 35. 31 < 35, go left to 31. Found target, predecessor=25.Step 3: Verify with inorder traversal
Inorder traversal sequence around 31 is ... 24, 25, 31, 35 ... The predecessor of 31 is the largest smaller value, which is 24 (left subtree of 25).Final Answer:
24 -> Option CQuick Check:
Inorder predecessor of 31 is 24 [OK]
- Choosing 25 instead of 24
- Choosing successor 35 instead of predecessor
- Ignoring left subtree check
Ready to prove it?
Pass the test and this pattern moves unknown
