Creating an iterative function to add nodes to a Binary Search Tree in JavaScript

Having trouble getting my add/insert method for a BST in JS to work properly. Check out my code below:

function Node(value) {
    this.value = value;
    this.left = null;
    this.right = null;
}


function BinarySearchTree() {
    this.root = null;

    this.add = function(insertElem){
        let currNode = this.root;

        var recurInsert = function(elem, node){
            if(node == null){
                let newNode = new Node(elem);
                node = newNode;
                console.log("firstNode");
                return undefined;
            }
            else if(elem == node.value){
                console.log("equal val");
                return null
            }
            else if(elem > node.value){
                console.log("go right");
                recurInsert(elem, node.right);
            }
            else{
                console.log("go left");
                recurInsert(elem, node.left);
            }
        }

        recurInsert(insertElem, currNode);
    }
}

Having an issue with node = newNode not setting node correctly to newNode. Possible pass-by-value problem in JavaScript?

Can someone help me find the mistake?

Prefer to keep it recursive for now.

Answer №1

Essentially, in order to avoid creating new nodes without linking them to the root node, you must pass the object reference to the recursive function.

This particular code handles an object with a key representing direction and checks the four different decisions that need to be made. If a new node needs to be assigned, both the object and the key are utilized.

If the value is less than or greater than the current node's value, the node along with the new direction is used for further evaluation.

function Node(value) {
    this.value = value;
    this.left = null;
    this.right = null;
}

function BinarySearchTree() {
    this.root = null;
    this.add = function (value) {

        function check(node, direction) {
            if (node[direction] === null) {
                node[direction] = new Node(value);
                console.log('new node', value);
                return;
            }
            if (node[direction].value === value) {
                console.log('equal value', value);
                return;
            }
            if (node[direction].value > value) {
                console.log('go left', node[direction].value);
                check(node[direction], 'left');
                return;
            }
            if (node[direction].value < value) {
                console.log('go right', node[direction].value);
                check(node[direction], 'right');
            }
        }

        check(this, 'root');
    };
}

var tree = new BinarySearchTree;

tree.add(10);
tree.add(5);
tree.add(15);
tree.add(2);
tree.add(4);
tree.add(11);

console.log(tree);
.as-console-wrapper { max-height: 100% !important; top: 0; }

An alternative, more concise approach involves utilizing a default node.

function Node(value) {
    this.value = value;
    this.left = null;
    this.right = null;
}

function BinarySearchTree() {
    this.root = null;
    this.add = function (value) {

        function check(node) {
            if (node.value === value) {
                return;
            }
            if (node.value > value) {
                check(node.left = node.left || new Node(value));
                return;
            }
            if (node.value < value) {
                check(node.right = node.right || new Node(value));
            }
        }

        check(this.root = this.root || new Node(value));
    };
}

var tree = new BinarySearchTree;

tree.add(10);
tree.add(5);
tree.add(15);
tree.add(2);
tree.add(4);
tree.add(11);

console.log(tree);
.as-console-wrapper { max-height: 100% !important; top: 0; }

A brief example illustrating the difference between changing objects vs properties

function assign(o) {      // take object reference as value of o
    o = { bar: 43 };      // assign a new value to o, object keeps it value
    console.log('o', o);  // the reference to object is replaced by an own object
}

function change(o) {      // take object reference as value of o
    o.bar = 41;           // take object reference and assign a new property
    console.log('o', o);  // because of the object reference, o and object has changed
}

var object = { foo: 42 };
console.log('object', object);

assign(object);
console.log('object', object);

change(object);
console.log('object', object);
.as-console-wrapper { max-height: 100% !important; top: 0; }

Answer №2

The issue lies in the necessity to assign the newNode to node.right or node.left, rather than simply setting node = newNode. This results in a failure to establish references and ultimately leads to the root node lacking any children.

Therefore, it is crucial that insertions are made at the point where right.next or left.next is null, rather than waiting for the next recursion.

      else if(elem > node.value){
            console.log("go right");
            if (node.right == null) 
                 node.right = new Node(elem);
            else 
                recurInsert(elem, node.right);
        }
        else{
            console.log("go left");
            if (node.left == null)
                node.left = new Node(elem);
            else 
                recurInsert(elem, node.left);
        }

In addition, the entire if (node == null) { ... } section can be eliminated by checking if the root is null just once before commencing.

if (root == null) {
   root = new Node(insertElem);
   return null;
}

Below is the complete code snippet:

    function Node(value) {
        this.value = value;
        this.right = null;
        this.left = null;
}

function BinarySearchTree() {
    this.root = null;

    this.add = function(value) {
        if (this.root == null) {
            this.root = new Node(value);
            return;
        } 
        var recInsert = function(value, node) {
            if (value == node.value) {
                print("equal");
                return;
            }
            if (value < node.value) {
                if (node.left == null) 
                    node.left = new Node(value);   
                else 
                    recInsert(value, node.left);
            }
            else {
                if (node.right == null) 
                    node.right = new Node(value);   
                else 
                    recInsert(value, node.right);
            }
        }
        recInsert(value, this.root);
    } 

    this.print = function() {
        if (this.root != null) {
           var rec = function(node) {
               if (node == null) 
                   return;
               rec(node.left);
               print(node.value);
               rec(node.right);
           }
           rec(this.root);
        }   
    }
}

Similar questions

If you have not found the answer to your question or you are interested in this topic, then look at other similar questions below or use the search

Retrieving a designated set of attributes for elements chosen using an element selector

Is there a way to retrieve specific attributes for the first 10 <p> elements in a document using jQuery? I know I can easily get the first 10 elements with $('p').slice(0,10), but I only need certain attributes like innerText for each eleme ...

The word-break CSS property is ineffective in this situation

I've been experimenting with the word-break css property, but I just can't seem to get it to work even when using a simple example. Here's my code: React: render() { return ( <h5 className="word-break">A very very long line.... ...

Sharing variables between different routes in ExpressJS

Currently, I am utilizing ExpressJs with Node.js and have organized all my routes in a 'routes' folder. When setting up the server, my process involves establishing a DB connection followed by defining the routes as shown below: var routes = re ...

The function is not able to fetch the value from the Amazon S3 file, however, it is printed

Despite troubleshooting methods such as declaring the variable outside the function and attempting to return it from the function, the below code is still not returning the Amazon S3 content. It seems to work when logging the data value on the console. ...

Tips on utilizing AngularJS $http for transferring multipart/form-data

In the process of creating a visual interface that interfaces with various REST services (coded in Java), I am encountering an issue when attempting to call one such service: @PUT @Path("serviceName") public Response serviceName(final FormDataMultiPart mu ...

Transform ajax functionality into jquery

I need help converting an AJAX function to a jQuery function, but I'm not sure how to do it. function convertToJquery() { // Create our XMLHttpRequest object var hr = new XMLHttpRequest(); // Set up variables needed to send to PHP file var ur ...

Retrieving the positions of a mesh as it looks towards an object in three.js

My scenario involves having a scene, multiple meshes, and a target object. After setting up the scene, I use the code snippet below to make a mesh (referred to as mesh) face the target object: mesh.lookAt(object) This action successfully aligns the me ...

Comparison Between Angular 4 `ng serve --prod` and `ng serve` Commands

So, here's the situation: I have an app that is 4.6MB when running on ng serve. When I run: ng serve --prod The file size drops to 1MB. However, when I use --prod, my entire application breaks. All of my services (which are promise-based) that ...

Can a string starting with certain values be omitted?

How can I determine if a value begins with any of the values in an array? var value = "background-color"; var value2 = "--my-variable"; var excludeItems = ["--", "-", "_"]; if (checkForStartsWith(value, excludeItems)) { // Exclude the value } ...

Utilizing React hook form to submit arrays with the help of React server actions

When attempting to submit an array for a field named services using react-hook-form, it is returning as a separate value upon submission. The data structure returned looks like this: { customerId: '', title: '', message: '', s ...

Receiving blank response from jQuery POST request

Lately, I've been facing a major issue that I can't seem to solve. The challenge lies in posting raw XML data to a server developed by another company, which should have a listener to receive this input. While I am able to post and send the infor ...

What causes my Excel file to become corrupted when inputting new data?

My intention with this code is to insert "ABC" into cell B3 of an existing Excel document. However, when the file is written, its size decreases significantly and Excel is unable to open it. const excel = require("exceljs"); const template = "./myexcel.xl ...

JavaScript is incorrectly showing the array as empty despite containing strings

I am experiencing an issue with my array of strings in JavaScript. Despite having strings in the array when I print it in the console, the forEach function runs 0 times and JS claims the array is empty when I print its size. What could be causing this?http ...

Is there a way to sequentially execute requests in a loop?

My goal is to extract a list of URLs from the request body, pass them to a request function (using the request module) to retrieve data from each URL, and then save that data to MongoDB. The response should be sent only after all requests are completed, in ...

Resolving the issue of nested modals within Bootstrap

I am experiencing some issues with my customer visits list page. When I try to add a visit, it opens a bootstrap popup ("#Pop1") to record the visit details. Within this modal, there is an option to add a new customer on the spot, which then triggers anoth ...

In Snowflake, SQL error handling block fails to execute

Implementing error handling in Snowflake using a Try Catch block has been my focus. I've enclosed SQL queries within JavaScript for this purpose. However, upon executing the query, I noticed that it skips the Try Catch block and directly executes the ...

Why do I need to double-click? (JavaScript onclick event handler)

As a beginner in JavaScript and web development, I encountered a peculiar issue for the first time. In a simple example, I have two divs - left and right. The left div contains five images, while the right div is empty. There are two buttons - copy and del ...

jQuery - selecting child elements with a strict hierachy restrictions

Can you provide the equivalent jQuery selector if I have a variable $table that references $('table.special') to start with? (something like $table.(...) but matching the original selector $('table.special > thead > tr')) Note: ...

Combining arrays within an array using the concat method in JavaScript instead of the push method

I am facing a challenge that requires me to merge arrays of an array and produce a single array with the format [ array[0][0], array[0][1], array[1][0], array[1][1], etc. ]. To solve this, I utilized the `push` method within nested for-loops. However, the ...

Perform an operation in JQuery after a different operation has been completed

Recently, I came across this JavaScript function that displays a loading image for a few seconds before revealing a hidden div: <script type="text/javascript> $(document).ready(function () { $('#load').html('<img style="display ...