Skip to content

Instantly share code, notes, and snippets.

@or9
Last active January 9, 2021 02:43
Show Gist options
  • Save or9/ecf7c55cf31d9b6ca6e2fc5d9ea7b744 to your computer and use it in GitHub Desktop.
Save or9/ecf7c55cf31d9b6ca6e2fc5d9ea7b744 to your computer and use it in GitHub Desktop.
Binary search tree stuff
class Node {
constructor (value) {
this.value = value;
this.left = null;
this.right = null;
}
}
class BinarySearchTree {
constructor () {
let root = undefined;
// Prevent directly modifying root property
Object.defineProperty(this, "root", {
enumerable: false,
configurable: false,
get () {
return root;
},
set (val) {
if (!root) {
root = val;
} else {
console.error(`Access error. Directly overwriting root is not allowed.`);
}
}
});
}
query (value) {
if (!this.root) return false;
let currentNode = this.root;
let found = false;
while (currentNode && !found) {
if (value < currentNode.value) {
currentNode = currentNode.left;
} else if (value > currentNode.value) {
currentNode = currentNode.right;
} else {
found = currentNode;
}
}
if (!found) return undefined;
else return found;
}
insert (value) {
// If we do this recursively, maybe we can leverage tail call optimization
// and in doing so, avoid increasing the stack while inserting into extremely large bst...?
let node = new Node(value);
if (!this.root) {
this.root = node;
// return the entire bst? or just the node...
return this.root;
}
let current = this.root;
while (current) {
if (value === current.value) return false;
if (value < current.value) {
if (current.left === null) {
current.left = node;
return current;
} else {
current = current.left;
}
} else {
if (current.right === null) {
current.right = node;
return current;
} else {
current = current.right;
}
}
}
}
}
class NonOverlappingRangesBinarySearchTree extends BinarySearchTree {
insert (min, max) {
// Insert range into bst...
}
query (value) {
// Return whether value exists between a min-max
// Maybe in this case it really just needs the value... no subclass required?
// if each `value` is represented as { min: int, max: int }, then it simply checks value.max - value > value.min... right? Maybe.
// What about negative numbers? -10 10... 10 - -10... in which case 15 would be between -10 and 10 and 5 would not. Not good.
// Probably just check if each number is < 0 then do something with them.
}
}
class Node {
constructor (value) {
this.value = value;
this.left = null;
this.right = null;
}
}
class BinarySearchTree {
constructor () {
let root = undefined;
// Prevent directly modifying root property
Object.defineProperty(this, "root", {
enumerable: false,
configurable: false,
get () {
return root;
},
set (val) {
if (!root) {
root = val;
} else {
console.error(`Access error. Directly overwriting root is not allowed.`);
}
}
});
}
query(value, node = {}) {
if (value === node?.value) return node;
if (noLeaves(node)) return undefined;
if (value < node.value) {
return this.query(value, node.left || null);
} else if (value > node.value) {
return this.query(value, node.right || null);
} else {
return undefined;
}
function noLeaves(node = {}) {
if (node.left === undefined && node.right === undefined || node.left === null && node.right === null) {
return true;
} else {
return false;
}
}
}
insert (value, current = this.root) {
// If we do this recursively, maybe we can leverage tail call optimization
// and in doing so, avoid increasing the stack while inserting into extremely large bst...?
let node = new Node(value);
if (!this.root) {
this.root = node;
// return the entire bst? or just the node...
return this.root;
}
if (value === current.value) return false;
if (value < current.value) {
if (current.left === null) {
current.left = node;
return current;
} else {
return this.insert(value, current.left);
}
} else {
if (current.right === null) {
current.right = node;
return current;
} else {
return this.insert(value, current.right);
}
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment