sonic-forest
Version:
High-performance (binary) tree and sorted map implementation (AVL, Splay, Radix, Red-Black)
159 lines (158 loc) • 5.1 kB
JavaScript
"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;