UNPKG

sonic-forest

Version:

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

159 lines (158 loc) 5.1 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.createMap = void 0; const util_1 = require("../util"); const printTree_1 = require("../print/printTree"); const defaultComparator = (a, b) => (a === b ? 0 : a < b ? -1 : 1); const createMap = (Node, insert, insertLeft, insertRight, remove, print) => { class SonicMapImpl { constructor(comparator) { this.min = undefined; this.root = undefined; this.max = undefined; this._size = 0; this.next = util_1.next; this.comparator = comparator || defaultComparator; } set(k, v) { const root = this.root; if (root === undefined) { this._size = 1; const node = new Node(k, v); return (this.root = this.min = this.max = insert(void 0, node, this.comparator)); } const comparator = this.comparator; let cmp; const max = this.max; cmp = comparator(k, max.k); if (cmp === 0) return (max.v = v), max; else if (cmp > 0) { const node = (this.max = new Node(k, v)); this.root = insertRight(root, node, max); this._size++; return node; } const min = this.min; cmp = comparator(k, min.k); if (cmp === 0) return (min.v = v), min; else if (cmp < 0) { const node = (this.min = new Node(k, v)); this.root = insertLeft(root, node, min); this._size++; return node; } let curr = root; do { cmp = comparator(k, curr.k); if (cmp === 0) return (curr.v = v), curr; else if (cmp > 0) { const r = curr.r; if (r === undefined) { const node = new Node(k, v); this.root = insertRight(root, node, curr); this._size++; return node; } curr = r; } else if (cmp < 0) { const l = curr.l; if (l === undefined) { const node = new Node(k, v); this.root = insertLeft(root, node, curr); this._size++; return node; } curr = l; } } while (true); } find(k) { const comparator = this.comparator; let curr = this.root; while (curr) { const cmp = +comparator(k, curr.k); if (cmp === 0) return curr; curr = cmp < 0 ? curr.l : curr.r; } return; } get(k) { return this.find(k)?.v; } del(k) { const node = this.find(k); if (!node) return false; if (node === this.max) this.max = (0, util_1.prev)(node); if (node === this.min) this.min = (0, util_1.next)(node); this.root = remove(this.root, node); this._size--; return true; } clear() { this._size = 0; this.root = this.min = this.max = undefined; } has(k) { return !!this.find(k); } size() { return this._size; } isEmpty() { return !this.min; } getOrNextLower(k) { return (0, util_1.findOrNextLower)(this.root, k, this.comparator) || undefined; } forEach(fn) { let curr = this.first(); if (!curr) return; do fn(curr); while ((curr = (0, util_1.next)(curr))); } first() { return this.min; } last() { return this.max; } iterator0() { let curr = this.first(); return () => { if (!curr) return; const value = curr; curr = (0, util_1.next)(curr); return value; }; } iterator() { const iterator = this.iterator0(); return { next: () => { const value = iterator(); const res = { value, done: !value }; return res; }, }; } entries() { return { [Symbol.iterator]: () => this.iterator() }; } toString(tab) { return this.constructor.name + (0, printTree_1.printTree)(tab, [(tab) => print(this.root, tab)]); } } return SonicMapImpl; }; exports.createMap = createMap;