2

I'm creating a program to represent a binary search tree in javascript. What I want is a way to create a common tree node with both ptrs(left, right) as null. This is the code i wrote:

var BST = function(data) {
    if (data === null || data === undefined){
        this.data  = null;
        this.left  = null;
        this.right = null;
    }

    else{
        this.data  = data;
        this.left  = new BST(null);
        this.right = new BST(null);
    }
};

BST.prototype.insert = function(data) {
    if (this.data === null){
        this.data  = data;
        this.left  = new BST(null);
        this.right = new BST(null);
    }
    else if (data < this.data)
        this.left.insert(data);
    else if (data > this.data)
        this.right.insert(data);
};

BST.prototype.inOrder = function(func) {
    if (this.data !== null) {
        this.left.inOrder(func);
        func(this.data);
        this.right.inOrder(func);
    }
};

Here, i want to assign all null pointers with a null node(as defined in the if(data === null || data === undefined) condition). But for every null node I'm having to create a new node representing the same data. Is there a way to assign to a common instance of the null node?
The reason i use a null node instead of just using

else{
    this.data = data;
    this.left = null;
    this.right = null;
}

is that on calling the inOrder method, on reaching a node with left or right = null, it gives a TypeError because it tries to run null.inOrder(func); since, this.left translates to null.
The way around that is to modify the inOrder function, which will lead to many conditions around each statement, i.e. not a very elegant implementation.
I could also define inOrder outside the prototype of the object, and make it take a tree as an argument i.e. inOder(tree,func), but I don't want to do that.

Also, as a second improvement to the code, consider the insert method; in the null case:

if (this.data === null){
    this.data  = data;
    this.left  = new BST(null);
    this.right = new BST(null);
}

since I have to override each entry anyway, I want to reassign this node to a new Tree altogether by doing something along the lines of:

if (this.data === null)
    this = new BST(data);

I am aware that this would be a less efficient implementation to the former, but it is still a lot more concise.So is there any way to do so?

Likhit
  • 799
  • 2
  • 6
  • 18

2 Answers2

1

Yes, in this case you can use a constant instance because all null-nodes are the same and don't have different references (like a "parent" property). To create such a constant you will need a place to store it; that can either be a (private) variable or something like

BST.emptyleaf = new BST(null);

And you could also use the singleton pattern:

function BST(data) {
    if (data === null || data === undefined) {
        if (BST.emptyleaf)
            return BST.emptyleaf; // singleton instance if available
        this.data  = null;
        this.left  = null;
        this.right = null;
        BST.emptyleaf = this; // else create it for re-use
    } else {
        this.data  = data;
        this.left  = new BST(null);
        this.right = new BST(null);
    }
}
Bergi
  • 630,263
  • 148
  • 957
  • 1,375
1

But for every null node I'm having to create a new node representing the same data. Is there a way to assign to a common instance of the null node?

Yes, but this would break your code. Think about it: what happens when you call the insert method on that node instance? ...

As for the second problem, you cannot optimize that with your current model. There is no such thing as in-place object replacement (there is in C#).

I think your current code is ok, though I'd personally stick with a simpler model, something like

var BST = function(data) {
    this.insert(data);
};

BST.prototype.insert = function(data) {
    if (typeof this.data == 'undefined') {
        this.data = data;
    } else if (data < this.data) {
        if (!this.left) {
            this.left = new BST();
        }
        this.left.insert(data);
    } else if (data > this.data) {
        if (!this.right) {
            this.right = new BST();
        }
        this.right.insert(data);
    }
};

BST.prototype.inOrder = function(func) {
    if (typeof this.data != 'undefined') {
        this.left && this.left.inOrder(func);
        func(this.data);
        this.right && this.right.inOrder(func);
    }
};

Note that this completely eliminates the need for a nullNode, since - hey! - it's JavaScript, so why not use such wonderful things as undefined and dynamic object extension.

Community
  • 1
  • 1
user123444555621
  • 148,182
  • 27
  • 114
  • 126