UNPKG

pisces-data-structure

Version:

373 lines (298 loc) 11.2 kB
/** * 红黑树 */ import { ERedBlackTreeNodeColor } from "../../../types"; class RedBlackTreeNode<T = any> { value: T; color: ERedBlackTreeNodeColor; parent: RedBlackTreeNode<T> | null; left: RedBlackTreeNode<T> | null; right: RedBlackTreeNode<T> | null; constructor( value: T, color: ERedBlackTreeNodeColor = ERedBlackTreeNodeColor.RED, parent: RedBlackTreeNode<T> | null = null, left: RedBlackTreeNode<T> | null = null, right: RedBlackTreeNode<T> | null = null ) { this.value = value; this.color = color; this.parent = parent; this.left = left; this.right = right; } } class RedBlackTree<T = any> { protected root: RedBlackTreeNode<T> | null = null; private searchTargetNode(value: T): RedBlackTreeNode<T> | null { let _targetNode = this.root; let parent: RedBlackTreeNode<T> | null = null; while (_targetNode) { if (_targetNode.value === value) { _targetNode.parent = parent; return _targetNode; } parent = _targetNode; if (value < _targetNode.value) { _targetNode = _targetNode.left; } else { _targetNode = _targetNode.right; } } return null; } private leftRotate(node: RedBlackTreeNode<T>) { let rightChild = node.right!; node.right = rightChild.left; if (rightChild.left) { rightChild.left.parent = node; } rightChild.parent = node.parent; if (!node.parent) { this.root = rightChild; } else if (node === node.parent.left) { node.parent.left = rightChild; } else { node.parent.right = rightChild; } rightChild.left = node; node.parent = rightChild; } private rightRotate(node: RedBlackTreeNode<T>) { let leftChild = node.left!; node.left = leftChild.right; if (leftChild.right) { leftChild.right.parent = node; } leftChild.parent = node.parent; if (!node.parent) { this.root = leftChild; } else if (node === node.parent.right) { node.parent.right = leftChild; } else { node.parent.left = leftChild; } leftChild.right = node; node.parent = leftChild; } private fixInsertion(node: RedBlackTreeNode<T>) { while (node.parent && node.parent.color === ERedBlackTreeNodeColor.RED) { let grandParent = node.parent.parent!; if (node.parent === grandParent.left) { let uncle = grandParent.right; if (uncle && uncle.color === ERedBlackTreeNodeColor.RED) { node.parent.color = ERedBlackTreeNodeColor.BLACK; uncle.color = ERedBlackTreeNodeColor.BLACK; grandParent.color = ERedBlackTreeNodeColor.RED; node = grandParent; } else { if (node === node.parent.right) { node = node.parent; this.leftRotate(node); } node.parent!.color = ERedBlackTreeNodeColor.BLACK; grandParent.color = ERedBlackTreeNodeColor.RED; this.rightRotate(grandParent); } } else { let uncle = grandParent.left; if (uncle && uncle.color === ERedBlackTreeNodeColor.RED) { node.parent.color = ERedBlackTreeNodeColor.BLACK; uncle.color = ERedBlackTreeNodeColor.BLACK; grandParent.color = ERedBlackTreeNodeColor.RED; node = grandParent; } else { if (node === node.parent.left) { node = node.parent; this.rightRotate(node); } node.parent!.color = ERedBlackTreeNodeColor.BLACK; grandParent.color = ERedBlackTreeNodeColor.RED; this.leftRotate(grandParent); } } } this.root!.color = ERedBlackTreeNodeColor.BLACK; } private _delete(node: RedBlackTreeNode<T>) { if (node.left && node.right) { const successor = this.minimum(node.right); node.value = successor!.value; node = successor!; } let child: RedBlackTreeNode<T> | null; if (node.left) { child = node.left; } else if (node.right) { child = node.right; } else { child = null; } if (!child) { if (node.color === ERedBlackTreeNodeColor.BLACK) { this._deleteCaseOne(node); } this._removeNode(node); } else { if (node.color === ERedBlackTreeNodeColor.BLACK) { if (child.color === ERedBlackTreeNodeColor.RED) { child.color = ERedBlackTreeNodeColor.BLACK; } else { this._deleteCaseOne(node); } } this._replaceNode(node, child); } } private _deleteCaseOne(node: RedBlackTreeNode<T>) { if (node.parent) { this._deleteStaTwo(node); } } private _deleteStaTwo(node: RedBlackTreeNode<T>) { const sibling = this._sibling(node); if (sibling && sibling.color === ERedBlackTreeNodeColor.RED) { node.parent!.color = ERedBlackTreeNodeColor.RED; sibling.color = ERedBlackTreeNodeColor.BLACK; if (node === node.parent!.left) { this.leftRotate(node.parent!); } else { this.rightRotate(node.parent!); } } this._deleteStaThree(node); } private _deleteStaThree(node: RedBlackTreeNode<T>) { const sibling = this._sibling(node); if ( node.parent!.color === ERedBlackTreeNodeColor.BLACK && sibling && sibling.color === ERedBlackTreeNodeColor.BLACK && (!sibling.left || sibling.left.color === ERedBlackTreeNodeColor.BLACK) && (!sibling.right || sibling.right.color === ERedBlackTreeNodeColor.BLACK) ) { sibling.color = ERedBlackTreeNodeColor.RED; this._deleteCaseOne(node.parent!); } else { this._deleteStaFour(node); } } private _deleteStaFour(node: RedBlackTreeNode<T>) { const sibling = this._sibling(node); if ( node.parent!.color === ERedBlackTreeNodeColor.RED && sibling && sibling.color === ERedBlackTreeNodeColor.BLACK && (!sibling.left || sibling.left.color === ERedBlackTreeNodeColor.BLACK) && (!sibling.right || sibling.right.color === ERedBlackTreeNodeColor.BLACK) ) { sibling.color = ERedBlackTreeNodeColor.RED; node.parent!.color = ERedBlackTreeNodeColor.BLACK; } else { this._deleteStaFive(node); } } private _deleteStaFive(node: RedBlackTreeNode<T>) { const sibling = this._sibling(node); if (sibling && sibling.color === ERedBlackTreeNodeColor.BLACK) { if ( node === node.parent!.left && sibling.right && sibling.right.color === ERedBlackTreeNodeColor.RED ) { sibling.color = ERedBlackTreeNodeColor.RED; sibling.right!.color = ERedBlackTreeNodeColor.BLACK; this.leftRotate(sibling); } else if ( node === node.parent!.right && sibling.left && sibling.left.color === ERedBlackTreeNodeColor.RED ) { sibling.color = ERedBlackTreeNodeColor.RED; sibling.left!.color = ERedBlackTreeNodeColor.BLACK; this.rightRotate(sibling); } } this._deleteStaSix(node); } private _deleteStaSix(node: RedBlackTreeNode<T>) { const sibling = this._sibling(node); sibling!.color = node.parent!.color; node.parent!.color = ERedBlackTreeNodeColor.BLACK; if (node === node.parent!.left) { sibling!.right!.color = ERedBlackTreeNodeColor.BLACK; this.leftRotate(node.parent!); } else { sibling!.left!.color = ERedBlackTreeNodeColor.BLACK; this.rightRotate(node.parent!); } } private _removeNode(node: RedBlackTreeNode<T>) { if (!node.parent) { this.root = null; } else if (node === node.parent.left) { node.parent.left = null; } else { node.parent.right = null; } } private _replaceNode(oldNode: RedBlackTreeNode<T>, newNode: RedBlackTreeNode<T>) { if (!oldNode.parent) { this.root = newNode; } else if (oldNode === oldNode.parent.left) { oldNode.parent.left = newNode; } else { oldNode.parent.right = newNode; } newNode.parent = oldNode.parent; } private _sibling(node: RedBlackTreeNode<T>) { if (!node.parent) { return null; } return node === node.parent.left ? node.parent.right : node.parent.left; } insert(value: T) { let newNode = new RedBlackTreeNode(value); if (!this.root) { this.root = newNode; newNode.color = ERedBlackTreeNodeColor.BLACK; return; } let current: RedBlackTreeNode<T> | null = this.root; let parent: RedBlackTreeNode<T> | null = null; while (current) { parent = current; if (value < current.value) { current = current.left; } else { current = current.right; } } newNode.parent = parent; if (value < parent!.value) { parent!.left = newNode; } else { parent!.right = newNode; } this.fixInsertion(newNode); } delete(value: T) { const nodeToDelete = this.searchTargetNode(value); if (!nodeToDelete) { return; } this._delete(nodeToDelete); } minimum(targetTreeNode: RedBlackTreeNode<T> | null = this.root): RedBlackTreeNode<T> | null { let current = targetTreeNode; while (current && current.left) { current = current.left; } return current; } } export { RedBlackTreeNode, RedBlackTree, };