UNPKG

datastructure-ts

Version:

Collection of data structures(LinkedList, DoubleLinkedList, Stack, Queue, Dictionary and etc...) for TypeScript.

328 lines (269 loc) 9.72 kB
import { BinaryTreeNode } from '../Nodes/BinaryTreeNode'; export class BinaryTree<T> { // ========================================================================================================================================================= // Public properties // ========================================================================================================================================================= // ========================================================================================================================================================= // Private properties // ========================================================================================================================================================= private _root: BinaryTreeNode<T>; // ========================================================================================================================================================= // Constructor // ========================================================================================================================================================= constructor() { this._root = new BinaryTreeNode<T>(null); } // ========================================================================================================================================================= // Public methods // ========================================================================================================================================================= /** * Returns 'root' node */ getRoot(): BinaryTreeNode<T> { return this._root; } /** * Returns node with a given value * @param value * @param node */ findNode(value: T, node: BinaryTreeNode<T> = null): BinaryTreeNode<T> { if (this._root === null) { return null; } if (node === null) { node = this.getRoot(); } let result: BinaryTreeNode<T> = null; if (node.getValue() === value) { result = node; } if (result === null && node.getLeft() !== null) { result = this.findNode(value, node.getLeft()); } if (result === null && node.getRight() !== null) { result = this.findNode(value, node.getRight()); } return result; } /** * Inserts new node to tree. * @param value */ insert(value: T): void { const newNode = new BinaryTreeNode<T>(value); if (!this._root || this._root.getValue() === null) { this._root = newNode; return; } let current = this._root; while (true) { if (value === current.getValue()) { return; } if (value < current.getValue()) { if (current.getLeft() === null) { current.setLeft(newNode); return; } current = current.getLeft(); } else { if (current.getRight() === null) { current.setRight(newNode); return; } current = current.getRight(); } } } /** * Deletes node from tree * @param node BinaryTreeNode **/ delete(node: T): void { const removeNode = (node: BinaryTreeNode<T>, value: T): BinaryTreeNode<T> => { if (!node) { return null; } if (value === node.getValue()) { if (!node.getLeft() && !node.getRight()) { return null; } if (!node.getLeft()) { return node.getRight(); } if (!node.getRight()) { return node.getLeft(); } const temp = this.getMinNode(node.getRight()); node.setValue(temp.getValue()); node.setRight(removeNode(node.getRight(), temp.getValue())); return node; } else if (value < node.getValue()) { node.setLeft(removeNode(node.getLeft(), value)); return node; } else { node.setRight(removeNode(node.getRight(), value)); return node; } }; this._root = removeNode(this._root, node); } /** * Returns in order traversal * @return BinaryTreeNode */ inOrderTraversal(): T[] { const result: T[] = []; const traverse = (node: BinaryTreeNode<T>): void => { if (node.getLeft() !== null && node.getLeft().getValue() !== null) { traverse(node.getLeft()); } result.push(node.getValue()); if (node.getRight() !== null && node.getRight().getValue() !== null) { traverse(node.getRight()); } }; if (this._root !== null && this._root.getValue() !== null) { traverse(this._root); } return result; } /** * Returns pre-order traversal of tree. * @return BinaryTreeNode */ preOrderTraversal(): T[] { const result: T[] = []; const traverse = (node: BinaryTreeNode<T>): void => { result.push(node.getValue()); if (node.getLeft() !== null && node.getLeft().getValue() !== null) { traverse(node.getLeft()); } if (node.getRight() !== null && node.getRight().getValue() !== null) { traverse(node.getRight()); } }; if (this._root !== null && this._root.getValue() !== null) { traverse(this._root); } return result; } /** * Returns post-order traversal of tree. * @return BinaryTreeNode */ postOrderTraversal(): T[] { const result: T[] = []; const traverse = (node: BinaryTreeNode<T>): void => { if (node.getLeft() !== null && node.getLeft().getValue() !== null) { traverse(node.getLeft()); } if (node.getRight() !== null && node.getRight().getValue() !== null) { traverse(node.getRight()); } result.push(node.getValue()); }; if (this._root !== null && this._root.getValue() !== null) { traverse(this._root); } return result; } /** * Returns level-order traversal of tree. * @return BinaryTreeNode */ levelOrderTraversal(): T[] { const result: T[] = []; const queue: BinaryTreeNode<T>[] = []; if (this._root !== null && this._root.getValue() !== null) { queue.push(this._root); } while (queue.length > 0) { const node = queue.shift(); result.push(node.getValue()); if (node.getLeft() !== null && node.getLeft().getValue() !== null) { queue.push(node.getLeft()); } if (node.getRight() !== null && node.getRight().getValue() !== null) { queue.push(node.getRight()); } } return result; } /** * Returns the height of the tree. * @return number */ getHeight(): number { const getHeightRec = (node: BinaryTreeNode<T>): number => { if (node === null || node.getValue() === null) { return 0; } const leftHeight = getHeightRec(node.getLeft()); const rightHeight = getHeightRec(node.getRight()); return Math.max(leftHeight, rightHeight) + 1; }; return getHeightRec(this._root); } /** * Returns the depth of the node. * @param node * @return number */ getDepth(node: BinaryTreeNode<T>): number { const getDepthRec = (node: BinaryTreeNode<T>, depth: number): number => { if (node === null) { return 0; } if (node === this._root) { return 1; } if (node === this._root.getLeft() || node === this._root.getRight()) { return 2; } const leftDepth = getDepthRec(node.getLeft(), depth + 1); const rightDepth = getDepthRec(node.getRight(), depth + 1); return leftDepth > rightDepth ? leftDepth : rightDepth; }; return getDepthRec(node, 1); } /** * Returns the min node in tree, if given node is null, returns min node in tree. * @param node * @return BinaryTreeNode */ getMinNode(node?: BinaryTreeNode<T>): BinaryTreeNode<T> { let current = !!node ? node : this._root; while (current.getLeft() !== null) { current = current.getLeft(); } return current; } /** * Returns the max node in tree, if given node is null, returns max node in tree. * @param node * @return BinaryTreeNode */ getMaxNode(node?: BinaryTreeNode<T>): BinaryTreeNode<T> { let current = !!node ? node : this._root; while (current.getRight() !== null) { current = current.getRight(); } return current; } /** * Returns an array of nodes in tree. * @return T[] */ toArray(): T[] { return this.inOrderTraversal(); } /** * Returns a string representation of the tree. * @return string */ toString(): string { return this.toArray().join(', '); } }