UNPKG

typescript-ds-lib

Version:

A collection of TypeScript data structure implementations

227 lines 6.69 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.BinarySearchTree = void 0; const base_collection_1 = require("./base-collection"); class TreeNode { value; left; right; constructor(value) { this.value = value; this.left = null; this.right = null; } } class BinarySearchTree extends base_collection_1.BaseCollection { root; comparator; nodeCount; constructor(comparator = (a, b) => a < b) { super(); this.root = null; this.comparator = comparator; this.nodeCount = 0; } /** * Inserts a value into the BST if it doesn't already exist */ insert(value) { const newNode = new TreeNode(value); if (!this.root) { this.root = newNode; this.nodeCount++; return; } let current = this.root; while (true) { if (this.comparator(value, current.value)) { if (current.left === null) { current.left = newNode; this.nodeCount++; break; } current = current.left; } else if (this.isEqual(value, current.value)) { return; } else { if (current.right === null) { current.right = newNode; this.nodeCount++; break; } current = current.right; } } } /** * Searches for a value in the BST. Returns true if found, false otherwise */ find(value) { let current = this.root; while (current !== null) { if (this.isEqual(value, current.value)) { return true; } if (this.comparator(value, current.value)) { current = current.left; } else { current = current.right; } } return false; } /** * Returns the minimum value in the BST, or undefined if tree is empty */ min() { if (!this.root) return undefined; let current = this.root; while (current.left !== null) { current = current.left; } return current.value; } /** * Returns the maximum value in the BST, or undefined if tree is empty */ max() { if (!this.root) return undefined; let current = this.root; while (current.right !== null) { current = current.right; } return current.value; } /** * Removes a value from the BST if it exists */ remove(value) { this.root = this.removeNode(this.root, value); } removeNode(node, value) { if (node === null) return null; if (this.comparator(value, node.value)) { node.left = this.removeNode(node.left, value); return node; } else if (this.comparator(node.value, value)) { node.right = this.removeNode(node.right, value); return node; } else { // Node to delete found this.nodeCount--; // Case 1: Leaf node if (node.left === null && node.right === null) { return null; } // Case 2: Node with one child if (node.left === null) return node.right; if (node.right === null) return node.left; // Case 3: Node with two children const minNode = this.findMin(node.right); node.value = minNode.value; node.right = this.removeNode(node.right, minNode.value); this.nodeCount++; // Increment back since the recursive call decremented return node; } } findMin(node) { let current = node; while (current.left !== null) { current = current.left; } return current; } isEqual(a, b) { // Two values are equal if neither is less than the other return !this.comparator(a, b) && !this.comparator(b, a); } /** * Executes a callback function for each element in the BST in-order traversal */ forEach(callback, traversal = 'inorder') { switch (traversal) { case 'inorder': this.inorderTraversal(this.root, callback); break; case 'preorder': this.preorderTraversal(this.root, callback); break; case 'postorder': this.postorderTraversal(this.root, callback); break; default: this.inorderTraversal(this.root, callback); } } inorderTraversal(node, callback) { if (node === null) return; this.inorderTraversal(node.left, callback); callback(node.value); this.inorderTraversal(node.right, callback); } preorderTraversal(node, callback) { if (node === null) return; callback(node.value); this.preorderTraversal(node.left, callback); this.preorderTraversal(node.right, callback); } postorderTraversal(node, callback) { if (node === null) return; this.postorderTraversal(node.left, callback); this.postorderTraversal(node.right, callback); callback(node.value); } /** * Returns true if the BST is empty, false otherwise */ isEmpty() { return this.root === null; } /** * Removes all nodes from the BST */ clear() { this.root = null; this.nodeCount = 0; } /** * Returns the number of nodes in the BST. */ size() { return this.nodeCount; } /** * Checks if two BSTs are equal. */ equals(other) { if (!other || !(other instanceof BinarySearchTree)) return false; if (this.size() !== other.size()) return false; return this.areTreesEqual(this.root, other.root); } areTreesEqual(node1, node2) { if (node1 === null && node2 === null) return true; if (node1 === null || node2 === null) return false; return this.isEqual(node1.value, node2.value) && this.areTreesEqual(node1.left, node2.left) && this.areTreesEqual(node1.right, node2.right); } } exports.BinarySearchTree = BinarySearchTree; //# sourceMappingURL=binary-search-tree.js.map