trie-typed
Version:
Trie, prefix tree
145 lines (144 loc) • 4.55 kB
JavaScript
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.SkipList = exports.SkipListNode = void 0;
class SkipListNode {
constructor(key, value, level) {
this.key = key;
this.value = value;
this.forward = new Array(level);
}
}
exports.SkipListNode = SkipListNode;
class SkipList {
constructor(elements = [], options) {
this._head = new SkipListNode(undefined, undefined, this.maxLevel);
this._level = 0;
this._maxLevel = 16;
this._probability = 0.5;
if (options) {
const { maxLevel, probability } = options;
if (typeof maxLevel === 'number')
this._maxLevel = maxLevel;
if (typeof probability === 'number')
this._probability = probability;
}
if (elements) {
for (const [key, value] of elements)
this.add(key, value);
}
}
get head() {
return this._head;
}
get level() {
return this._level;
}
get maxLevel() {
return this._maxLevel;
}
get probability() {
return this._probability;
}
get first() {
const firstNode = this.head.forward[0];
return firstNode ? firstNode.value : undefined;
}
get last() {
let current = this.head;
for (let i = this.level - 1; i >= 0; i--) {
while (current.forward[i]) {
current = current.forward[i];
}
}
return current.value;
}
add(key, value) {
const newNode = new SkipListNode(key, value, this._randomLevel());
const update = new Array(this.maxLevel).fill(this.head);
let current = this.head;
for (let i = this.level - 1; i >= 0; i--) {
while (current.forward[i] && current.forward[i].key < key) {
current = current.forward[i];
}
update[i] = current;
}
for (let i = 0; i < newNode.forward.length; i++) {
newNode.forward[i] = update[i].forward[i];
update[i].forward[i] = newNode;
}
if (!newNode.forward[0]) {
this._level = Math.max(this.level, newNode.forward.length);
}
}
get(key) {
let current = this.head;
for (let i = this.level - 1; i >= 0; i--) {
while (current.forward[i] && current.forward[i].key < key) {
current = current.forward[i];
}
}
current = current.forward[0];
if (current && current.key === key) {
return current.value;
}
return undefined;
}
has(key) {
return this.get(key) !== undefined;
}
delete(key) {
const update = new Array(this.maxLevel).fill(this.head);
let current = this.head;
for (let i = this.level - 1; i >= 0; i--) {
while (current.forward[i] && current.forward[i].key < key) {
current = current.forward[i];
}
update[i] = current;
}
current = current.forward[0];
if (current && current.key === key) {
for (let i = 0; i < this.level; i++) {
if (update[i].forward[i] !== current) {
break;
}
update[i].forward[i] = current.forward[i];
}
while (this.level > 0 && !this.head.forward[this.level - 1]) {
this._level--;
}
return true;
}
return false;
}
higher(key) {
let current = this.head;
for (let i = this.level - 1; i >= 0; i--) {
while (current.forward[i] && current.forward[i].key <= key) {
current = current.forward[i];
}
}
const nextNode = current.forward[0];
return nextNode ? nextNode.value : undefined;
}
lower(key) {
let current = this.head;
let lastLess = undefined;
for (let i = this.level - 1; i >= 0; i--) {
while (current.forward[i] && current.forward[i].key < key) {
current = current.forward[i];
}
if (current.key < key) {
lastLess = current;
}
}
return lastLess ? lastLess.value : undefined;
}
_randomLevel() {
let level = 1;
while (Math.random() < this.probability && level < this.maxLevel) {
level++;
}
return level;
}
}
exports.SkipList = SkipList;