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
JavaScript
"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;