283 lines
10 KiB
JavaScript
283 lines
10 KiB
JavaScript
"use strict";
|
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
exports.XTree = void 0;
|
|
//================================================================
|
|
/**
|
|
* @packageDocumentation
|
|
* @module std.internal
|
|
*/
|
|
//================================================================
|
|
var XTreeNode_1 = require("./XTreeNode");
|
|
/**
|
|
* Red-Black Tree
|
|
*
|
|
* @reference https://en.wikipedia.org/w/index.php?title=Red%E2%80%93black_tree
|
|
* @inventor Rudolf Bayer
|
|
* @author Jeongho Nam - https://github.com/samchon
|
|
*/
|
|
var XTree = /** @class */ (function () {
|
|
/* ---------------------------------------------------------
|
|
CONSTRUCTOR
|
|
--------------------------------------------------------- */
|
|
function XTree(comp) {
|
|
this.root_ = null;
|
|
this.comp_ = comp;
|
|
this.equal_ = function (x, y) {
|
|
return !comp(x, y) && !comp(y, x);
|
|
};
|
|
}
|
|
XTree.prototype.clear = function () {
|
|
this.root_ = null;
|
|
};
|
|
/* =========================================================
|
|
ACCESSORS
|
|
- GETTERS
|
|
- COMPARISON
|
|
============================================================
|
|
GETTERS
|
|
--------------------------------------------------------- */
|
|
XTree.prototype.root = function () {
|
|
return this.root_;
|
|
};
|
|
XTree.prototype.get = function (val) {
|
|
var ret = this.nearest(val);
|
|
if (ret === null || !this.equal_(val, ret.value))
|
|
return null;
|
|
else
|
|
return ret;
|
|
};
|
|
XTree.prototype.nearest = function (val) {
|
|
// NEED NOT TO ITERATE
|
|
if (this.root_ === null)
|
|
return null;
|
|
//----
|
|
// ITERATE
|
|
//----
|
|
var ret = this.root_;
|
|
while (true) {
|
|
// UNTIL MEET THE MATCHED VALUE OR FINAL BRANCH
|
|
var my_node = null;
|
|
// COMPARE
|
|
if (this.comp_(val, ret.value))
|
|
my_node = ret.left;
|
|
else if (this.comp_(ret.value, val))
|
|
my_node = ret.right;
|
|
else
|
|
return ret; // MATCHED VALUE
|
|
// FINAL BRANCH? OR KEEP GOING
|
|
if (my_node !== null)
|
|
ret = my_node;
|
|
else
|
|
break;
|
|
}
|
|
return ret; // DIFFERENT NODE
|
|
};
|
|
XTree.prototype._Fetch_maximum = function (node) {
|
|
while (node.right !== null)
|
|
node = node.right;
|
|
return node;
|
|
};
|
|
/* =========================================================
|
|
ELEMENTS I/O
|
|
- INSERT
|
|
- ERASE
|
|
- COLOR
|
|
- ROTATION
|
|
============================================================
|
|
INSERT
|
|
--------------------------------------------------------- */
|
|
XTree.prototype.insert = function (val) {
|
|
var parent = this.nearest(val);
|
|
var node = new XTreeNode_1.XTreeNode(val, 1 /* Color.RED */);
|
|
if (parent === null)
|
|
this.root_ = node;
|
|
else {
|
|
node.parent = parent;
|
|
if (this.comp_(node.value, parent.value))
|
|
parent.left = node;
|
|
else
|
|
parent.right = node;
|
|
}
|
|
this._Insert_case1(node);
|
|
};
|
|
XTree.prototype._Insert_case1 = function (n) {
|
|
if (n.parent === null)
|
|
n.color = 0 /* Color.BLACK */;
|
|
else
|
|
this._Insert_case2(n);
|
|
};
|
|
XTree.prototype._Insert_case2 = function (n) {
|
|
if (this._Fetch_color(n.parent) === 0 /* Color.BLACK */)
|
|
return;
|
|
else
|
|
this._Insert_case3(n);
|
|
};
|
|
XTree.prototype._Insert_case3 = function (n) {
|
|
if (this._Fetch_color(n.uncle) === 1 /* Color.RED */) {
|
|
n.parent.color = 0 /* Color.BLACK */;
|
|
n.uncle.color = 0 /* Color.BLACK */;
|
|
n.grand.color = 1 /* Color.RED */;
|
|
this._Insert_case1(n.grand);
|
|
}
|
|
else
|
|
this._Insert_case4(n);
|
|
};
|
|
XTree.prototype._Insert_case4 = function (n) {
|
|
if (n === n.parent.right && n.parent === n.grand.left) {
|
|
this._Rotate_left(n.parent);
|
|
n = n.left;
|
|
}
|
|
else if (n === n.parent.left && n.parent === n.grand.right) {
|
|
this._Rotate_right(n.parent);
|
|
n = n.right;
|
|
}
|
|
this._Insert_case5(n);
|
|
};
|
|
XTree.prototype._Insert_case5 = function (n) {
|
|
n.parent.color = 0 /* Color.BLACK */;
|
|
n.grand.color = 1 /* Color.RED */;
|
|
if (n === n.parent.left && n.parent === n.grand.left)
|
|
this._Rotate_right(n.grand);
|
|
else
|
|
this._Rotate_left(n.grand);
|
|
};
|
|
/* ---------------------------------------------------------
|
|
ERASE
|
|
--------------------------------------------------------- */
|
|
XTree.prototype.erase = function (val) {
|
|
var node = this.get(val);
|
|
if (node === null)
|
|
return; // UNABLE TO FIND THE MATCHED NODE
|
|
if (node.left !== null && node.right !== null) {
|
|
var pred = this._Fetch_maximum(node.left);
|
|
node.value = pred.value;
|
|
node = pred;
|
|
}
|
|
var child = node.right === null ? node.left : node.right;
|
|
if (this._Fetch_color(node) === 0 /* Color.BLACK */) {
|
|
node.color = this._Fetch_color(child);
|
|
this._Erase_case1(node);
|
|
}
|
|
this._Replace_node(node, child);
|
|
if (this._Fetch_color(this.root_) === 1 /* Color.RED */)
|
|
this.root_.color = 0 /* Color.BLACK */;
|
|
};
|
|
XTree.prototype._Erase_case1 = function (n) {
|
|
if (n.parent === null)
|
|
return;
|
|
else
|
|
this._Erase_case2(n);
|
|
};
|
|
XTree.prototype._Erase_case2 = function (n) {
|
|
if (this._Fetch_color(n.sibling) === 1 /* Color.RED */) {
|
|
n.parent.color = 1 /* Color.RED */;
|
|
n.sibling.color = 0 /* Color.BLACK */;
|
|
if (n === n.parent.left)
|
|
this._Rotate_left(n.parent);
|
|
else
|
|
this._Rotate_right(n.parent);
|
|
}
|
|
this._Erase_case3(n);
|
|
};
|
|
XTree.prototype._Erase_case3 = function (n) {
|
|
if (this._Fetch_color(n.parent) === 0 /* Color.BLACK */ &&
|
|
this._Fetch_color(n.sibling) === 0 /* Color.BLACK */ &&
|
|
this._Fetch_color(n.sibling.left) === 0 /* Color.BLACK */ &&
|
|
this._Fetch_color(n.sibling.right) === 0 /* Color.BLACK */) {
|
|
n.sibling.color = 1 /* Color.RED */;
|
|
this._Erase_case1(n.parent);
|
|
}
|
|
else
|
|
this._Erase_case4(n);
|
|
};
|
|
XTree.prototype._Erase_case4 = function (N) {
|
|
if (this._Fetch_color(N.parent) === 1 /* Color.RED */ &&
|
|
N.sibling !== null &&
|
|
this._Fetch_color(N.sibling) === 0 /* Color.BLACK */ &&
|
|
this._Fetch_color(N.sibling.left) === 0 /* Color.BLACK */ &&
|
|
this._Fetch_color(N.sibling.right) === 0 /* Color.BLACK */) {
|
|
N.sibling.color = 1 /* Color.RED */;
|
|
N.parent.color = 0 /* Color.BLACK */;
|
|
}
|
|
else
|
|
this._Erase_case5(N);
|
|
};
|
|
XTree.prototype._Erase_case5 = function (n) {
|
|
if (n === n.parent.left &&
|
|
n.sibling !== null &&
|
|
this._Fetch_color(n.sibling) === 0 /* Color.BLACK */ &&
|
|
this._Fetch_color(n.sibling.left) === 1 /* Color.RED */ &&
|
|
this._Fetch_color(n.sibling.right) === 0 /* Color.BLACK */) {
|
|
n.sibling.color = 1 /* Color.RED */;
|
|
n.sibling.left.color = 0 /* Color.BLACK */;
|
|
this._Rotate_right(n.sibling);
|
|
}
|
|
else if (n === n.parent.right &&
|
|
n.sibling !== null &&
|
|
this._Fetch_color(n.sibling) === 0 /* Color.BLACK */ &&
|
|
this._Fetch_color(n.sibling.left) === 0 /* Color.BLACK */ &&
|
|
this._Fetch_color(n.sibling.right) === 1 /* Color.RED */) {
|
|
n.sibling.color = 1 /* Color.RED */;
|
|
n.sibling.right.color = 0 /* Color.BLACK */;
|
|
this._Rotate_left(n.sibling);
|
|
}
|
|
this._Erase_case6(n);
|
|
};
|
|
XTree.prototype._Erase_case6 = function (n) {
|
|
n.sibling.color = this._Fetch_color(n.parent);
|
|
n.parent.color = 0 /* Color.BLACK */;
|
|
if (n === n.parent.left) {
|
|
n.sibling.right.color = 0 /* Color.BLACK */;
|
|
this._Rotate_left(n.parent);
|
|
}
|
|
else {
|
|
n.sibling.left.color = 0 /* Color.BLACK */;
|
|
this._Rotate_right(n.parent);
|
|
}
|
|
};
|
|
/* ---------------------------------------------------------
|
|
ROTATION
|
|
--------------------------------------------------------- */
|
|
XTree.prototype._Rotate_left = function (node) {
|
|
var right = node.right;
|
|
this._Replace_node(node, right);
|
|
node.right = right.left;
|
|
if (right.left !== null)
|
|
right.left.parent = node;
|
|
right.left = node;
|
|
node.parent = right;
|
|
};
|
|
XTree.prototype._Rotate_right = function (node) {
|
|
var left = node.left;
|
|
this._Replace_node(node, left);
|
|
node.left = left.right;
|
|
if (left.right !== null)
|
|
left.right.parent = node;
|
|
left.right = node;
|
|
node.parent = left;
|
|
};
|
|
XTree.prototype._Replace_node = function (oldNode, newNode) {
|
|
if (oldNode.parent === null)
|
|
this.root_ = newNode;
|
|
else {
|
|
if (oldNode === oldNode.parent.left)
|
|
oldNode.parent.left = newNode;
|
|
else
|
|
oldNode.parent.right = newNode;
|
|
}
|
|
if (newNode !== null)
|
|
newNode.parent = oldNode.parent;
|
|
};
|
|
/* ---------------------------------------------------------
|
|
COLOR
|
|
--------------------------------------------------------- */
|
|
XTree.prototype._Fetch_color = function (node) {
|
|
if (node === null)
|
|
return 0 /* Color.BLACK */;
|
|
else
|
|
return node.color;
|
|
};
|
|
return XTree;
|
|
}());
|
|
exports.XTree = XTree;
|
|
//# sourceMappingURL=XTree.js.map
|