sonic-forest
Version:
High-performance (binary) tree and sorted map implementation (AVL, Splay, Radix, Red-Black)
238 lines (237 loc) • 5.84 kB
JavaScript
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.LlrbTree = exports.LlrbNode = void 0;
const util_1 = require("../util");
const printTree_1 = require("../print/printTree");
const red_black_1 = require("../red-black");
class LlrbNode {
constructor(k, v, b) {
this.k = k;
this.v = v;
this.b = b;
this.p = undefined;
this.l = undefined;
this.r = undefined;
}
}
exports.LlrbNode = LlrbNode;
const defaultComparator = (a, b) => (a === b ? 0 : a < b ? -1 : 1);
class LlrbTree {
constructor(comparator = defaultComparator) {
this.comparator = comparator;
this.min = undefined;
this.root = undefined;
this.max = undefined;
this._size = 0;
this.next = util_1.next;
}
set(k, v) {
const root = this.root;
if (!root) {
const item = new LlrbNode(k, v, true);
this.min = this.max = this.root = item;
this._size = 1;
return item;
}
let p = root;
let cmp;
const comparator = this.comparator;
const min = this.min;
if (min instanceof LlrbNode) {
cmp = comparator(k, min.k);
if (cmp < 0) {
this.min = p = new LlrbNode(k, v, false);
p.p = min;
min.l = p;
this._size++;
if (!min.b)
this._fixRRB(p, min);
return p;
}
}
const max = this.max;
if (max instanceof LlrbNode) {
cmp = comparator(k, max.k);
if (cmp > 0) {
this.max = p = new LlrbNode(k, v, false);
p.p = max;
max.r = p;
this._size++;
this._fix(p);
return p;
}
}
while (true) {
cmp = comparator(k, p.k);
if (cmp < 0) {
const l = p.l;
if (!l) {
const n = new LlrbNode(k, v, false);
n.p = p;
p.l = n;
this._size++;
if (!p.b)
this._fixRRB(n, p);
return n;
}
p = l;
}
else if (cmp > 0) {
const r = p.r;
if (!r) {
const n = new LlrbNode(k, v, false);
n.p = p;
p.r = n;
this._size++;
this._fix(n);
return n;
}
p = r;
}
else {
p.v = v;
return p;
}
}
}
_fixRRB(n, p) {
const g = p.p;
const s = p.r;
const gp = g.p;
p.p = gp;
p.r = g;
g.p = p;
g.l = s;
if (s)
s.p = g;
n.b = true;
if (!gp)
this.root = p;
else {
if (gp.l === g)
gp.l = p;
else
gp.r = p;
}
this._fix(p);
}
_fixBRR(n, p) {
const g = p.p;
const nl = n.l;
g.l = n;
n.p = g;
n.l = p;
p.p = n;
p.r = nl;
if (nl)
nl.p = p;
this._fixRRB(p, n);
}
_fixBBR(n, p) {
const g = p.p;
const nl = n.l;
n.p = g;
p.p = n;
n.l = p;
p.r = nl;
if (g) {
if (g.l === p)
g.l = n;
else
g.r = n;
}
else
this.root = n;
if (nl)
nl.p = p;
p.b = false;
n.b = true;
}
_fix(n) {
const p = n.p;
if (!p) {
n.b = true;
return;
}
const isLeftChild = p.l === n;
if (isLeftChild) {
if (p.b)
return;
this._fixRRB(n, p);
return;
}
const s = p.l;
const siblingIsBlack = !s || s.b;
if (siblingIsBlack) {
if (p.b) {
this._fixBBR(n, p);
return;
}
else {
this._fixBRR(n, p);
return;
}
}
else {
p.b = false;
s.b = true;
n.b = true;
this._fix(p);
return;
}
}
find(k) {
const comparator = this.comparator;
let curr = this.root;
while (curr) {
const cmp = comparator(k, curr.k);
if (!cmp)
return curr;
curr = cmp < 0 ? curr.l : curr.r;
}
return;
}
get(k) {
return this.find(k)?.v;
}
del(k) {
throw new Error('Method not implemented.');
}
clear() {
this.root = undefined;
}
has(k) {
return !!this.find(k);
}
size() {
return this._size;
}
isEmpty() {
return !this.root;
}
getOrNextLower(k) {
throw new Error('Method not implemented.');
}
forEach(fn) {
throw new Error('Method not implemented.');
}
first() {
return (0, util_1.first)(this.root);
}
last() {
return (0, util_1.last)(this.root);
}
iterator0() {
throw new Error('Method not implemented.');
}
iterator() {
throw new Error('Method not implemented.');
}
entries() {
return { [Symbol.iterator]: () => this.iterator() };
}
toString(tab) {
return this.constructor.name + (0, printTree_1.printTree)(tab, [(tab) => (0, red_black_1.print)(this.root, tab)]);
}
}
exports.LlrbTree = LlrbTree;