#include <iostream>
using namespace std;
struct Node {
int val;
Node* left;
Node* right;
Node* parent;
Node(int v) : val(v), left(nullptr), right(nullptr), parent(nullptr) {}
};
Node* insert(Node* root, int val, Node* parent = nullptr) {
if (!root) {
Node* n = new Node(val);
n->parent = parent;
return n;
}
if (val < root->val) {
root->left = insert(root->left, val, root);
} else {
root->right = insert(root->right, val, root);
}
return root;
}
Node* maximum(Node* node) {
while (node->right) {
node = node->right; // go right as far as possible
}
return node;
}
Node* inorderPredecessor(Node* node) {
if (!node) return nullptr;
if (node->left) {
// predecessor is max in left subtree
return maximum(node->left);
}
// else go up until node is right child of parent
Node* p = node->parent;
while (p && node == p->left) {
node = p;
p = p->parent; // move up
}
return p;
}
void printNode(Node* node) {
if (node) cout << node->val << "\n";
else cout << "No predecessor\n";
}
int main() {
Node* root = nullptr;
root = insert(root, 20);
root = insert(root, 10);
root = insert(root, 30);
root = insert(root, 5);
root = insert(root, 15);
// find node 15
Node* curr = root->left->right; // 15
Node* pred = inorderPredecessor(curr);
printNode(pred);
return 0;
}
while (node->right) { node = node->right; }
go right as far as possible to find max in left subtree
if (node->left) { return maximum(node->left); }
if left subtree exists, predecessor is max node there
while (p && node == p->left) { node = p; p = p->parent; }
move up until node is right child of parent to find predecessor
return found predecessor or nullptr if none