Inorder predecessor and successor in BST

Last Updated : 3 Aug, 2026

Given the root of a Binary Search Tree (BST) and an integer key, find its inorder predecessor and inorder successor.

The inorder predecessor is the node with the largest value smaller than key, and the inorder successor is the node with the smallest value greater than key. If either does not exist, return NULL for that position.

Examples:

Input: Input: root = [50, 30, 70, 20, 40, 60, 80], key = 65

420046821

Output: [60, 70]
Explanation: In given BST the inorder predecessor of 65 is 60 and inorder successor of 65 is 70.

12

Input: root = [8, 1, 9, N, 4, N, 10, 3], key = 8

Frame-34

Output: [4, 9]
Explanation: In the given BST the inorder predecessor of 8 is 4 and inorder successor of 8 is 9.

Frame-3141
Try It Yourself
redirect icon

[Naive Approach] Maintaining predecessor and successors - O(n) Time and O(1) Space

The idea is to traverse the entire BST while maintaining the inorder predecessor and successor of the given key. For each node, if its value is smaller than the key, it can be a potential predecessor, so we update it if it is greater than the current predecessor. Similarly, if its value is greater than the key, it can be a potential successor, so we update it if it is smaller than the current successor.

C++
#include <iostream>
#include <vector>
using namespace std;

// Node Structure
class Node {
public:
    int data;
    Node* left;
    Node* right;
    Node(int x) {
        data = x;
        left = right = nullptr;
    }
};

// traversal to find 
// predecessor and successor
void preorder(Node* root, int key, Node*& pre, Node*& suc) {
    if (root == nullptr) return;

    if (root->data < key && (pre == nullptr || pre->data < root->data)) {
        pre = root;
    }

    if (root->data > key && (suc == nullptr || suc->data > root->data)) {
        suc = root;
    }

    preorder(root->left, key, pre, suc);
    preorder(root->right, key, pre, suc);
}

// return vector with predecessor at 
// index 0 and successor at index 1
vector<Node*> findPreSuc(Node* root, int key) {
    Node* pre = nullptr;
    Node* suc = nullptr;
    preorder(root, key, pre, suc);
    return {pre, suc};
}

int main() {
    // Create BST:
    //      50 
    //     /  \
    //   30     70
    //   / \    / \
    // 20  40  60  80

    int key = 65;
    Node* root = new Node(50);
    root->left = new Node(30);
    root->right = new Node(70);
    root->left->left = new Node(20);
    root->left->right = new Node(40);
    root->right->left = new Node(60);
    root->right->right = new Node(80);

    vector<Node*> result = findPreSuc(root, key);
    Node* pre = result[0];
    Node* suc = result[1];

    cout << (pre ? to_string(pre->data) : "NULL") << " ";
    cout << (suc ? to_string(suc->data) : "NULL") << endl;
}
Java
import java.util.ArrayList;
import java.util.Arrays;

// Node Structure
class Node {
    int data;
    Node left, right;
    Node(int x) {
        data = x;
        left = right = null;
    }
}

class GFG {
    
    // return ArrayList with predecessor at index 0 
    // and successor at index 1
    static ArrayList<Node> findPreSuc(Node root, int key) {
        Node[] pre = new Node[1];
        Node[] suc = new Node[1];
        preorder(root, key, pre, suc);
        return new ArrayList<>(Arrays.asList(pre[0], suc[0]));
    }
    
    // traversal to find predecessor and successor
    static void preorder(Node root, int key, Node[] pre, Node[] suc) {
        if (root == null) return;
    
        if (root.data < key && (pre[0] == null || pre[0].data < root.data)) {
            pre[0] = root;
        }
    
        if (root.data > key && (suc[0] == null || suc[0].data > root.data)) {
            suc[0] = root;
        }
    
        preorder(root.left, key, pre, suc);
        preorder(root.right, key, pre, suc);
    }
    
    public static void main(String[] args) {
        
        // Create BST:
        //      50 
        //     /  \
        //   30     70
        //   / \    / \
        // 20  40  60  80
        
        int key = 65;
        
        Node root = new Node(50);
        root.left = new Node(30);
        root.right = new Node(70);
        root.left.left = new Node(20);
        root.left.right = new Node(40);
        root.right.left = new Node(60);
        root.right.right = new Node(80);

        ArrayList<Node> result = findPreSuc(root, key);
        Node pre = result.get(0);
        Node suc = result.get(1);
        
        System.out.print((pre == null) ? "NULL " : (pre.data + " "));
        System.out.print((suc == null) ? "NULL " : (suc.data + " "));
    }
}
Python
# Node Structure
class Node:
    def __init__(self, x):
        self.data = x
        self.left = None
        self.right = None

# traversal to find predecessor and successor
def preorder(root, key, pre, suc):
    if root is None:
        return

    if root.data < key and (pre[0] is None or pre[0].data < root.data):
        pre[0] = root

    if root.data > key and (suc[0] is None or suc[0].data > root.data):
        suc[0] = root

    preorder(root.left, key, pre, suc)
    preorder(root.right, key, pre, suc)

# return list with predecessor at index 0 and successor at index 1
def findPreSuc(root, key):
    pre = [None]
    suc = [None]
    preorder(root, key, pre, suc)
    return [pre[0], suc[0]]

if __name__ == "__main__":
    
    # Create BST:
    #      50 
    #     /  \
    #   30     70
    #   / \    / \
    # 20  40  60  80
    key = 65
    root = Node(50)
    root.left = Node(30)
    root.right = Node(70)
    root.left.left = Node(20)
    root.left.right = Node(40)
    root.right.left = Node(60)
    root.right.right = Node(80)
    
    result = findPreSuc(root, key)
    pre = result[0]
    suc = result[1]
    
    print((str(pre.data) if pre else "NULL"), (str(suc.data) if suc else "NULL"))
C#
using System;
using System.Collections.Generic;

// Node Structure
class Node {
    public int data;
    public Node left, right;
    public Node(int x) {
        data = x;
        left = right = null;
    }
}

class GFG {
    
    // return List with predecessor at index 0 
    // and successor at index 1
    static List<Node> findPreSuc(Node root, int key) {
        Node[] pre = new Node[1];
        Node[] suc = new Node[1];
        preorder(root, key, pre, suc);
        return new List<Node> { pre[0], suc[0] };
    }

    // traversal to find 
    // predecessor and successor
    static void preorder(Node root, int key, Node[] pre, Node[] suc) {
        if (root == null) return;

        if (root.data < key && (pre[0] == null || pre[0].data < root.data)) {
            pre[0] = root;
        }

        if (root.data > key && (suc[0] == null || suc[0].data > root.data)) {
            suc[0] = root;
        }

        preorder(root.left, key, pre, suc);
        preorder(root.right, key, pre, suc);
    }

    public static void Main() {
        // Create BST:
        //      50 
        //     /  \
        //   30     70
        //   / \    / \
        // 20  40  60  80

        int key = 65;
        Node root = new Node(50);
        root.left = new Node(30);
        root.right = new Node(70);
        root.left.left = new Node(20);
        root.left.right = new Node(40);
        root.right.left = new Node(60);
        root.right.right = new Node(80);

        List<Node> result = findPreSuc(root, key);
        Node pre = result[0];
        Node suc = result[1];

        Console.Write((pre == null ? "NULL " : pre.data + " "));
        Console.Write((suc == null ? "NULL " : suc.data + " "));
    }
}
JavaScript
// Node Structure
class Node {
    constructor(x) {
        this.data = x;
        this.left = null;
        this.right = null;
    }
}

// traversal to find predecessor and successor
function preorder(root, key, pre, suc) {
    if (root === null) return;

    if (root.data < key && (pre[0] === null || pre[0].data < root.data)) {
        pre[0] = root;
    }

    if (root.data > key && (suc[0] === null || suc[0].data > root.data)) {
        suc[0] = root;
    }

    preorder(root.left, key, pre, suc);
    preorder(root.right, key, pre, suc);
}

// return array with predecessor at index 0 and successor at index 1
function findPreSuc(root, key) {
    let pre = [null];
    let suc = [null];
    preorder(root, key, pre, suc);
    return [pre[0], suc[0]];
}

// Driver code

// Create BST:
//      50 
//     /  \
//   30     70
//   / \    / \
// 20  40  60  80
let key = 65;
let root = new Node(50);
root.left = new Node(30);
root.right = new Node(70);
root.left.left = new Node(20);
root.left.right = new Node(40);
root.right.left = new Node(60);
root.right.right = new Node(80);

let result = findPreSuc(root, key);
let pre = result[0];
let suc = result[1];

console.log((pre ? pre.data : "NULL") + " " + 
            (suc ? suc.data : "NULL"));

Output
60 70

[Expected Approach-1] Using Two Traversals - O(h) Time and O(1) Space

The idea is to traverse the BST twice-once to find the predecessor and once to find the successor. For the predecessor, if the current node is smaller than the key, update it as the potential predecessor and move to the right subtree; otherwise, move to the left subtree. Similarly, for the successor, if the current node is greater than the key, update it as the potential successor and move to the left subtree; otherwise, move to the right subtree.

C++
#include <vector>
#include <iostream>
using namespace std;

// Node Structure
class Node {
  public:
    int data;
    Node* left;
    Node* right;
    Node(int val) {
        data = val;
        left = right = nullptr;
    }
};

// Finding predecessor of key
Node* findPredecessor(Node* root, int key) {
    Node* predecessor = nullptr;
    while (root) {
        if (key > root->data) {
            
            // potential predecessor
            predecessor = root;
            
            // look for larger predecessors
            root = root->right;
        } else {
            root = root->left;
        }
    }
    return predecessor;
}

// Finding successor of key
Node* findSuccessor(Node* root, int key) {
    Node* successor = nullptr;
    while (root) {
        if (key < root->data) {
            
            // potential successor
            successor = root;
            
            // look for smaller successor
            root = root->left;
        } else {
            root = root->right;
        }
    }
    return successor;
}

// return vector with predecessor at index 0 
// and successor at index 1
vector<Node*> findPreSuc(Node* root, int key) {
    Node* pre = findPredecessor(root, key);
    Node* suc = findSuccessor(root, key);
    return {pre, suc};
}

int main() {
    
    // Create BST:
    //      50 
    //     /  \
    //   30     70
    //   / \    / \
    // 20  40  60  80
    
    Node* root = new Node(50);
    root->left = new Node(30);
    root->right = new Node(70);
    root->left->left = new Node(20);
    root->left->right = new Node(40);
    root->right->left = new Node(60);
    root->right->right = new Node(80);

    int key = 65;
    vector<Node*> result = findPreSuc(root, key);
    Node* pre = result[0];
    Node* suc = result[1];

    cout << (pre ? to_string(pre->data) : string("NULL")) << " "
     << (suc ? to_string(suc->data) : string("NULL"));

    return 0;
}
Java
import java.util.ArrayList;
import java.util.Arrays;

// Node Structure
class Node {
    int data;
    Node left, right;
    Node(int x) {
        data = x;
        left = right = null;
    }
}

class GFG {
    
    // return ArrayList with predecessor at index 0 
    // and successor at index 1
    static ArrayList<Node> findPreSuc(Node root, int key) {
        Node predecessor = findPredecessor(root, key);
        
        Node successor = findSuccessor(root, key);
        
        return new ArrayList<>(Arrays.asList(predecessor, successor));
    }
    
    // Finding predecessor of key
    static Node findPredecessor(Node root, int key) {
        Node predecessor = null;
        while (root != null) {
            if (key > root.data) {
                
                // potential predecessor
                predecessor = root;
                
                // look for larger predecessors
                root = root.right;
            } else {
                root = root.left;
            }
        }
        return predecessor;
    }
    
    // Finding successor of key
    static Node findSuccessor(Node root, int key) {
        Node successor = null;
        while (root != null) {
            if (key < root.data) {
                
                // potential successor
                successor = root;
                
                // look for smaller successors
                root = root.left;
            } else {
                root = root.right;
            }
        }
        return successor;
    }
    
    public static void main(String[] args) {
        
        // Create BST:
        //      50 
        //     /  \
        //   30     70
        //   / \    / \
        // 20  40  60  80
        
        int key = 65;
        
        Node root = new Node(50);
        root.left = new Node(30);
        root.right = new Node(70);
        root.left.left = new Node(20);
        root.left.right = new Node(40);
        root.right.left = new Node(60);
        root.right.right = new Node(80);

        ArrayList<Node> result = findPreSuc(root, key);
        Node pre = result.get(0);
        Node suc = result.get(1);

        System.out.print((pre != null ? pre.data : "NULL") + " ");
        System.out.print(suc != null ? suc.data : "NULL");
    }
}
Python
# Node Structure
class Node:
    def __init__(self, x):
        self.data = x
        self.left = None
        self.right = None

# Finding predecessor of key
def findPredecessor(root, key):
    predecessor = None
    while root:
        if key > root.data:
            
            #  potential predecessor
            predecessor = root;
            
            #  look for larger predecessors
            root = root.right
        else:
            root = root.left
    return predecessor

# Finding successor of key
def findSuccessor(root, key):
    successor = None
    while root:
        if key < root.data:
            
            # potential successor
            successor = root
            
            # look for smaller successor
            root = root.left
        else:
            root = root.right
    return successor


#  return list with predecessor at index 0 
#  and successor at index 1
def findPreSuc(root, key):
    return [findPredecessor(root, key), findSuccessor(root, key)]

if __name__ == '__main__':
    # Create BST:
    #          50 
    #         /  \
    #       30     70
    #       / \    / \
    #     20  40  60  80
    
    root = Node(50)
    root.left = Node(30)
    root.right = Node(70)
    root.left.left = Node(20)
    root.left.right = Node(40)
    root.right.left = Node(60)
    root.right.right = Node(80)
    
    key = 65
    pre, suc = findPreSuc(root, key)
    print((pre.data if pre else "NULL"), 
          (suc.data if suc else "NULL"))
C#
using System;
using System.Collections.Generic;

// Node Structure
class Node {
    public int data;
    public Node left, right;
    public Node(int x) {
        data = x;
        left = right = null;
    }
}

class GFG {
    
    // Finding predecessor of key
    static Node findPredecessor(Node root, int key) {
        Node predecessor = null;
        while (root != null) {
            if (key > root.data) {
                
                // potential predecessor
                predecessor = root;
                
                // look for larger predecessors
                root = root.right;
            } else {
                root = root.left;
            }
        }
        return predecessor;
    }
    
    // Finding successor of key
    static Node findSuccessor(Node root, int key) {
        Node successor = null;
        while (root != null) {
            if (key < root.data) {
                
                // potential successor
                successor = root;
                
                // look for smaller successors
                root = root.left;
            } else {
                root = root.right;
            }
        }
        return successor;
    }
    
    // return List with predecessor at index 0 
    // and successor at index 1
    static List<Node> findPreSuc(Node root, int key) {
        Node pre = findPredecessor(root, key);
        Node suc = findSuccessor(root, key);
        return new List<Node> { pre, suc };
    }

    static void Main() {
        
        // Create BST:
        //      50 
        //     /  \
        //   30     70
        //   / \    / \
        // 20  40  60  80

        Node root = new Node(50);
        root.left = new Node(30);
        root.right = new Node(70);
        root.left.left = new Node(20);
        root.left.right = new Node(40);
        root.right.left = new Node(60);
        root.right.right = new Node(80);

        int key = 65;
        List<Node> result = findPreSuc(root, key);
        Node pre = result[0];
        Node suc = result[1];

        Console.WriteLine(
            $"{(pre != null ? pre.data.ToString() : "NULL")} " +
            $"{(suc != null ? suc.data.ToString() : "NULL")}"
        );
    }
}
JavaScript
// Node Structure
class Node {
    constructor(x) {
        this.data = x;
        this.left = this.right = null;
    }
}


// Finding predecessor of key
function findPredecessor(root, key) {
    let predecessor = null;
    while (root) {
        if (key > root.data) {
            
            // potential predecessor
            predecessor = root;
            
            // look for larger predecessors
            root = root.right;
        } else {
            root = root.left;
        }
    }
    return predecessor;
}

// Finding successor of key
function findSuccessor(root, key) {
    let successor = null;
    while (root) {
        if (key < root.data) {
            
            // potential successor
            successor = root;
            
            // look for smaller successor
            root = root.left;
        } else {
            root = root.right;
        }
    }
    return successor;
}

// return array with predecessor at index 0 
// and successor at index 1
function findPreSuc(root, key) {
    return [findPredecessor(root, key), findSuccessor(root, key)];
}

// Driver Code

// Create BST:
//      50 
//     /  \
//   30     70
//   / \    / \
// 20  40  60  80

let root = new Node(50);
root.left = new Node(30);
root.right = new Node(70);
root.left.left = new Node(20);
root.left.right = new Node(40);
root.right.left = new Node(60);
root.right.right = new Node(80);

let key = 65;
let [pre, suc] = findPreSuc(root, key);
console.log((pre ? pre.data : "NULL") + " " + (suc ? suc.data : "NULL"));

Output
60 70

[Expected Approach-2] Using Single Traversal - O(h) Time and O(1) Space

The idea is to traverse the BST only once while maintaining both the predecessor and successor. If the current node is smaller than the key, update it as the potential predecessor and move to the right subtree. If it is greater than the key, update it as the potential successor and move to the left subtree. When the key is found, the predecessor is the rightmost node in its left subtree, and the successor is the leftmost node in its right subtree.

Consider the following BST and key = 65:

file

Initially, pre = NULL, suc = NULL, curr = 50

  • At 50: 50 < 65, so update pre = 50 and move to the right child.
  • At 70: 70 > 65, so update suc = 70 and move to the left child.
  • At 60: 60 < 65, so update pre = 60 and move to the right child.
  • curr becomes NULL, so the search ends.

Since the key is not present in the BST, the last recorded predecessor and successor are the required answer, i.e., Predecessor = 60 and Successor = 70.

If the key exists, say key = 70, then:

  • The predecessor is the rightmost node in its left subtree (60).
  • The successor is the leftmost node in its right subtree (80).

Hence, the answer is: Predecessor = 60 and Successor = 80

C++
#include <vector>
#include <iostream>
using namespace std;

// Node Structure
class Node {
  public:
    int data;
    Node* left;
    Node* right;
    Node(int val) {
        data = val;
        left = right = nullptr;
    }
};

Node* rightMost(Node* node) {
    while (node->right)
        node = node->right;
    return node;
}

Node* leftMost(Node* node) {
    while (node->left)
        node = node->left;
    return node;
}

// return vector with predecessor at index 0 
// and successor at index 1
vector<Node*> findPreSuc(Node* root, int key) {
    Node* pre = nullptr;
    Node* suc = nullptr;
    Node* curr = root;

    while (curr) {
        if (curr->data < key) {
            pre = curr;
            
            // look for predecessor with greater value
            curr = curr->right;
        } else if (curr->data > key) {
            suc = curr;
            
            // look for successor with smaller value
            curr = curr->left;
        } else {
            if (curr->left)
                pre = rightMost(curr->left);
            if (curr->right)
                suc = leftMost(curr->right);
            break;
        }
    }

    return {pre, suc};
}

int main() {
    int key = 65;

    // Create BST:
    //      50 
    //     /  \
    //   30     70
    //   / \    / \
    // 20  40  60  80
    
    Node* root = new Node(50);
    root->left = new Node(30);
    root->right = new Node(70);
    root->left->left = new Node(20);
    root->left->right = new Node(40);
    root->right->left = new Node(60);
    root->right->right = new Node(80);

    vector<Node*> result = findPreSuc(root, key);
    Node* pre = result[0];
    Node* suc = result[1];

    cout << (pre ? to_string(pre->data) : "NULL") << " ";
    cout << (suc ? to_string(suc->data) : "NULL");
}
Java
import java.util.ArrayList;

// Node Structure
class Node {
    int data;
    Node left, right;

    Node(int x) {
        data = x;
        left = right = null;
    }
}

class GFG {

    static Node rightMost(Node node) {
        while (node.right != null) {
            node = node.right;
        }
        return node;
    }

    static Node leftMost(Node node) {
        while (node.left != null) {
            node = node.left;
        }
        return node;
    }

    // return ArrayList with predecessor at index 0 
    // and successor at index 1
    static ArrayList<Node> findPreSuc(Node root, int key) {
        Node pre = null, suc = null;
        Node curr = root;

        while (curr != null) {
            if (curr.data < key) {
                pre = curr;
                
                // look for predecessor with greater value
                curr = curr.right;
            } else if (curr.data > key) {
                suc = curr;
                
                // look for successor with smaller value
                curr = curr.left;
            } else {
                if (curr.left != null)
                    pre = rightMost(curr.left);
                if (curr.right != null)
                    suc = leftMost(curr.right);
                break;
            }
        }

        ArrayList<Node> result = new ArrayList<>();
        result.add(pre);
        result.add(suc);
        return result;
    }

    public static void main(String[] args) {
        int key = 65;

        // Create BST:
        //      50 
        //     /  \
        //   30     70
        //   / \    / \
        // 20  40  60  80
        Node root = new Node(50);
        root.left = new Node(30);
        root.right = new Node(70);
        root.left.left = new Node(20);
        root.left.right = new Node(40);
        root.right.left = new Node(60);
        root.right.right = new Node(80);

        ArrayList<Node> result = findPreSuc(root, key);
        Node pre = result.get(0);
        Node suc = result.get(1);

        System.out.print((pre == null) ? "NULL " : (pre.data + " "));
        
        System.out.print((suc == null) ? "NULL " : (suc.data + " "));
    }
}
Python
# Node Structure
class Node:
    def __init__(self, x):
        self.data = x
        self.left = None
        self.right = None

def rightMost(node):
    while node.right:
        node = node.right
    return node


def leftMost(node):
    while node.left:
        node = node.left
    return node

#  return list with predecessor at index 0 
#  and successor at index 1
def findPreSuc(root, key):
    pre, suc = None, None
    curr = root

    while curr:
        if curr.data < key:
            pre = curr
            
            #  look for predecessor with greater value
            curr = curr.right
        elif curr.data > key:
            suc = curr
            
            #  look for successor with smaller value
            curr = curr.left
        else:
            if curr.left:
                pre = rightMost(curr.left)
            if curr.right:
                suc = leftMost(curr.right)
            break

    return [pre, suc]

if __name__ == "__main__":
    key = 65
    
    # Create BST:
    #      50 
    #     /  \
    #   30     70
    #   / \    / \
    # 20  40  60  80
    root = Node(50)
    root.left = Node(30)
    root.right = Node(70)
    root.left.left = Node(20)
    root.left.right = Node(40)
    root.right.left = Node(60)
    root.right.right = Node(80)
    
    pre, suc = findPreSuc(root, key)
    print((pre.data if pre else "NULL"), (suc.data if suc else "NULL"))
C#
using System;
using System.Collections.Generic;

// Node Structure
class Node {
    public int data;
    public Node left, right;
    public Node(int x) {
        data = x;
        left = right = null;
    }
}

class GfG {

    static Node RightMost(Node node) {
        while (node.right != null)
            node = node.right;
        return node;
    }

    static Node LeftMost(Node node) {
        while (node.left != null)
            node = node.left;
        return node;
    }

    // return List with predecessor at index 0 
    // and successor at index 1
    public static List<Node> FindPreSuc(Node root, int key) {
        Node pre = null, suc = null;
        Node curr = root;

        while (curr != null) {
            if (curr.data < key) {
                pre = curr;
                
                // look for predecessor with greater value
                curr = curr.right;
            } else if (curr.data > key) {
                suc = curr;
                
                // look for successor with smaller value
                curr = curr.left;
            } else {
                if (curr.left != null)
                    pre = RightMost(curr.left);
                if (curr.right != null)
                    suc = LeftMost(curr.right);
                break;
            }
        }

        return new List<Node> { pre, suc };
    }

    public static void Main() {
        int key = 65;
        
        // Create BST:
        //      50 
        //     /  \
        //   30     70
        //   / \    / \
        // 20  40  60  80
        
        Node root = new Node(50);
        root.left = new Node(30);
        root.right = new Node(70);
        root.left.left = new Node(20);
        root.left.right = new Node(40);
        root.right.left = new Node(60);
        root.right.right = new Node(80);

        List<Node> result = FindPreSuc(root, key);
        Node pre = result[0];
        Node suc = result[1];

        Console.Write((pre == null ? "NULL " : pre.data + " "));
        Console.Write((suc == null ? "NULL" : suc.data.ToString()));
    }
}
Javascript
// Node Structure
class Node {
    constructor(x) {
        this.data = x;
        this.left = null;
        this.right = null;
    }
}

function leftMost(node) {
    while (node.left) node = node.left;
    return node;
}

function rightMost(node) {
    while (node.right) node = node.right;
    return node;
}

// return array with predecessor at index 0 
// and successor at index 1
function findPreSuc(root, key) {
    let pre = null, suc = null;
    let curr = root;

    while (curr) {
        if (curr.data < key) {
            pre = curr;
            
            // look for predecessor with greater value
            curr = curr.right;
        } else if (curr.data > key) {
            suc = curr;
            
            // look for successor with smaller value
            curr = curr.left;
        } else {
            if (curr.left) pre = rightMost(curr.left);
            if (curr.right) suc = leftMost(curr.right);
            break;
        }
    }

    return [pre, suc];
}

// Driver code

// Create BST:
//      50 
//     /  \
//   30     70
//   / \    / \
// 20  40  60  80

let key = 65;
let root = new Node(50);
root.left = new Node(30);
root.right = new Node(70);
root.left.left = new Node(20);
root.left.right = new Node(40);
root.right.left = new Node(60);
root.right.right = new Node(80);

let [pre, suc] = findPreSuc(root, key);
console.log((pre ? pre.data : "NULL") + " " + (suc ? suc.data : "NULL"));

Output
60 70
Comment