Implement a Binary Search Tree in JavaScript
This challenge asks you to build a fundamental data structure: a Binary Search Tree (BST). BSTs are incredibly useful for efficiently searching, inserting, and deleting data. Mastering their implementation is a crucial step in understanding more complex data structures and algorithms.
Problem Description
You need to implement a BinarySearchTree class in JavaScript. This class should represent a binary search tree and support basic operations.
Key Requirements:
- Node Structure: Each node in the BST should store a
value. It should also have references to itsleftandrightchildren. - Insertion (
insert(value)): Implement a method to insert a new node with a givenvalueinto the BST. The BST property must be maintained: all values in the left subtree of a node must be less than the node's value, and all values in the right subtree must be greater than the node's value. Duplicates can be handled in a consistent way (e.g., placed in the right subtree or ignored). For this challenge, assume duplicates will be placed in the right subtree. - Search (
search(value)): Implement a method to check if a givenvalueexists in the BST. This method should returntrueif the value is found, andfalseotherwise. - Minimum Value (
findMin()): Implement a method to find the smallest value in the BST. - Maximum Value (
findMax()): Implement a method to find the largest value in the BST.
Expected Behavior:
- When inserting values, the tree should maintain its BST properties.
- The
searchmethod should be efficient, leveraging the BST structure. findMinandfindMaxshould return the appropriate values.
Edge Cases to Consider:
- Inserting into an empty tree.
- Searching for a value in an empty tree.
- Searching for the root value.
- Searching for values that do not exist.
findMinandfindMaxon an empty tree (should returnnullorundefined).
Examples
Example 1:
Input:
let bst = new BinarySearchTree();
bst.insert(10);
bst.insert(5);
bst.insert(15);
bst.insert(2);
bst.insert(5); // Duplicate
bst.insert(13);
bst.insert(22);
Output:
bst.search(10) // returns true
bst.search(7) // returns false
bst.findMin() // returns 2
bst.findMax() // returns 22
Explanation: The BST is constructed as follows:
10
/ \
5 15
/ \ / \
2 5 13 22
The search operations correctly identify existing and non-existing values. findMin returns the leftmost node's value (2), and findMax returns the rightmost node's value (22).
Example 2:
Input:
let bst = new BinarySearchTree();
bst.insert(50);
bst.insert(30);
bst.insert(70);
bst.insert(20);
bst.insert(40);
bst.insert(60);
bst.insert(80);
Output:
bst.findMin() // returns 20
bst.findMax() // returns 80
bst.search(30) // returns true
bst.search(55) // returns false
Explanation: A balanced BST is formed. findMin correctly identifies the smallest element at the far left, and findMax at the far right.
Example 3: (Edge Case - Empty Tree)
Input:
let bst = new BinarySearchTree();
Output:
bst.search(5) // returns false
bst.findMin() // returns null (or undefined, depending on implementation choice)
bst.findMax() // returns null (or undefined)
Explanation: For an empty tree, searches should always fail, and findMin/findMax should indicate the absence of values.
Constraints
- Node values will be integers.
- The
insertmethod will be called at least once. - The
searchmethod will be called at least once. findMinandfindMaxmight be called on an empty tree.- The tree can potentially become unbalanced (no AVL or Red-Black tree balancing required for this challenge).
Notes
- You will need to define a
Nodeclass (or a factory function) to represent the nodes within yourBinarySearchTree. - The
insertoperation can be implemented recursively or iteratively. - The
search,findMin, andfindMaxoperations are typically implemented recursively for elegance, but iterative solutions are also valid. - Consider how to handle the root of the tree when it's initially empty.
- For
findMin, you'll traverse left as far as possible. ForfindMax, you'll traverse right as far as possible.