345 lines
8.7 KiB
JavaScript
345 lines
8.7 KiB
JavaScript
class f {
|
|
constructor(t, e) {
|
|
this.next = null, this.key = t, this.data = e, this.left = null, this.right = null;
|
|
}
|
|
}
|
|
function d(n, t) {
|
|
return n > t ? 1 : n < t ? -1 : 0;
|
|
}
|
|
function u(n, t, e) {
|
|
const r = new f(null, null);
|
|
let l = r, i = r;
|
|
for (; ; ) {
|
|
const o = e(n, t.key);
|
|
if (o < 0) {
|
|
if (t.left === null) break;
|
|
if (e(n, t.left.key) < 0) {
|
|
const s = t.left;
|
|
if (t.left = s.right, s.right = t, t = s, t.left === null) break;
|
|
}
|
|
i.left = t, i = t, t = t.left;
|
|
} else if (o > 0) {
|
|
if (t.right === null) break;
|
|
if (e(n, t.right.key) > 0) {
|
|
const s = t.right;
|
|
if (t.right = s.left, s.left = t, t = s, t.right === null) break;
|
|
}
|
|
l.right = t, l = t, t = t.right;
|
|
} else break;
|
|
}
|
|
return l.right = t.left, i.left = t.right, t.left = r.right, t.right = r.left, t;
|
|
}
|
|
function c(n, t, e, r) {
|
|
const l = new f(n, t);
|
|
if (e === null)
|
|
return l.left = l.right = null, l;
|
|
e = u(n, e, r);
|
|
const i = r(n, e.key);
|
|
return i < 0 ? (l.left = e.left, l.right = e, e.left = null) : i >= 0 && (l.right = e.right, l.left = e, e.right = null), l;
|
|
}
|
|
function m(n, t, e) {
|
|
let r = null, l = null;
|
|
if (t) {
|
|
t = u(n, t, e);
|
|
const i = e(t.key, n);
|
|
i === 0 ? (r = t.left, l = t.right) : i < 0 ? (l = t.right, t.right = null, r = t) : (r = t.left, t.left = null, l = t);
|
|
}
|
|
return { left: r, right: l };
|
|
}
|
|
function w(n, t, e) {
|
|
return t === null ? n : (n === null || (t = u(n.key, t, e), t.left = n), t);
|
|
}
|
|
function _(n, t, e, r, l) {
|
|
if (n) {
|
|
r(`${t}${e ? "└── " : "├── "}${l(n)}
|
|
`);
|
|
const i = t + (e ? " " : "│ ");
|
|
n.left && _(n.left, i, !1, r, l), n.right && _(n.right, i, !0, r, l);
|
|
}
|
|
}
|
|
class z {
|
|
constructor(t = d) {
|
|
this._root = null, this._size = 0, this._comparator = t;
|
|
}
|
|
/**
|
|
* Inserts a key, allows duplicates
|
|
*/
|
|
insert(t, e) {
|
|
return this._size++, this._root = c(t, e, this._root, this._comparator);
|
|
}
|
|
/**
|
|
* Adds a key, if it is not present in the tree
|
|
*/
|
|
add(t, e) {
|
|
const r = new f(t, e);
|
|
this._root === null && (r.left = r.right = null, this._size++, this._root = r);
|
|
const l = this._comparator, i = u(t, this._root, l), o = l(t, i.key);
|
|
return o === 0 ? this._root = i : (o < 0 ? (r.left = i.left, r.right = i, i.left = null) : o > 0 && (r.right = i.right, r.left = i, i.right = null), this._size++, this._root = r), this._root;
|
|
}
|
|
/**
|
|
* @param {Key} key
|
|
* @return {Node|null}
|
|
*/
|
|
remove(t) {
|
|
this._root = this._remove(t, this._root, this._comparator);
|
|
}
|
|
/**
|
|
* Deletes i from the tree if it's there
|
|
*/
|
|
_remove(t, e, r) {
|
|
let l;
|
|
return e === null ? null : (e = u(t, e, r), r(t, e.key) === 0 ? (e.left === null ? l = e.right : (l = u(t, e.left, r), l.right = e.right), this._size--, l) : e);
|
|
}
|
|
/**
|
|
* Removes and returns the node with smallest key
|
|
*/
|
|
pop() {
|
|
let t = this._root;
|
|
if (t) {
|
|
for (; t.left; ) t = t.left;
|
|
return this._root = u(t.key, this._root, this._comparator), this._root = this._remove(t.key, this._root, this._comparator), { key: t.key, data: t.data };
|
|
}
|
|
return null;
|
|
}
|
|
/**
|
|
* Find without splaying
|
|
*/
|
|
findStatic(t) {
|
|
let e = this._root;
|
|
const r = this._comparator;
|
|
for (; e; ) {
|
|
const l = r(t, e.key);
|
|
if (l === 0) return e;
|
|
l < 0 ? e = e.left : e = e.right;
|
|
}
|
|
return null;
|
|
}
|
|
find(t) {
|
|
return this._root && (this._root = u(t, this._root, this._comparator), this._comparator(t, this._root.key) !== 0) ? null : this._root;
|
|
}
|
|
contains(t) {
|
|
let e = this._root;
|
|
const r = this._comparator;
|
|
for (; e; ) {
|
|
const l = r(t, e.key);
|
|
if (l === 0) return !0;
|
|
l < 0 ? e = e.left : e = e.right;
|
|
}
|
|
return !1;
|
|
}
|
|
forEach(t, e) {
|
|
let r = this._root;
|
|
const l = [];
|
|
let i = !1;
|
|
for (; !i; )
|
|
r !== null ? (l.push(r), r = r.left) : l.length !== 0 ? (r = l.pop(), t.call(e, r), r = r.right) : i = !0;
|
|
return this;
|
|
}
|
|
/**
|
|
* Walk key range from `low` to `high`. Stops if `fn` returns a value.
|
|
*/
|
|
range(t, e, r, l) {
|
|
const i = [], o = this._comparator;
|
|
let s = this._root, h;
|
|
for (; i.length !== 0 || s; )
|
|
if (s)
|
|
i.push(s), s = s.left;
|
|
else {
|
|
if (s = i.pop(), h = o(s.key, e), h > 0)
|
|
break;
|
|
if (o(s.key, t) >= 0 && r.call(l, s))
|
|
return this;
|
|
s = s.right;
|
|
}
|
|
return this;
|
|
}
|
|
/**
|
|
* Returns array of keys
|
|
*/
|
|
keys() {
|
|
const t = [];
|
|
return this.forEach(({ key: e }) => {
|
|
t.push(e);
|
|
}), t;
|
|
}
|
|
/**
|
|
* Returns array of all the data in the nodes
|
|
*/
|
|
values() {
|
|
const t = [];
|
|
return this.forEach(({ data: e }) => {
|
|
t.push(e);
|
|
}), t;
|
|
}
|
|
min() {
|
|
return this._root ? this.minNode(this._root).key : null;
|
|
}
|
|
max() {
|
|
return this._root ? this.maxNode(this._root).key : null;
|
|
}
|
|
minNode(t = this._root) {
|
|
if (t) for (; t.left; ) t = t.left;
|
|
return t;
|
|
}
|
|
maxNode(t = this._root) {
|
|
if (t) for (; t.right; ) t = t.right;
|
|
return t;
|
|
}
|
|
/**
|
|
* Returns node at given index
|
|
*/
|
|
at(t) {
|
|
let e = this._root, r = !1, l = 0;
|
|
const i = [];
|
|
for (; !r; )
|
|
if (e)
|
|
i.push(e), e = e.left;
|
|
else if (i.length > 0) {
|
|
if (e = i.pop(), l === t) return e;
|
|
l++, e = e.right;
|
|
} else r = !0;
|
|
return null;
|
|
}
|
|
next(t) {
|
|
let e = this._root, r = null;
|
|
if (t.right) {
|
|
for (r = t.right; r.left; ) r = r.left;
|
|
return r;
|
|
}
|
|
const l = this._comparator;
|
|
for (; e; ) {
|
|
const i = l(t.key, e.key);
|
|
if (i === 0) break;
|
|
i < 0 ? (r = e, e = e.left) : e = e.right;
|
|
}
|
|
return r;
|
|
}
|
|
prev(t) {
|
|
let e = this._root, r = null;
|
|
if (t.left !== null) {
|
|
for (r = t.left; r.right; ) r = r.right;
|
|
return r;
|
|
}
|
|
const l = this._comparator;
|
|
for (; e; ) {
|
|
const i = l(t.key, e.key);
|
|
if (i === 0) break;
|
|
i < 0 ? e = e.left : (r = e, e = e.right);
|
|
}
|
|
return r;
|
|
}
|
|
clear() {
|
|
return this._root = null, this._size = 0, this;
|
|
}
|
|
toList() {
|
|
return k(this._root);
|
|
}
|
|
/**
|
|
* Bulk-load items. Both array have to be same size
|
|
*/
|
|
load(t, e = [], r = !1) {
|
|
let l = t.length;
|
|
const i = this._comparator;
|
|
if (r && g(t, e, 0, l - 1, i), this._root === null)
|
|
this._root = a(t, e, 0, l), this._size = l;
|
|
else {
|
|
const o = y(
|
|
this.toList(),
|
|
x(t, e),
|
|
i
|
|
);
|
|
l = this._size + l, this._root = p({ head: o }, 0, l);
|
|
}
|
|
return this;
|
|
}
|
|
isEmpty() {
|
|
return this._root === null;
|
|
}
|
|
get size() {
|
|
return this._size;
|
|
}
|
|
get root() {
|
|
return this._root;
|
|
}
|
|
toString(t = (e) => String(e.key)) {
|
|
const e = [];
|
|
return _(this._root, "", !0, (r) => e.push(r), t), e.join("");
|
|
}
|
|
update(t, e, r) {
|
|
const l = this._comparator;
|
|
let { left: i, right: o } = m(t, this._root, l);
|
|
l(t, e) < 0 ? o = c(e, r, o, l) : i = c(e, r, i, l), this._root = w(i, o, l);
|
|
}
|
|
split(t) {
|
|
return m(t, this._root, this._comparator);
|
|
}
|
|
*[Symbol.iterator]() {
|
|
let t = this._root;
|
|
const e = [];
|
|
let r = !1;
|
|
for (; !r; )
|
|
t !== null ? (e.push(t), t = t.left) : e.length !== 0 ? (t = e.pop(), yield t, t = t.right) : r = !0;
|
|
}
|
|
}
|
|
function a(n, t, e, r) {
|
|
const l = r - e;
|
|
if (l > 0) {
|
|
const i = e + Math.floor(l / 2), o = n[i], s = t[i], h = new f(o, s);
|
|
return h.left = a(n, t, e, i), h.right = a(n, t, i + 1, r), h;
|
|
}
|
|
return null;
|
|
}
|
|
function x(n, t) {
|
|
const e = new f(null, null);
|
|
let r = e;
|
|
for (let l = 0; l < n.length; l++)
|
|
r = r.next = new f(n[l], t[l]);
|
|
return r.next = null, e.next;
|
|
}
|
|
function k(n) {
|
|
let t = n;
|
|
const e = [];
|
|
let r = !1;
|
|
const l = new f(null, null);
|
|
let i = l;
|
|
for (; !r; )
|
|
t ? (e.push(t), t = t.left) : e.length > 0 ? (t = i = i.next = e.pop(), t = t.right) : r = !0;
|
|
return i.next = null, l.next;
|
|
}
|
|
function p(n, t, e) {
|
|
const r = e - t;
|
|
if (r > 0) {
|
|
const l = t + Math.floor(r / 2), i = p(n, t, l), o = n.head;
|
|
return o.left = i, n.head = n.head.next, o.right = p(n, l + 1, e), o;
|
|
}
|
|
return null;
|
|
}
|
|
function y(n, t, e) {
|
|
const r = new f(null, null);
|
|
let l = r, i = n, o = t;
|
|
for (; i !== null && o !== null; )
|
|
e(i.key, o.key) < 0 ? (l.next = i, i = i.next) : (l.next = o, o = o.next), l = l.next;
|
|
return i !== null ? l.next = i : o !== null && (l.next = o), r.next;
|
|
}
|
|
function g(n, t, e, r, l) {
|
|
if (e >= r) return;
|
|
const i = n[e + r >> 1];
|
|
let o = e - 1, s = r + 1;
|
|
for (; ; ) {
|
|
do
|
|
o++;
|
|
while (l(n[o], i) < 0);
|
|
do
|
|
s--;
|
|
while (l(n[s], i) > 0);
|
|
if (o >= s) break;
|
|
let h = n[o];
|
|
n[o] = n[s], n[s] = h, h = t[o], t[o] = t[s], t[s] = h;
|
|
}
|
|
g(n, t, e, s, l), g(n, t, s + 1, r, l);
|
|
}
|
|
export {
|
|
z as default
|
|
};
|
|
//# sourceMappingURL=splaytree.js.map
|