Thursday, December 26, 2024
Google search engine
HomeData Modelling & AIImplementation of Binary Search Tree in Javascript

Implementation of Binary Search Tree in Javascript

In this article, we would be implementing the Binary Search Tree data structure in Javascript. A tree is a collection of nodes connected by some edges. A tree is a non linear data structure. A Binary Search tree is a binary tree in which nodes that have lesser value are stored on the left while the nodes with a higher value are stored at the right.

Now let’s see an example of a Binary Search Tree node:

Javascript




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


As in the above code snippet we define a node class having three property data, left and right, Left and right are pointers to the left and right node in a Binary Search Tree. Data is initialized with data which is passed when object for this node is created and left and right is set to null.

Now let’s see an example of a Binary Search Tree class. 

Javascript




// Binary Search tree class
class BinarySearchTree
{
    constructor()
    {
        // root of a binary search tree
        this.root = null;
    }
 
    // function to be implemented
    // insert(data)
    // remove(data)
                 
 
    // Helper function
    // findMinNode()
    // getRootNode()
    // inorder(node)
    // preorder(node)              
    // postorder(node)
    // search(node, data)
}


The above example shows a framework of a Binary Search tree class, which contains a private variable root which holds the root of a tree, it is initialized to null. 

Now lets implement each of this function: 

1. insert(data) – It inserts a new node in a tree with a value data

Javascript




// helper method which creates a new node to
// be inserted and calls insertNode
insert(data)
{
    // Creating a node and initialising
    // with data
    var newNode = new Node(data);
                     
    // root is null then node will
    // be added to the tree and made root.
    if(this.root === null)
        this.root = newNode;
    else
 
        // find the correct position in the
        // tree and add the node
        this.insertNode(this.root, newNode);
}
 
// Method to insert a node in a tree
// it moves over the tree to find the location
// to insert a node with a given data
insertNode(node, newNode)
{
    // if the data is less than the node
    // data move left of the tree
    if(newNode.data < node.data)
    {
        // if left is null insert node here
        if(node.left === null)
            node.left = newNode;
        else
 
            // if left is not null recur until
            // null is found
            this.insertNode(node.left, newNode);
    }
 
    // if the data is more than the node
    // data move right of the tree
    else
    {
        // if right is null insert node here
        if(node.right === null)
            node.right = newNode;
        else
 
            // if right is not null recur until
            // null is found
            this.insertNode(node.right,newNode);
    }
}


In the above code we have two methods insert(data) and insertNode(node, newNode). Let’s understand them one by one:- 

  • insert(data) – It creates a new node with a value data, if the tree is empty it add this node to a tree and make it a root, otherwise it calls insert(node, data).
  • insert(node, data) – It compares the given data with the data of the current node and moves left or right accordingly and recur until it finds a correct node with a null value where new node can be added.

2.remove(data) – This function removes a node with a given data.

Javascript




// helper method that calls the
// removeNode with a given data
remove(data)
{
    // root is re-initialized with
    // root of a modified tree.
    this.root = this.removeNode(this.root, data);
}
 
// Method to remove node with a
// given data
// it recur over the tree to find the
// data and removes it
removeNode(node, key)
{
         
    // if the root is null then tree is
    // empty
    if(node === null)
        return null;
 
    // if data to be delete is less than
    // roots data then move to left subtree
    else if(key < node.data)
    {
        node.left = this.removeNode(node.left, key);
        return node;
    }
 
    // if data to be delete is greater than
    // roots data then move to right subtree
    else if(key > node.data)
    {
        node.right = this.removeNode(node.right, key);
        return node;
    }
 
    // if data is similar to the root's data
    // then delete this node
    else
    {
         // deleting node with no children
        if(node.left === null && node.right === null)
        {
            node = null;
            return node;
        }
 
        // deleting node with one children
        if(node.left === null)
        {
            node = node.right;
            return node;
        }
         
        else if(node.right === null)
        {
            node = node.left;
            return node;
        }
 
        // Deleting node with two children
        // minimum node of the right subtree
        // is stored in aux
        var aux = this.findMinNode(node.right);
        node.data = aux.data;
 
        node.right = this.removeNode(node.right, aux.data);
        return node;
    }
 
}


In the above code we have two methods remove(data) and removeNode(node, data), let understand them one by one: 

  • remove(data) – It is helper methods which call removeNode by passing root node and given data and updates the root of the tree with the value returned by the function
  • removeNode(node, data) – It searches for a node with a given data and then perform certain steps to delete it.
  • Deleting the leaf node – As leaf node does not have any children, hence they can be easily removed and null is returned to the parent node
  • Deleting a node with one child – If a node has a left child, then we update the pointer of the parent node to the left child of the node to be deleted and similarly, if a node have a right child then we update the pointer of the parent node to the right child of the node to be deleted
  • Deleting a node with two children – In order to delete a node with two children we find the node with minimum value in its right subtree and replace this node with the minimum valued node and remove the minimum valued node from the tree

Tree Traversal

Now Lets understand different ways of traversing a Binary Search Tree. 

inorder(node) – It performs inorder traversal of a tree starting from a given node 
Algorithm for inorder:  

Traverse the left subtree i.e perform inorder on left subtreeVisit the rootTraverse the right subtree i.e perform inorder on right subtree

Javascript




// Performs inorder traversal of a tree
inorder(node)
{
    if(node !== null)
    {
        this.inorder(node.left);
        console.log(node.data);
        this.inorder(node.right);
    }
}


1. preorder(node) – It performs preorder traversal of a tree starting from a given node

Algorithm for preorder: 

Visit the rootTraverse the left subtree i.e perform preorder on left subtreeTraverse the right subtree i.e perform preorder on right subtree

Javascript




// Performs preorder traversal of a tree   
preorder(node)
{
    if(node !== null)
    {
        console.log(node.data);
        this.preorder(node.left);
        this.preorder(node.right);
    }
}


2. postorder(node) – It performs postorder traversal of a tree starting from a given node

Algorithm for postorder: 

Traverse the left subtree i.e perform postorder on left subtreeTraverse the right subtree i.e perform postorder on right subtreeVisit the root

Javascript




// Performs postorder traversal of a tree
postorder(node)
{
    if(node !== null)
    {
        this.postorder(node.left);
        this.postorder(node.right);
        console.log(node.data);
    }
}


Helper Methods
Let’s declare some helper method which is useful while working with Binary Search Tree. 

1. findMinNode(node) – It searches for a node with a minimum value starting from node.

Javascript




//  finds the minimum node in tree
// searching starts from given node
findMinNode(node)
{
    // if left of a node is null
    // then it must be minimum node
    if(node.left === null)
        return node;
    else
        return this.findMinNode(node.left);
}


As seen in the above method we start from a node and keep moving to the left subtree until we find a node whose left child is null, once we find such node we return it.

2. getRootNode() – It returns the root node of a tree.

Javascript




// returns root of the tree
getRootNode()
{
    return this.root;
}


3. search(data) – It searches the node with a value data in the entire tree.

Javascript




// search for a node with given data
search(node, data)
{
   // if trees is empty return null
    if(node === null)
        return null;
 
    // if data is less than node's data
    // move left
    else if(data < node.data)
        return this.search(node.left, data);
 
    // if data is more than node's data
    // move right
    else if(data > node.data)
        return this.search(node.right, data);
 
    // if data is equal to the node data
    // return node
    else
        return node;
}


Note : Different helper method can be declared in the BinarySearchTree class as per the requirement. 

Implementation:
Now lets use the BinarySearchTree class and its different methods described above.

Javascript




// create an object for the BinarySearchTree
var BST = new BinarySearchTree();
 
// Inserting nodes to the BinarySearchTree
BST.insert(15);
BST.insert(25);
BST.insert(10);
BST.insert(7);
BST.insert(22);
BST.insert(17);
BST.insert(13);
BST.insert(5);
BST.insert(9);
BST.insert(27);
                         
//          15
//         /  \
//        10   25
//       / \   / \
//      7  13 22  27
//     / \    /
//    5   9  17
 
var root = BST.getRootNode();
             
// prints 5 7 9 10 13 15 17 22 25 27
BST.inorder(root);
             
// Removing node with no children
BST.remove(5);
             
             
//          15
//         /  \
//        10   25
//       / \   / \
//      7  13 22  27
//       \    /
//        9  17
             
                         
var root = BST.getRootNode();
             
// prints 7 9 10 13 15 17 22 25 27
BST.inorder(root);
             
// Removing node with one child
BST.remove(7);
             
//          15
//         /  \
//        10   25
//       / \   / \
//      9  13 22  27
//            /
//           17
             
             
var root = BST.getRootNode();
 
// prints 9 10 13 15 17 22 25 27
BST.inorder(root);
             
// Removing node with two children
BST.remove(15);
     
//          17
//         /  \
//        10   25
//       / \   / \
//      9  13 22  27
 
var root = BST.getRootNode();
console.log("inorder traversal");
 
// prints 9 10 13 17 22 25 27
BST.inorder(root);
             
console.log("postorder traversal");
BST.postorder(root);
console.log("preorder traversal");
BST.preorder(root);


For more on binary trees, please refer to the following article: Binary tree Data Structure

This article is contributed by Sumit Ghosh. If you like neveropen and would like to contribute, you can also write an article using write.geeksforgeeks.org or mail your article to review-team@geeksforgeeks.org. See your article appearing on the neveropen main page and help other Geeks.

Feeling lost in the world of random DSA topics, wasting time without progress? It’s time for a change! Join our DSA course, where we’ll guide you on an exciting journey to master DSA efficiently and on schedule.
Ready to dive in? Explore our Free Demo Content and join our DSA course, trusted by over 100,000 neveropen!

Dominic Rubhabha-Wardslaus
Dominic Rubhabha-Wardslaushttp://wardslaus.com
infosec,malicious & dos attacks generator, boot rom exploit philanthropist , wild hacker , game developer,
RELATED ARTICLES

Most Popular

Recent Comments