const root = Symbol("root"); class BinarySearchTreeNode { constructor (value) { this.value = value; this.left = null; this.right = null; } } class BinarySearchTree { constructor () { this[root] = null; } add (value) { const node = new BinarySearchTreeNode(value); let current = null; // No items in tree if (this[root] === null) { this[root] = node; } else { current = this[root]; while (true) { if (value < current.value) { // If there's no left, insert if (current.left === null) { current.left = node; break; } current = current.left; } else if (value > current.value) { if (current.right === null) { current.right = node; break; } current = current.right; } else { break; } } } } contains (value) { let found = false; let current = this[root]; while ( ! found && current !== null) { if (value < current.value) { current = current.left; } else if (value > current.value) { current = current.right; } else if (value === current.value) { found = true; } } return found; } remove (value) { } size () { let length = 0; this.traverse(() => { length++; }); return length; } traverse (process) { const inOrder = (node) => { if ( ! node) { return; } // traverse the left subtree if (node.left !== null) { inOrder(node.left); } // handle the current node process.call(this, node); // traverse the right subtree if (node.right !== null) { inOrder(node.right); } }; // start with the root inOrder(this[root]); } toArray () { let result = []; this.traverse((node) => { result.push(node.value); }); return result; } toString () { return this.toArray().toString(); } }