import {RBNode} from './rbNode' import {RBColor} from './rbColor' export class RBTree { readonly comparer: (a: T, b: T) => number count: number root: RBNode nil: RBNode; [Symbol.iterator](): IterableIterator { return this.allNodes() } constructor(comparer: (a: T, b: T) => number) { this.comparer = comparer this.count = 0 this.root = this.nil = new RBNode(RBColor.Black) } clear() { this.root = this.nil = new RBNode(RBColor.Black) } toNull(y: RBNode): RBNode { return y !== this.nil ? y : null } isEmpty(): boolean { return this.root === this.nil } getComparer(): (a: T, b: T) => number { return this.comparer } getRoot(): RBNode { return this.root } find(i: T, x: RBNode = this.root): RBNode { let compareResult: number while (x !== this.nil && (compareResult = this.comparer(i, x.item)) !== 0) x = compareResult < 0 ? x.left : x.right return this.toNull(x) } findFirst(predicate: (t: T) => boolean, n: RBNode = this.root): RBNode { if (n === this.nil) return null let good: RBNode = null while (n !== this.nil) { n = predicate(n.item) ? (good = n).left : n.right } return good } findLast(predicate: (t: T) => boolean, n: RBNode = this.root): RBNode { if (n === this.nil) return null let good: RBNode = null while (n !== this.nil) n = predicate(n.item) ? (good = n).right : n.left return good } treeMinimum(x: RBNode = this.root): RBNode { while (x.left !== this.nil) x = x.left return this.toNull(x) } treeMaximum(x: RBNode = this.root): RBNode { while (x.right !== this.nil) x = x.right return this.toNull(x) } next(x: RBNode): RBNode { if (x.right !== this.nil) return this.treeMinimum(x.right) let y: RBNode = x.parent while (y !== this.nil && x === y.right) { x = y y = y.parent } return this.toNull(y) } previous(x: RBNode): RBNode { if (x.left !== this.nil) return this.treeMaximum(x.left) let y: RBNode = x.parent while (y !== this.nil && x === y.left) { x = y y = y.parent } return this.toNull(y) } private leftRotate(x: RBNode) { const y: RBNode = x.right x.right = y.left if (y.left !== this.nil) y.left.parent = x y.parent = x.parent if (x.parent === this.nil) this.root = y else if (x === x.parent.left) x.parent.left = y else x.parent.right = y y.left = x x.parent = y } private rightRotate(x: RBNode) { const y: RBNode = x.left x.left = y.right if (y.right !== this.nil) y.right.parent = x y.parent = x.parent if (x.parent === this.nil) this.root = y else if (x === x.parent.right) x.parent.right = y else x.parent.left = y y.right = x x.parent = y } private deleteFixup(x: RBNode) { while (x !== this.root && x.color === RBColor.Black) { if (x === x.parent.left) { let w: RBNode = x.parent.right if (w.color === RBColor.Red) { w.color = RBColor.Black x.parent.color = RBColor.Red this.leftRotate(x.parent) w = x.parent.right } if (w.left.color === RBColor.Black && w.right.color === RBColor.Black) { w.color = RBColor.Red x = x.parent } else { if (w.right.color === RBColor.Black) { w.left.color = RBColor.Black w.color = RBColor.Red this.rightRotate(w) w = x.parent.right } w.color = x.parent.color x.parent.color = RBColor.Black w.right.color = RBColor.Black this.leftRotate(x.parent) x = this.root } } else { let w: RBNode = x.parent.left if (w.color === RBColor.Red) { w.color = RBColor.Black x.parent.color = RBColor.Red this.rightRotate(x.parent) w = x.parent.left } if (w.right.color === RBColor.Black && w.left.color === RBColor.Black) { w.color = RBColor.Red x = x.parent } else { if (w.left.color === RBColor.Black) { w.right.color = RBColor.Black w.color = RBColor.Red this.leftRotate(w) w = x.parent.left } w.color = x.parent.color x.parent.color = RBColor.Black w.left.color = RBColor.Black this.rightRotate(x.parent) x = this.root } } } x.color = RBColor.Black } deleteSubTree(z: RBNode): RBNode { //Assert.assert(z !== nil); /*Assert.assert(z !== this.nil, 'root of subtree to delete must not be null.')*/ let y: RBNode if (z.left === this.nil || z.right === this.nil) { /* y has a nil node as a child */ y = z } else { /* find tree successor with a nilnode as a child */ y = z.right while (y.left !== this.nil) y = y.left } /* x is y's only child */ const x: RBNode = y.left !== this.nil ? y.left : y.right x.parent = y.parent if (y.parent === this.nil) this.root = x else { if (y === y.parent.left) y.parent.left = x else y.parent.right = x } if (y !== z) z.item = y.item if (y.color === RBColor.Black) this.deleteFixup(x) return this.toNull(z) } deleteNodeInternal(x: RBNode) { this.count-- this.deleteSubTree(x) } remove(i: T): RBNode { const n: RBNode = this.find(i) if (n != null) { this.count-- return this.deleteSubTree(n) } return null } insert(v: T): RBNode { const x: RBNode = this.treeInsert(v) this.insertPrivate(x) return this.toNull(x) } treeInsert(z: T): RBNode { let y = this.nil let x = this.root let compareRes = 0 while (x !== this.nil) { y = x //#if SHARPKIT //https://code.google.com/p/sharpkit/issues/detail?id=368 // compareRes = Comparer.Compare(z, x.Item); // x = compareRes < 0 ? x.left : x.right; compareRes = this.comparer(z, x.item) x = compareRes < 0 ? x.left : x.right // #else // x = (compareRes = Comparer.Compare(z, x.Item)) < 0 ? x.left : x.right; // #endif } const nz = new RBNode(RBColor.Black, z, y, this.nil, this.nil) if (y === this.nil) this.root = nz else if (compareRes < 0) y.left = nz else y.right = nz return this.toNull(nz) } private insertPrivate(x: RBNode) { this.count++ x.color = RBColor.Red while (x !== this.root && x.parent.color === RBColor.Red) { if (x.parent === x.parent.parent.left) { const y: RBNode = x.parent.parent.right if (y.color === RBColor.Red) { x.parent.color = RBColor.Black y.color = RBColor.Black x.parent.parent.color = RBColor.Red x = x.parent.parent } else { if (x === x.parent.right) { x = x.parent this.leftRotate(x) } x.parent.color = RBColor.Black x.parent.parent.color = RBColor.Red this.rightRotate(x.parent.parent) } } else { const y: RBNode = x.parent.parent.left if (y.color === RBColor.Red) { x.parent.color = RBColor.Black y.color = RBColor.Black x.parent.parent.color = RBColor.Red x = x.parent.parent } else { if (x === x.parent.left) { x = x.parent this.rightRotate(x) } x.parent.color = RBColor.Black x.parent.parent.color = RBColor.Red this.leftRotate(x.parent.parent) } } } this.root.color = RBColor.Black } *allNodes(): IterableIterator { if (this.isEmpty()) return let c: RBNode = this.treeMinimum() while (c != null) { yield c.item c = this.next(c) } return } public toString(): string { let ret = '{' let i = 0 for (const node of this.allNodes()) { ret += node.toString() if (i !== this.count - 1) { ret += '\n' } i++ } return ret + '}' } }