datastructure-ts
Version:
Collection of data structures(LinkedList, DoubleLinkedList, Stack, Queue, Dictionary and etc...) for TypeScript.
328 lines (269 loc) • 9.72 kB
text/typescript
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(', ');
}
}