UNPKG

ts-ds-tool

Version:

Data structure and algorithm of TypeScript

281 lines (280 loc) 9.57 kB
import { BinarySearchTree } from "../binary-search-tree/BinarySearchTree"; import { ENodeColor } from "../binary-search-tree/BinarySearchTreeNode"; function colorOf(node) { return node ? node.Color : ENodeColor.Black; } function leftOf(node) { return (node == null) ? null : node.Left; } function parentOf(node) { return !node ? null : node.parent; } function rightOf(node) { return !node ? null : node.Right; } function setColor(node, color) { if (node) { node.setColor(color); } } export class RedBlackTree extends BinarySearchTree { constructor(compareKey) { super(compareKey); } insert(value) { if (value === null || value === undefined) { return; } const insertedNode = super.insert(value); if (insertedNode === this.Root) { insertedNode.setColor(ENodeColor.Black); return insertedNode; } insertedNode.setColor(ENodeColor.Red); this.blance(insertedNode); return insertedNode; } remove(value) { if (value === null || value === undefined) { return false; } let p = this.find(value); if (!p) { return false; } if (p.Left && p.Right) { const s = this.getSuccessor(p); p.setValue(s.Value); p = s; } const replacement = (p.Left ? p.Left : p.Right); if (replacement) { replacement.parent = p.parent; if (!p.parent) this.Root = replacement; else if (p === p.parent.Left) p.parent.setLeft(replacement); else p.parent.setRight(replacement); p.setLeft(null); p.setRight(null); p.parent = null; if (p.Color === ENodeColor.Black) { this.deleteFixUp(replacement); } } else if (!p.parent) { this.Root = null; } else { if (p.Color === ENodeColor.Black) { this.deleteFixUp(p); } if (p.parent) { if (p === p.parent.Left) { p.parent.setLeft(null); } else if (p === p.parent.Right) { p.parent.setRight(null); } p.parent = null; } } return true; } getSuccessor(t) { if (t == null) return null; else if (t.Right) { let p = t.Right; while (p.Left) p = p.Left; return p; } else { let p = t.parent; let ch = t; while (p && ch === p.Right) { ch = p; p = p.parent; } return p; } } deleteFixUp(x) { while (x !== this.Root && colorOf(x) === ENodeColor.Black) { if (x === leftOf(parentOf(x))) { let sib = rightOf(parentOf(x)); if (colorOf(sib) === ENodeColor.Red) { setColor(sib, ENodeColor.Black); setColor(parentOf(x), ENodeColor.Red); this.leftRotate(parentOf(x), false); sib = rightOf(parentOf(x)); } if (colorOf(leftOf(sib)) === ENodeColor.Black && colorOf(rightOf(sib)) === ENodeColor.Black) { setColor(sib, ENodeColor.Red); x = parentOf(x); } else { if (colorOf(rightOf(sib)) === ENodeColor.Black) { setColor(leftOf(sib), ENodeColor.Black); setColor(sib, ENodeColor.Red); this.rightRotate(sib, false); sib = rightOf(parentOf(x)); } setColor(sib, colorOf(parentOf(x))); setColor(parentOf(x), ENodeColor.Black); setColor(rightOf(sib), ENodeColor.Black); this.leftRotate(parentOf(x), false); x = this.Root; } } else { let sib = leftOf(parentOf(x)); if (colorOf(sib) === ENodeColor.Red) { setColor(sib, ENodeColor.Black); setColor(parentOf(x), ENodeColor.Red); this.rightRotate(parentOf(x), false); sib = leftOf(parentOf(x)); } if (colorOf(rightOf(sib)) === ENodeColor.Black && colorOf(leftOf(sib)) === ENodeColor.Black) { setColor(sib, ENodeColor.Red); x = parentOf(x); } else { if (colorOf(leftOf(sib)) === ENodeColor.Black) { setColor(rightOf(sib), ENodeColor.Black); setColor(sib, ENodeColor.Red); this.leftRotate(sib, false); sib = leftOf(parentOf(x)); } setColor(sib, colorOf(parentOf(x))); setColor(parentOf(x), ENodeColor.Black); setColor(leftOf(sib), ENodeColor.Black); this.rightRotate(parentOf(x), false); x = this.Root; } } } setColor(x, ENodeColor.Black); } blance(node) { if (node === this.Root) { return; } const parent = node.parent; if (parent.Color === ENodeColor.Black) { return; } const uncle = node.getUncle(); const grandParent = parent.parent; if (uncle && uncle.Color === ENodeColor.Red) { parent.setColor(ENodeColor.Black); uncle.setColor(ENodeColor.Black); if (grandParent === this.Root) { return; } grandParent.setColor(ENodeColor.Red); this.blance(parent.parent); } else { let parentNode; if (parent === parent.parent.Left) { if (node === parent.Left) { parentNode = this.rightRotate(grandParent); } else { parentNode = this.leftRightRotate(grandParent); } } else { if (node === parent.Right) { parentNode = this.leftRotate(grandParent); } else { parentNode = this.rightLeftRotate(grandParent); } } if (!parentNode.parent) { this.Root = parentNode; this.Root.setColor(ENodeColor.Black); } this.blance(parentNode); } } rightRotate(grandParentNode, swapColor = true) { const grandGrandParent = grandParentNode.parent; let grandParentNodeIsLeft; if (grandGrandParent) { grandParentNodeIsLeft = grandGrandParent.Left === grandParentNode; } const parentNode = grandParentNode.Left; const parentRightNode = parentNode.Right; parentNode.setRight(grandParentNode); grandParentNode.setLeft(parentRightNode); if (grandGrandParent) { if (grandParentNodeIsLeft) { grandGrandParent.setLeft(parentNode); } else { grandGrandParent.setRight(parentNode); } } else { parentNode.parent = null; this.Root = parentNode; } swapColor && this.swapColor(parentNode, grandParentNode); return parentNode; } leftRightRotate(grandParentNode) { const parentNode = grandParentNode.Left; const childNode = parentNode.Right; const childLeftNode = childNode.Left; childNode.setLeft(parentNode); parentNode.setRight(childLeftNode); grandParentNode.setLeft(childNode); return this.rightRotate(grandParentNode); } leftRotate(grandParentNode, swapColor = true) { const grandGrandParent = grandParentNode.parent; let grandParentNodeIsLeft; if (grandGrandParent) { grandParentNodeIsLeft = grandGrandParent.Left === grandParentNode; } const parentNode = grandParentNode.Right; const parentLeftNode = parentNode.Left; parentNode.setLeft(grandParentNode); grandParentNode.setRight(parentLeftNode); if (grandGrandParent) { if (grandParentNodeIsLeft) { grandGrandParent.setLeft(parentNode); } else { grandGrandParent.setRight(parentNode); } } else { parentNode.parent = null; this.Root = parentNode; } swapColor && this.swapColor(parentNode, grandParentNode); return parentNode; } rightLeftRotate(grandParentNode) { const parentNode = grandParentNode.Right; const childNode = parentNode.Left; const childRightNode = childNode.Right; childNode.setRight(parentNode); parentNode.setLeft(childRightNode); grandParentNode.setRight(childNode); return this.leftRotate(grandParentNode); } swapColor(a, b) { const color = a.Color; a.setColor(b.Color); b.setColor(color); } }