UNPKG

sonic-forest

Version:

High-performance (binary) tree and sorted map implementation (AVL, Splay, Radix, Red-Black)

238 lines (237 loc) 5.84 kB
"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;