200 lines
4.9 KiB
JavaScript
200 lines
4.9 KiB
JavaScript
"use strict";
|
|
|
|
Object.defineProperty(exports, "__esModule", {
|
|
value: true
|
|
});
|
|
exports.RedBlackTreeIterator = exports.Direction = void 0;
|
|
var Arr = _interopRequireWildcard(require("../../Array.js"));
|
|
var Option = _interopRequireWildcard(require("../../Option.js"));
|
|
function _interopRequireWildcard(e, t) { if ("function" == typeof WeakMap) var r = new WeakMap(), n = new WeakMap(); return (_interopRequireWildcard = function (e, t) { if (!t && e && e.__esModule) return e; var o, i, f = { __proto__: null, default: e }; if (null === e || "object" != typeof e && "function" != typeof e) return f; if (o = t ? n : r) { if (o.has(e)) return o.get(e); o.set(e, f); } for (const t in e) "default" !== t && {}.hasOwnProperty.call(e, t) && ((i = (o = Object.defineProperty) && Object.getOwnPropertyDescriptor(e, t)) && (i.get || i.set) ? o(f, t, i) : f[t] = e[t]); return f; })(e, t); }
|
|
/** @internal */
|
|
const Direction = exports.Direction = {
|
|
Forward: 0,
|
|
Backward: 1 << 0
|
|
};
|
|
/** @internal */
|
|
class RedBlackTreeIterator {
|
|
self;
|
|
stack;
|
|
direction;
|
|
count = 0;
|
|
constructor(self, stack, direction) {
|
|
this.self = self;
|
|
this.stack = stack;
|
|
this.direction = direction;
|
|
}
|
|
/**
|
|
* Clones the iterator
|
|
*/
|
|
clone() {
|
|
return new RedBlackTreeIterator(this.self, this.stack.slice(), this.direction);
|
|
}
|
|
/**
|
|
* Reverse the traversal direction
|
|
*/
|
|
reversed() {
|
|
return new RedBlackTreeIterator(this.self, this.stack.slice(), this.direction === Direction.Forward ? Direction.Backward : Direction.Forward);
|
|
}
|
|
/**
|
|
* Iterator next
|
|
*/
|
|
next() {
|
|
const entry = this.entry;
|
|
this.count++;
|
|
if (this.direction === Direction.Forward) {
|
|
this.moveNext();
|
|
} else {
|
|
this.movePrev();
|
|
}
|
|
switch (entry._tag) {
|
|
case "None":
|
|
{
|
|
return {
|
|
done: true,
|
|
value: this.count
|
|
};
|
|
}
|
|
case "Some":
|
|
{
|
|
return {
|
|
done: false,
|
|
value: entry.value
|
|
};
|
|
}
|
|
}
|
|
}
|
|
/**
|
|
* Returns the key
|
|
*/
|
|
get key() {
|
|
if (this.stack.length > 0) {
|
|
return Option.some(this.stack[this.stack.length - 1].key);
|
|
}
|
|
return Option.none();
|
|
}
|
|
/**
|
|
* Returns the value
|
|
*/
|
|
get value() {
|
|
if (this.stack.length > 0) {
|
|
return Option.some(this.stack[this.stack.length - 1].value);
|
|
}
|
|
return Option.none();
|
|
}
|
|
/**
|
|
* Returns the key
|
|
*/
|
|
get entry() {
|
|
return Option.map(Arr.last(this.stack), node => [node.key, node.value]);
|
|
}
|
|
/**
|
|
* Returns the position of this iterator in the sorted list
|
|
*/
|
|
get index() {
|
|
let idx = 0;
|
|
const stack = this.stack;
|
|
if (stack.length === 0) {
|
|
const r = this.self._root;
|
|
if (r != null) {
|
|
return r.count;
|
|
}
|
|
return 0;
|
|
} else if (stack[stack.length - 1].left != null) {
|
|
idx = stack[stack.length - 1].left.count;
|
|
}
|
|
for (let s = stack.length - 2; s >= 0; --s) {
|
|
if (stack[s + 1] === stack[s].right) {
|
|
;
|
|
++idx;
|
|
if (stack[s].left != null) {
|
|
idx += stack[s].left.count;
|
|
}
|
|
}
|
|
}
|
|
return idx;
|
|
}
|
|
/**
|
|
* Advances iterator to next element in list
|
|
*/
|
|
moveNext() {
|
|
const stack = this.stack;
|
|
if (stack.length === 0) {
|
|
return;
|
|
}
|
|
let n = stack[stack.length - 1];
|
|
if (n.right != null) {
|
|
n = n.right;
|
|
while (n != null) {
|
|
stack.push(n);
|
|
n = n.left;
|
|
}
|
|
} else {
|
|
stack.pop();
|
|
while (stack.length > 0 && stack[stack.length - 1].right === n) {
|
|
n = stack[stack.length - 1];
|
|
stack.pop();
|
|
}
|
|
}
|
|
}
|
|
/**
|
|
* Checks if there is a next element
|
|
*/
|
|
get hasNext() {
|
|
const stack = this.stack;
|
|
if (stack.length === 0) {
|
|
return false;
|
|
}
|
|
if (stack[stack.length - 1].right != null) {
|
|
return true;
|
|
}
|
|
for (let s = stack.length - 1; s > 0; --s) {
|
|
if (stack[s - 1].left === stack[s]) {
|
|
return true;
|
|
}
|
|
}
|
|
return false;
|
|
}
|
|
/**
|
|
* Advances iterator to previous element in list
|
|
*/
|
|
movePrev() {
|
|
const stack = this.stack;
|
|
if (stack.length === 0) {
|
|
return;
|
|
}
|
|
let n = stack[stack.length - 1];
|
|
if (n != null && n.left != null) {
|
|
n = n.left;
|
|
while (n != null) {
|
|
stack.push(n);
|
|
n = n.right;
|
|
}
|
|
} else {
|
|
stack.pop();
|
|
while (stack.length > 0 && stack[stack.length - 1].left === n) {
|
|
n = stack[stack.length - 1];
|
|
stack.pop();
|
|
}
|
|
}
|
|
}
|
|
/**
|
|
* Checks if there is a previous element
|
|
*/
|
|
get hasPrev() {
|
|
const stack = this.stack;
|
|
if (stack.length === 0) {
|
|
return false;
|
|
}
|
|
if (stack[stack.length - 1].left != null) {
|
|
return true;
|
|
}
|
|
for (let s = stack.length - 1; s > 0; --s) {
|
|
if (stack[s - 1].right === stack[s]) {
|
|
return true;
|
|
}
|
|
}
|
|
return false;
|
|
}
|
|
}
|
|
exports.RedBlackTreeIterator = RedBlackTreeIterator;
|
|
//# sourceMappingURL=iterator.js.map
|