UNPKG

directed-graph-typed

Version:
281 lines (247 loc) 8.48 kB
/** * data-structure-typed * * @author Pablo Zeng * @copyright Copyright (c) 2022 Pablo Zeng <zrwusa@gmail.com> * @license MIT License */ import type { SkipLinkedListOptions } from '../../types'; export class SkipListNode<K, V> { key: K; value: V; forward: SkipListNode<K, V>[]; constructor(key: K, value: V, level: number) { this.key = key; this.value = value; this.forward = new Array(level); } } /** * */ export class SkipList<K, V> { /** * The constructor function initializes a SkipLinkedList object with optional options and elements. * @param elements - The `elements` parameter is an iterable containing key-value pairs `[K, V]`. It * is used to initialize the SkipLinkedList with the given key-value pairs. If no elements are * provided, the SkipLinkedList will be empty. * @param {SkipLinkedListOptions} [options] - The `options` parameter is an optional object that can * contain two properties: */ constructor(elements: Iterable<[K, V]> = [], options?: SkipLinkedListOptions) { 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); } } protected _head: SkipListNode<K, V> = new SkipListNode<K, V>(undefined as any, undefined as any, this.maxLevel); /** * The function returns the head node of a SkipList. * @returns The method is returning a SkipListNode object with generic key type K and value type V. */ get head(): SkipListNode<K, V> { return this._head; } protected _level: number = 0; /** * The function returns the value of the protected variable _level. * @returns The level property of the object. */ get level(): number { return this._level; } protected _maxLevel: number = 16; /** * The function returns the maximum level. * @returns The value of the variable `_maxLevel` is being returned. */ get maxLevel(): number { return this._maxLevel; } protected _probability: number = 0.5; /** * The function returns the probability value. * @returns The probability value stored in the protected variable `_probability` is being returned. */ get probability(): number { return this._probability; } /** * Time Complexity: O(1) * Space Complexity: O(1) * * Get the value of the first element (the smallest element) in the Skip List. * @returns The value of the first element, or undefined if the Skip List is empty. */ get first(): V | undefined { const firstNode = this.head.forward[0]; return firstNode ? firstNode.value : undefined; } /** * Time Complexity: O(log n) * Space Complexity: O(1) * * Get the value of the last element (the largest element) in the Skip List. * @returns The value of the last element, or undefined if the Skip List is empty. */ get last(): V | undefined { let current = this.head; for (let i = this.level - 1; i >= 0; i--) { while (current.forward[i]) { current = current.forward[i]; } } return current.value; } /** * Time Complexity: O(log n) * Space Complexity: O(1) * * The add function adds a new node with a given key and value to a Skip List data structure. * @param {K} key - The key parameter represents the key of the node that needs to be added to the skip list. * @param {V} value - The "value" parameter represents the value associated with the key that is being added to the Skip * List. */ add(key: K, value: V): void { const newNode = new SkipListNode(key, value, this._randomLevel()); const update: SkipListNode<K, V>[] = 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); } } /** * Time Complexity: O(log n) * Space Complexity: O(1) * * The function `get` retrieves the value associated with a given key from a skip list data structure. * @param {K} key - The `key` parameter is the key of the element that we want to retrieve from the data structure. * @returns The method `get(key: K)` returns the value associated with the given key if it exists in the data structure, * otherwise it returns `undefined`. */ get(key: K): V | undefined { 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; } /** * Time Complexity: O(log n) * Space Complexity: O(1) * * The function checks if a key exists in a data structure. * @param {K} key - The parameter "key" is of type K, which represents the type of the key being * checked. * @returns a boolean value. */ has(key: K): boolean { return this.get(key) !== undefined; } /** * Time Complexity: O(log n) * Space Complexity: O(1) * * The `delete` function removes a node with a specific key from a Skip List data structure. * @param {K} key - The key parameter represents the key of the node that needs to be removed from the skip list. * @returns The `delete` method returns a boolean value. It returns `true` if the key was successfully removed from the * skip list, and `false` if the key was not found in the skip list. */ delete(key: K): boolean { const update: SkipListNode<K, V>[] = 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; } /** * Time Complexity: O(log n) * Space Complexity: O(1) * * Get the value of the first element in the Skip List that is greater than the given key. * @param key - the given key. * @returns The value of the first element greater than the given key, or undefined if there is no such element. */ higher(key: K): V | undefined { 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; } /** * Time Complexity: O(log n) * Space Complexity: O(1) * * Get the value of the last element in the Skip List that is less than the given key. * @param key - the given key. * @returns The value of the last element less than the given key, or undefined if there is no such element. */ lower(key: K): V | undefined { 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; } /** * Time Complexity: O(maxLevel) * Space Complexity: O(1) * * The function "_randomLevel" generates a random level based on a given probability and maximum level. * @returns the level, which is a number. */ protected _randomLevel(): number { let level = 1; while (Math.random() < this.probability && level < this.maxLevel) { level++; } return level; } }