UNPKG

trie-typed

Version:
145 lines (144 loc) 4.55 kB
"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;