Optimization for Binary Search Tree 'remove' function - javascript

I just finished my first binary search tree remove function and it is in major need of optimization. I have spent a lot of time on this and this was the best I could manage. Is there a easier way to do this? Does anyone have any suggestions for optimization? To me, it just seems like it will necessarily be massive code.
For starters...
My Binary Search Tree...
function BST() {
this.root = null;
}
My 'remove' function...
BST.prototype.remove = function(data) {
if(this.root.data === data){
var curr = this.root.left;
while(true){
if(curr.right.left === null && curr.right.right === null){
this.root.data = curr.right.data;
curr.right = null;
break;
}
curr = curr.right;
}
}
var curr = this.root;
var found_data = this.find(data);
if(found_data.left !== null && found_data.right !== null){
var runner = found_data.right;
var runner_prev = found_data;
while(true){
if(runner.left === null && runner.right === null){
found_data.data = runner.data;
if(runner_prev.left === runner){
runner_prev.left = null;
}else{
runner_prev.right = null;
}
break;
}
runner_prev = runner;
runner = runner.left;
}
}else if(found_data.left === null || found_data.right === null){
var prev = this.prev(found_data.data);
if(prev.right === found_data){
if(found_data.left){
prev.right = found_data.left;
}else{
prev.right = found_data.right;
}
}else{
if(found_data.left){
prev.left = found_data.left;
}else{
prev.left = found_data.right;
}
}
}else{
var prev = this.prev(found_data.data);
if(prev.left === found_data){
prev.left = null;
}else{
prev.right = null;
}
}
};
You will notice that I use supporting functions within my remove() function, such as prev() and find() They are apart of my overarching BST() function and can be used anywhere within is by prefacing it using this..
Supporting functions I use within remove() (prev() and find())
BST.prototype.find = function(data) {
if(this.root === null){
return 'wrong';
}
var curr = this.root;
while(true){
if(data > curr.data){
curr = curr.right;
}else if(data < curr.data){
curr = curr.left;
}else{
if(curr.data enter code here=== data){
return curr;
}else{
return 'not here player'
}
}
}
}
BST.prototype.prev = function(data){
if(this.root === null){
return false;
}
var prev = this.root;
var curr = this.root;
while(true){
if(curr.left === null && curr.right === null){
return prev;
}
if(data < curr.data){
prev = curr;
curr = curr.left;
}else if(data > curr.data){
prev = curr;
curr = curr.right;
}else{
return prev;
}
}
}
This algorithm absolutely works, but as you can imagine, this is not the type of monster you would want to be answering a whiteboard interview question with.

It would be more efficient if you either:
Combine prev() and find() by returning both the previous node and the found node from find()
Give each node a parent pointer, and just follow it to find prev

Related

Remove() function doesn't remove the element from BST

I'm trying to add a remove method to my BST But I just can't figure out what is wrong. I have defined the pointer variable using let but it's still not working. It seems like it doesn't update the root object.
const Node = (data, left = null, right = null) => {
return {data, left, right};
};
const Tree = array => {
const remDupsAndSort = array => {
const mergeSort = array => {
if(array.length <= 1) return array;
let leftArr = array.slice(0, array.length / 2);
let rightArr = array.slice(array.length / 2);
return merge(mergeSort(rightArr), mergeSort(leftArr))
};
const merge = (leftArr, rightArr) => {
let sorted = [];
while(leftArr.length && rightArr.length){
if(leftArr[0] < rightArr[0]){
sorted.push(leftArr.shift());
}else{
sorted.push(rightArr.shift());
}
};
return [...sorted, ...leftArr, ...rightArr]
};
return mergeSort([... new Set(array)])
};
array = remDupsAndSort(array);
const buildTree = (array, start, end) => {
if(start > end) return null;
let mid = Math.floor((start + end) / 2);
let node = Node(array[mid]);
node.left = buildTree(array, start, mid - 1);
node.right = buildTree(array, mid + 1, end);
return node;
};
const remove = value => {
if(!root) return root;
let pointer = root;
while(pointer){
if(value < pointer.data){
pointer = pointer.left
}
else if(value > pointer.data){
pointer = pointer.right;
}else{
if(!pointer.right && !pointer.left){
return null;
}
if(!pointer.left){
return pointer.right;
}else if(!pointer.right){
return pointer.left;
}else{
let nextBiggest = pointer.right;
while(nextBiggest.left){
nextBiggest = nextBiggest.left;
}
return pointer = nextBiggest;
}
}
}
};
let root = buildTree(array, 0, array.length - 1);
return {root, remove}
};
When I run the code it doesn't remove anything from the tree. What am I missing?
let pointer = root; will assign the value of root to the pointer variable. Changing the value of pointer will not change the value of the original variable though. The variable is an object, and changing the key values within that object will cause the original to change.
So you either need to set the value of each key individually (which won't work really in this case because you want to set the whole value to be null sometimes), or you can track the parent value as you traverse through the tree so that you can modify parent.left and parent.right (or go a completely different route make a recursive removal function)
Thanks to #abney317 the problem was solved by tracking the parent nodes. Although I'm not happiest with this code and it's not the most good looking code I've done, but I'm sharing it here just in case some one needed it.
const remove = value => {
if(!root) return root;
let pointer = root;
let parent = null;
while(pointer){
if(value < pointer.data){
parent = pointer;
pointer = pointer.left
}
else if(value > pointer.data){
parent = pointer;
pointer = pointer.right;
}else{
if(!pointer.right && !pointer.left){
if(pointer === parent.left) return parent.left = null;
if(pointer === parent.right) return parent.right = null;
}
if(!pointer.left){
if(pointer === parent.left) return parent.left = pointer.right
if(pointer === parent.right) return parent.right = pointer.right
}else if(!pointer.right){
if(pointer === parent.left) return parent.left = pointer.left
if(pointer === parent.right) return parent.right = pointer.left
}else{
let replacingNode = pointer.right;
let replacingParent = pointer;
while(replacingNode.left){
replacingParent = replacingNode;
replacingNode = replacingNode.left;
}
if(pointer === root){
replacingNode.right = root.right;
replacingNode.left = root.left;
root = replacingNode;
if(replacingNode === replacingParent.left) return replacingParent.left = null;
if(replacingNode === replacingParent.right) return replacingParent.right = null;
}
if(pointer === parent.left){
if(replacingNode === pointer.left){
replacingNode.left = null;
}else{
replacingNode.left = pointer.left;
}
if(replacingNode === pointer.right){
replacingNode.right = null;
}else{
replacingNode.right = pointer.right;
}
parent.left = replacingNode;
if(replacingNode === replacingParent.left) return replacingParent.left = null;
if(replacingNode === replacingParent.right) return replacingParent.right = null;
}
if(pointer === parent.right){
if(replacingNode === pointer.left){
replacingNode.left = null;
}else{
replacingNode.left = pointer.left;
}
if(replacingNode === pointer.right){
replacingNode.right = null;
}else{
replacingNode.right = pointer.right;
}
parent.right = replacingNode;
if(replacingNode === replacingParent.left) return replacingParent.left = null;
if(replacingNode === replacingParent.right) return replacingParent.right = null;
}
}
}
}
};

Leetcode Same Tree Iterative Solution

Question at hand: https://leetcode.com/problems/same-tree/
Can someone point out why my JavaScript solution can pass the test cases but fails during the actual submission?
var isSameTree = function(p, q) {
let queue = [];
queue.push(p);
queue.push(q);
while (!queue.length) {
let p = queue.shift();
let q = queue.shift();
if (p == null && q == null) {
continue;
} else if (p == null || q == null || p.val != q.val) {
return false;
} else {
queue.push(p.left);
queue.push(q.left);
queue.push(p.right);
queue.push(q.right);
}
}
return true;
};
#trincot mentioned it in the comments.
Just update the comparison inside the while loop to get into that loop.
var isSameTree = function(p, q) {
let queue = [];
queue.push(p);
queue.push(q);
while (queue.length != 0) {
let p = queue.shift();
let q = queue.shift();
if (p == null && q == null) {
continue;
} else if (p == null || q == null || p.val != q.val) {
return false;
} else {
queue.push(p.left);
queue.push(q.left);
queue.push(p.right);
queue.push(q.right);
}
}
console.log(queue);
return true;
};
This will pass all the test cases.

Why am I getting an infinite loop while trying to search my Binary Tree?

I inserted numbers into the tree. I use get to see if that number exists(knowing it does) and google chrome crashes because its looping infinitely. I've gone over the code multiple times and I can't figure out why its not working. Please help.
My commands in console:
tree = new BinaryTree;
tree.insert(15);
tree.insert(23);
tree.insert(6);
etc...
tree.get(55);
Google Chrome CRASHES NOOOOOO collapses
class Node {
constructor(val){
this.val = val;
this.left = null;
this.right = null;
}
}
class BinaryTree {
constructor(){
this.root = null;
}
insert(val){
var newNode = new Node(val);
if (this.root){
var current = this.root
while(true) {
if(val < current.val){
if(current.left === null){
current.left = newNode;
return current;
}
current = current.left;
}
if(val > current.val){
if(current.right === null){
current.right = newNode;
return current;
}
current = current.right;
}
if(val === current.val){
return "already exists";
}
}
}
this.root = newNode;
return this;
}
get(val) {
if(this.root){
var current = this.root;
while(true){
if (val < current.val){
if(current.left == null){
return "does not exist";
}
current = current.left;
}
if (val > current.val){
if(current.right == null){
return "does not exist";
}
current = current.right;
}
if(current === val){
return current;
}
}
}
return "tree is empty";
}
}
Your code is fine, you are simple doing the equality check wrong at the bottom of the get() method. You are checking the node object itself for equality to the passed in value instead of it's .val property.
You wrote:
if(current === val){
return current;
}
When it needs to be:
if(current.val === val){
return current;
}
Your code never breaks out of this while loop
while(true) {
if(val < current.val){
if(current.left === null){
current.left = newNode;
return current;
}
current = current.left;
}
}
white(true) will always be true, so that runs infinitely if you don't return out of the loop, so my guess is that for some reason
current.left === null
is never true

I'm trying to implement delete method of BST but i cant figure out the problem

After calling the delete() against an integer value in my Binary Search Tree, the number still not removed from the bst and no error is given and can't figure out the problem thanks in advance
delete(data) {
function removeNode(node, data) {
if (node === null) {
return node;
}
if (data === node.data) {
if (node.right === null && node.left === null) {
node = null;
return node;
} else if (node.right === null) {
node = node.left;
return node
} else if (node.left === null) {
node = node.right;
return node
} else {
// node with two leaves
var tempNode = node.right;
while (tempNode.left !== null) {
tempNode = tempNode.left;
}
node.data = tempNode.data;
tempNode = null;
}
} else if (data < node.data) {
node.left = removeNode(node, data);
return node;
} else if (data > node.data) {
removeNode(node.right, data);
return node;
}
}
this.root = removeNode(this.root, data);
}
}
const mybst = new BST();
mybst.add(20);
mybst.add(25);
console.log(mybst.findMax());
console.log(mybst.findMin());
mybst.delete(25);
console.log(mybst.findMax());
//I expected 25 to be removed in this case but i still have 25 when log mybst.findMax(). Thanx in advance.

Faster Evaluating IF Condition of JavaScript

Back to the basics of JavaScript. This is a question I am coming with is based on computation time speed of JavaScript If condition.
I have a logic which includes usage of if condition. The question is computing equal to value is faster OR not equal to value is faster?
if(vm.currentFeedbackObject.sendReminderLists[0].sendReminderFlag !== '' && vm.currentFeedbackObject.sendReminderLists[0].sendReminderedOn !== null)
{
vm.isReminderSectionVisible = true;
} else
{
vm.isReminderSectionVisible = false;
}
The above one computes not equal to
if(vm.currentFeedbackObject.sendReminderLists[0].sendReminderFlag === '' && vm.currentFeedbackObject.sendReminderLists[0].sendReminderedOn === null)
{
vm.isReminderSectionVisible = false;
} else
{
vm.isReminderSectionVisible = true;
}
The above one computes equal to value
which of both these is faster in execution?
Why don't you try it out? Write to your console this:
function notequal() {
if(vm.currentFeedbackObject.sendReminderLists[0].sendReminderFlag !== '' && vm.currentFeedbackObject.sendReminderLists[0].sendReminderedOn !== null)
vm.isReminderSectionVisible = true;
}
else {
vm.isReminderSectionVisible = false;
}
}
function yesequal() {
if(vm.currentFeedbackObject.sendReminderLists[0].sendReminderFlag === '' && vm.currentFeedbackObject.sendReminderLists[0].sendReminderedOn === null)
vm.isReminderSectionVisible = false;
}
else {
vm.isReminderSectionVisible = true;
}
}
var iterations = 1000000;
console.time('Notequal #1');
for(var i = 0; i < iterations; i++ ){
notequal();
};
console.timeEnd('Notequal #1')
console.time('Yesequal #2');
for(var i = 0; i < iterations; i++ ){
yesequal();
};
console.timeEnd('Yesequal #2')

Categories

Resources