简体   繁体   中英

Writing a recursive add method for a Javascript Binary Search Tree

I'm trying to write an add/insert method for a BST in JS, but can't seem to get it working for some reason. My code is here:

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);
    }
}

Specifically, the line node = newNode doesn't actually set node to newNode . I suspect that this could have something to do with pass-by-value nature of JavaScript, but I'm not completely sure.

Where did I go wrong?

Also, I'm hoping to keep this recursive form for now if possible.

The problem is that you need to set the node.right or node.left to the newNode and not node = newNode. Otherwise there is no linking of references and your root will never have any children.

So your insertions should actually be done here, if right.next or left.next is null, rather than on 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);
        }

You can also remove the whole if (node == null) { ... } section, and simply check if the root is null once before starting

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

Here is the full code:

    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);
        }   
    }
}

Basically you need to hand over the object reference to the recursive function, because if not, you create new nodes without linking to the root node.

This code takes an object and the direction as key and checkes the four different dicision to make. If a new node has to be assigned, the object and the key is used.

If a value is smaller or greater than the node's value, the node is used along with the new direction for checking.

 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 even shorter approach by using 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; } 

Small example of 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; } 

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM