Binary Search Tree in Javascript

A Binary Search Tree (BST) is a specialized data structure where each node follows a specific ordering rule. A node's left child must have a value less than its parent's value, and the node's right child must have a value greater than its parent's value.

8 3 10 1 6 14

This ordering property makes BSTs efficient for searching, insertion, and deletion operations with an average time complexity of O(log n).

Binary Search Tree Implementation

First, let's create a Node class and the basic BST structure:

class Node {
    constructor(data) {
        this.data = data;
        this.left = null;
        this.right = null;
    }
}

class BinarySearchTree {
    constructor() {
        this.root = null;
    }
}

// Create a new BST
const bst = new BinarySearchTree();
console.log("Empty BST created:", bst.root); // null
Empty BST created: null

Inserting Values into BST

class Node {
    constructor(data) {
        this.data = data;
        this.left = null;
        this.right = null;
    }
}

class BinarySearchTree {
    constructor() {
        this.root = null;
    }
    
    insert(data) {
        const newNode = new Node(data);
        
        if (this.root === null) {
            this.root = newNode;
        } else {
            this.insertNode(this.root, newNode);
        }
    }
    
    insertNode(node, newNode) {
        if (newNode.data < node.data) {
            if (node.left === null) {
                node.left = newNode;
            } else {
                this.insertNode(node.left, newNode);
            }
        } else {
            if (node.right === null) {
                node.right = newNode;
            } else {
                this.insertNode(node.right, newNode);
            }
        }
    }
}

// Insert values
const bst = new BinarySearchTree();
bst.insert(8);
bst.insert(3);
bst.insert(10);
bst.insert(1);
bst.insert(6);

console.log("Root value:", bst.root.data);
console.log("Left child of root:", bst.root.left.data);
console.log("Right child of root:", bst.root.right.data);
Root value: 8
Left child of root: 3
Right child of root: 10

Tree Traversal Methods

In-order Traversal

In-order traversal visits nodes in ascending order (left ? root ? right):

class Node {
    constructor(data) {
        this.data = data;
        this.left = null;
        this.right = null;
    }
}

class BinarySearchTree {
    constructor() {
        this.root = null;
    }
    
    insert(data) {
        const newNode = new Node(data);
        if (this.root === null) {
            this.root = newNode;
        } else {
            this.insertNode(this.root, newNode);
        }
    }
    
    insertNode(node, newNode) {
        if (newNode.data < node.data) {
            if (node.left === null) {
                node.left = newNode;
            } else {
                this.insertNode(node.left, newNode);
            }
        } else {
            if (node.right === null) {
                node.right = newNode;
            } else {
                this.insertNode(node.right, newNode);
            }
        }
    }
    
    inOrder(node = this.root, result = []) {
        if (node !== null) {
            this.inOrder(node.left, result);
            result.push(node.data);
            this.inOrder(node.right, result);
        }
        return result;
    }
}

const bst = new BinarySearchTree();
[8, 3, 10, 1, 6, 14].forEach(val => bst.insert(val));

console.log("In-order traversal:", bst.inOrder());
In-order traversal: [ 1, 3, 6, 8, 10, 14 ]

Pre-order and Post-order Traversal

class BinarySearchTree {
    constructor() {
        this.root = null;
    }
    
    insert(data) {
        const newNode = new Node(data);
        if (this.root === null) {
            this.root = newNode;
        } else {
            this.insertNode(this.root, newNode);
        }
    }
    
    insertNode(node, newNode) {
        if (newNode.data < node.data) {
            if (node.left === null) {
                node.left = newNode;
            } else {
                this.insertNode(node.left, newNode);
            }
        } else {
            if (node.right === null) {
                node.right = newNode;
            } else {
                this.insertNode(node.right, newNode);
            }
        }
    }
    
    preOrder(node = this.root, result = []) {
        if (node !== null) {
            result.push(node.data);      // Visit root first
            this.preOrder(node.left, result);
            this.preOrder(node.right, result);
        }
        return result;
    }
    
    postOrder(node = this.root, result = []) {
        if (node !== null) {
            this.postOrder(node.left, result);
            this.postOrder(node.right, result);
            result.push(node.data);      // Visit root last
        }
        return result;
    }
}

class Node {
    constructor(data) {
        this.data = data;
        this.left = null;
        this.right = null;
    }
}

const bst = new BinarySearchTree();
[8, 3, 10, 1, 6].forEach(val => bst.insert(val));

console.log("Pre-order traversal:", bst.preOrder());
console.log("Post-order traversal:", bst.postOrder());
Pre-order traversal: [ 8, 3, 1, 6, 10 ]
Post-order traversal: [ 1, 6, 3, 10, 8 ]

Searching Operations

Search for a Value

class Node {
    constructor(data) {
        this.data = data;
        this.left = null;
        this.right = null;
    }
}

class BinarySearchTree {
    constructor() {
        this.root = null;
    }
    
    insert(data) {
        const newNode = new Node(data);
        if (this.root === null) {
            this.root = newNode;
        } else {
            this.insertNode(this.root, newNode);
        }
    }
    
    insertNode(node, newNode) {
        if (newNode.data < node.data) {
            node.left === null ? node.left = newNode : this.insertNode(node.left, newNode);
        } else {
            node.right === null ? node.right = newNode : this.insertNode(node.right, newNode);
        }
    }
    
    search(data, node = this.root) {
        if (node === null) return false;
        if (data === node.data) return true;
        
        return data < node.data ? 
            this.search(data, node.left) : 
            this.search(data, node.right);
    }
    
    findMin(node = this.root) {
        if (node === null) return null;
        while (node.left !== null) {
            node = node.left;
        }
        return node.data;
    }
    
    findMax(node = this.root) {
        if (node === null) return null;
        while (node.right !== null) {
            node = node.right;
        }
        return node.data;
    }
}

const bst = new BinarySearchTree();
[8, 3, 10, 1, 6, 14].forEach(val => bst.insert(val));

console.log("Search for 6:", bst.search(6));
console.log("Search for 15:", bst.search(15));
console.log("Minimum value:", bst.findMin());
console.log("Maximum value:", bst.findMax());
Search for 6: true
Search for 15: false
Minimum value: 1
Maximum value: 14

Comparison of Traversal Methods

Traversal Type Order Use Case
In-order Left ? Root ? Right Get sorted values
Pre-order Root ? Left ? Right Copy/serialize tree
Post-order Left ? Right ? Root Delete tree nodes

Conclusion

Binary Search Trees provide efficient O(log n) operations for insertion, searching, and traversal. The BST property ensures that in-order traversal always returns values in sorted order, making it ideal for maintaining ordered data.

Updated on: 2026-03-15T23:18:59+05:30

497 Views

Kickstart Your Career

Get certified by completing the course

Get Started
Advertisements