UNPKG

ts-collection

Version:

This is re-write of the java collection classes in typescript. There is some tweak as typescript templates are not as equivalent as Java.

574 lines (573 loc) 19.5 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); var nullpointerexception_1 = require("../lang/nullpointerexception"); var nosuchelementexception_1 = require("./nosuchelementexception"); var RedBlackColor; (function (RedBlackColor) { RedBlackColor[RedBlackColor["RED"] = 0] = "RED"; RedBlackColor[RedBlackColor["BLACK"] = 1] = "BLACK"; })(RedBlackColor = exports.RedBlackColor || (exports.RedBlackColor = {})); var RedBlackTreeNode = /** @class */ (function () { function RedBlackTreeNode(value, parent) { this.value = value; if (parent === undefined) { parent = null; } this.parent = parent; this.left = this.right = null; this.color = RedBlackColor.BLACK; } return RedBlackTreeNode; }()); exports.RedBlackTreeNode = RedBlackTreeNode; ; var RedBlackTree = /** @class */ (function () { function RedBlackTree(comparator) { this.m_Size = 0; this.modCount = 0; if (comparator === null) { throw new nullpointerexception_1.NullPointerException(); } this.m_Comparator = comparator; this.m_Root = null; } RedBlackTree.prototype.comparator = function () { return this.m_Comparator; }; RedBlackTree.prototype.contains = function (value) { return this.getRedBlackTreeNode(value) !== null; }; RedBlackTree.prototype.remove = function (value) { var p = this.getRedBlackTreeNode(value); if (p !== null) { this.deleteEntry(p); this.modCount++; this.m_Size--; return p.value; } return null; }; RedBlackTree.prototype.clear = function () { this.m_Root = null; }; RedBlackTree.prototype.put = function (value) { var t = this.m_Root; if (t === null) { this.m_Root = new RedBlackTreeNode(value); this.m_Size = 1; this.modCount++; return null; } var cmp; var parent; var cpr = this.m_Comparator; if (cpr !== null) { do { parent = t; cmp = cpr.compare(value, t.value); if (cmp < 0) { t = t.left; } else if (cmp > 0) { t = t.right; } else { return value; } } while (t !== null); } else { var k = value; do { parent = t; cmp = k.compareTo(t.value); if (cmp < 0) { t = t.left; } else if (cmp > 0) { t = t.right; } else { return value; } } while (t !== null); } var e = new RedBlackTreeNode(value, parent); if (cmp < 0) { parent.left = e; } else { parent.right = e; } this.fixAfterInsertion(e); this.modCount++; this.m_Size++; return null; }; RedBlackTree.prototype.getPredecessor = function (value) { var node = this.getRedBlackTreeNode(value); if (node === null) { return null; } var pred = this.predecessor(node); return RedBlackTree.entryOrNull(pred); }; RedBlackTree.prototype.getSuccessor = function (value) { var node = this.getRedBlackTreeNode(value); if (node === null) { return null; } var pred = this.successor(node); return RedBlackTree.entryOrNull(pred); }; RedBlackTree.prototype.getFirstNode = function () { var p = this.m_Root; if (p === null) { return null; } while (p.left !== null) { p = p.left; } return p; }; RedBlackTree.prototype.getLastNode = function () { var p = this.m_Root; if (p === null) { return null; } while (p.right !== null) { p = p.right; } return p; }; RedBlackTree.prototype.compareValues = function (v1, v2) { if (this.m_Comparator !== null) { return this.m_Comparator.compare(v1, v2); } else { var vc1 = v1; return vc1.compareTo(v2); } }; RedBlackTree.prototype.getCeilingNode = function (value) { var p = this.m_Root; while (p !== null) { var cmp = this.compareValues(value, p.value); if (cmp < 0) { if (p.left !== null) { p = p.left; } else { return p; } } else if (cmp > 0) { if (p.right !== null) { p = p.right; } else { var parent_1 = p.parent; var child = p; while (parent_1 !== null && child === parent_1.right) { child = parent_1; parent_1 = parent_1.parent; } return parent_1; } } else { return p; } } return null; }; RedBlackTree.prototype.getFloorNode = function (value) { var p = this.m_Root; while (p !== null) { var cmp = this.compareValues(value, p.value); if (cmp > 0) { if (p.right !== null) { p = p.right; } else { return p; } } else if (cmp < 0) { if (p.left !== null) { p = p.left; } else { var parent_2 = p.parent; var child = parent_2; while (parent_2 !== null && child === parent_2.left) { child = parent_2; parent_2 = parent_2.parent; } return parent_2; } } else { return p; } } return null; }; RedBlackTree.prototype.getHigherNode = function (value) { var p = this.m_Root; while (p != null) { var cmp = this.compareValues(value, p.value); if (cmp < 0) { if (p.left != null) p = p.left; else return p; } else { if (p.right != null) { p = p.right; } else { var parent_3 = p.parent; var ch = p; while (parent_3 != null && ch == parent_3.right) { ch = parent_3; parent_3 = parent_3.parent; } return parent_3; } } } return null; }; RedBlackTree.prototype.getLowerNode = function (value) { var p = this.m_Root; while (p != null) { var cmp = this.compareValues(value, p.value); if (cmp > 0) { if (p.right != null) p = p.right; else return p; } else { if (p.left != null) { p = p.left; } else { var parent_4 = p.parent; var ch = p; while (parent_4 != null && ch == parent_4.left) { ch = parent_4; parent_4 = parent_4.parent; } return parent_4; } } } return null; }; RedBlackTree.prototype.isEmpty = function () { return this.m_Root !== null; }; RedBlackTree.prototype.size = function () { return this.m_Size; }; RedBlackTree.prototype.getRedBlackTreeNode = function (value) { if (this.m_Comparator !== null) { return this.getNodeUsingComparator(value); } if (value === null) { throw new nullpointerexception_1.NullPointerException(); } var v = value; var p = this.m_Root; while (p !== null) { var cmp = v.compareTo(p.value); if (cmp < 0) { p = p.left; } else if (cmp > 0) { p = p.right; } else { return p; } } return null; }; RedBlackTree.prototype.getNodeUsingComparator = function (value) { var cpr = this.m_Comparator; if (cpr !== null) { var p = this.m_Root; while (p !== null) { var cmp = cpr.compare(value, p.value); if (cmp < 0) { p = p.left; } else if (cmp > 0) { p = p.right; } else { return p; } } } return null; }; RedBlackTree.prototype.colorOf = function (node) { if (node === null) { return RedBlackColor.BLACK; } return node.color; }; RedBlackTree.prototype.setColor = function (node, color) { if (node !== null) { node.color = color; } }; RedBlackTree.prototype.leftOf = function (node) { return node === null ? null : node.left; }; RedBlackTree.prototype.rightOf = function (node) { return node === null ? null : node.right; }; RedBlackTree.prototype.parentOf = function (node) { return node === null ? null : node.parent; }; RedBlackTree.prototype.rotateLeft = function (node) { var p = node; if (p !== null) { var r = p.right; p.right = r.left; if (r.left != null) r.left.parent = p; r.parent = p.parent; if (p.parent == null) this.m_Root = r; else if (p.parent.left == p) p.parent.left = r; else p.parent.right = r; r.left = p; p.parent = r; } }; RedBlackTree.prototype.rotateRight = function (node) { var p = node; if (p != null) { var l = p.left; p.left = l.right; if (l.right != null) l.right.parent = p; l.parent = p.parent; if (p.parent == null) this.m_Root = l; else if (p.parent.right == p) p.parent.right = l; else p.parent.left = l; l.right = p; p.parent = l; } }; RedBlackTree.prototype.fixAfterInsertion = function (x) { x.color = RedBlackColor.RED; while (x !== null && x != this.m_Root && x.parent.color == RedBlackColor.RED) { if (this.parentOf(x) == this.leftOf(this.parentOf(this.parentOf(x)))) { var y = this.rightOf(this.parentOf(this.parentOf(x))); if (this.colorOf(y) == RedBlackColor.RED) { this.setColor(this.parentOf(x), RedBlackColor.BLACK); this.setColor(y, RedBlackColor.BLACK); this.setColor(this.parentOf(this.parentOf(x)), RedBlackColor.RED); x = this.parentOf(this.parentOf(x)); } else { if (x == this.rightOf(this.parentOf(x))) { x = this.parentOf(x); this.rotateLeft(x); } this.setColor(this.parentOf(x), RedBlackColor.BLACK); this.setColor(this.parentOf(this.parentOf(x)), RedBlackColor.RED); this.rotateRight(this.parentOf(this.parentOf(x))); } } else { var y = this.leftOf(this.parentOf(this.parentOf(x))); if (this.colorOf(y) == RedBlackColor.RED) { this.setColor(this.parentOf(x), RedBlackColor.BLACK); this.setColor(y, RedBlackColor.BLACK); this.setColor(this.parentOf(this.parentOf(x)), RedBlackColor.RED); x = this.parentOf(this.parentOf(x)); } else { if (x == this.leftOf(this.parentOf(x))) { x = this.parentOf(x); this.rotateRight(x); } this.setColor(this.parentOf(x), RedBlackColor.BLACK); this.setColor(this.parentOf(this.parentOf(x)), RedBlackColor.RED); this.rotateLeft(this.parentOf(this.parentOf(x))); } } } this.m_Root.color = RedBlackColor.BLACK; }; RedBlackTree.prototype.successor = function (t) { if (t == null) return null; else if (t.right != null) { var p = t.right; while (p.left != null) p = p.left; return p; } else { var p = t.parent; var ch = t; while (p != null && ch == p.right) { ch = p; p = p.parent; } return p; } }; RedBlackTree.key = function (entry) { if (entry === null) { throw new nosuchelementexception_1.NoSuchElementException(); } return entry.getKey(); }; RedBlackTree.entryOrNull = function (node) { return node === null ? null : node.value; }; /** * Returns the predecessor of the specified Entry, or null if no such. */ RedBlackTree.prototype.predecessor = function (t) { if (t == null) return null; else if (t.left != null) { var p = t.left; while (p.right != null) p = p.right; return p; } else { var p = t.parent; var ch = t; while (p != null && ch == p.left) { ch = p; p = p.parent; } return p; } }; /** * Delete node p, and then rebalance the tree. */ RedBlackTree.prototype.deleteEntry = function (p) { // If strictly internal, copy successor's element to p and then make p // point to successor. this.m_Size--; this.modCount++; if (p.left != null && p.right != null) { var s = this.successor(p); p.value = s.value; p = s; } // p has 2 children // Start fixup at replacement node, if it exists. var replacement = (p.left !== null ? p.left : p.right); if (replacement !== null) { // Link replacement to parent replacement.parent = p.parent; if (p.parent === null) this.m_Root = replacement; else if (p === p.parent.left) p.parent.left = replacement; else p.parent.right = replacement; // Null out links so they are OK to use by fixAfterDeletion. p.left = p.right = p.parent = null; // Fix replacement if (p.color === RedBlackColor.BLACK) this.fixAfterDeletion(replacement); } else if (p.parent === null) { // return if we are the only node. this.m_Root = null; } else { // No children. Use self as phantom replacement and unlink. if (p.color === RedBlackColor.BLACK) this.fixAfterDeletion(p); if (p.parent !== null) { if (p === p.parent.left) p.parent.left = null; else if (p === p.parent.right) p.parent.right = null; p.parent = null; } } }; /** From CLR */ RedBlackTree.prototype.fixAfterDeletion = function (x) { while (x != this.m_Root && this.colorOf(x) == RedBlackColor.BLACK) { if (x == this.leftOf(this.parentOf(x))) { var sib = this.rightOf(this.parentOf(x)); if (this.colorOf(sib) == RedBlackColor.RED) { this.setColor(sib, RedBlackColor.BLACK); this.setColor(this.parentOf(x), RedBlackColor.RED); this.rotateLeft(this.parentOf(x)); sib = this.rightOf(this.parentOf(x)); } if (this.colorOf(this.leftOf(sib)) == RedBlackColor.BLACK && this.colorOf(this.rightOf(sib)) == RedBlackColor.BLACK) { this.setColor(sib, RedBlackColor.RED); x = this.parentOf(x); } else { if (this.colorOf(this.rightOf(sib)) == RedBlackColor.BLACK) { this.setColor(this.leftOf(sib), RedBlackColor.BLACK); this.setColor(sib, RedBlackColor.RED); this.rotateRight(sib); sib = this.rightOf(this.parentOf(x)); } this.setColor(sib, this.colorOf(this.parentOf(x))); this.setColor(this.parentOf(x), RedBlackColor.BLACK); this.setColor(this.rightOf(sib), RedBlackColor.BLACK); this.rotateLeft(this.parentOf(x)); x = this.m_Root; } } else { // symmetric var sib = this.leftOf(this.parentOf(x)); if (this.colorOf(sib) == RedBlackColor.RED) { this.setColor(sib, RedBlackColor.BLACK); this.setColor(this.parentOf(x), RedBlackColor.RED); this.rotateRight(this.parentOf(x)); sib = this.leftOf(this.parentOf(x)); } if (this.colorOf(this.rightOf(sib)) == RedBlackColor.BLACK && this.colorOf(this.leftOf(sib)) == RedBlackColor.BLACK) { this.setColor(sib, RedBlackColor.RED); x = this.parentOf(x); } else { if (this.colorOf(this.leftOf(sib)) == RedBlackColor.BLACK) { this.setColor(this.rightOf(sib), RedBlackColor.BLACK); this.setColor(sib, RedBlackColor.RED); this.rotateLeft(sib); sib = this.leftOf(this.parentOf(x)); } this.setColor(sib, this.colorOf(this.parentOf(x))); this.setColor(this.parentOf(x), RedBlackColor.BLACK); this.setColor(this.leftOf(sib), RedBlackColor.BLACK); this.rotateRight(this.parentOf(x)); x = this.m_Root; } } } this.setColor(x, RedBlackColor.BLACK); }; return RedBlackTree; }()); exports.RedBlackTree = RedBlackTree;