heap-typed
Advanced tools
Comparing version 1.44.1 to 1.45.0
@@ -1,2 +0,1 @@ | ||
import { HashFunction } from '../../types'; | ||
/** | ||
@@ -9,43 +8,237 @@ * data-structure-typed | ||
*/ | ||
export declare class HashMap<K, V> { | ||
import { HashMapLinkedNode, HashMapOptions, IterateDirection } from "../../types"; | ||
/** | ||
* Because the implementation of HashMap relies on JavaScript's built-in objects and arrays, | ||
* these underlying structures have already dealt with dynamic expansion and hash collisions. | ||
* Therefore, there is no need for additional logic to handle these issues. | ||
*/ | ||
export declare class HashMapIterator<K, V> { | ||
readonly hashMap: HashMap<K, V>; | ||
protected _node: HashMapLinkedNode<K, V>; | ||
readonly iterateDirection: IterateDirection; | ||
protected readonly _sentinel: HashMapLinkedNode<K, V>; | ||
/** | ||
* The constructor initializes the properties of a hash table, including the initial capacity, load factor, capacity | ||
* multiplier, size, table array, and hash function. | ||
* @param [initialCapacity=16] - The initial capacity is the initial size of the hash table. It determines the number of | ||
* buckets or slots available for storing key-value pairs. The default value is 16. | ||
* @param [loadFactor=0.75] - The load factor is a measure of how full the hash table can be before it is resized. It is | ||
* a value between 0 and 1, where 1 means the hash table is completely full and 0 means it is completely empty. When the | ||
* load factor is reached, the hash table will | ||
* @param [hashFn] - The `hashFn` parameter is an optional parameter that represents the hash function used to calculate | ||
* the index of a key in the hash table. If a custom hash function is not provided, a default hash function is used. The | ||
* default hash function converts the key to a string, calculates the sum of the | ||
* This is a constructor function for a linked list iterator in a HashMap data structure. | ||
* @param node - The `node` parameter is a reference to a `HashMapLinkedNode` object. This object | ||
* represents a node in a linked list used in a hash map data structure. It contains a key-value pair | ||
* and references to the previous and next nodes in the linked list. | ||
* @param sentinel - The `sentinel` parameter is a reference to a special node in a linked list. It | ||
* is used to mark the beginning or end of the list and is typically used in data structures like | ||
* hash maps or linked lists to simplify operations and boundary checks. | ||
* @param hashMap - A HashMap object that stores key-value pairs. | ||
* @param {IterateDirection} iterateDirection - The `iterateDirection` parameter is an optional | ||
* parameter that specifies the direction in which the iterator should iterate over the elements of | ||
* the HashMap. It can take one of the following values: | ||
* @returns The constructor does not return anything. It is used to initialize the properties and | ||
* methods of the object being created. | ||
*/ | ||
constructor(initialCapacity?: number, loadFactor?: number, hashFn?: HashFunction<K>); | ||
protected _initialCapacity: number; | ||
get initialCapacity(): number; | ||
protected _loadFactor: number; | ||
get loadFactor(): number; | ||
protected _capacityMultiplier: number; | ||
get capacityMultiplier(): number; | ||
constructor(node: HashMapLinkedNode<K, V>, sentinel: HashMapLinkedNode<K, V>, hashMap: HashMap<K, V>, iterateDirection?: IterateDirection); | ||
/** | ||
* The above function returns a Proxy object that allows access to the key and value of a node in a | ||
* data structure. | ||
* @returns The code is returning a Proxy object. | ||
*/ | ||
get current(): [K, V]; | ||
/** | ||
* The function checks if a node is accessible. | ||
* @returns a boolean value indicating whether the `_node` is not equal to the `_sentinel`. | ||
*/ | ||
isAccessible(): boolean; | ||
prev(): this; | ||
next(): this; | ||
} | ||
export declare class HashMap<K = any, V = any> { | ||
protected _nodes: HashMapLinkedNode<K, V>[]; | ||
protected _orgMap: Record<string, HashMapLinkedNode<K, V>>; | ||
protected _head: HashMapLinkedNode<K, V>; | ||
protected _tail: HashMapLinkedNode<K, V>; | ||
protected readonly _sentinel: HashMapLinkedNode<K, V>; | ||
readonly OBJ_KEY_INDEX: symbol; | ||
protected _size: number; | ||
get size(): number; | ||
protected _table: Array<Array<[K, V]>>; | ||
get table(): Array<Array<[K, V]>>; | ||
protected _hashFn: HashFunction<K>; | ||
get hashFn(): HashFunction<K>; | ||
set(key: K, value: V): void; | ||
get(key: K): V | undefined; | ||
delete(key: K): void; | ||
entries(): IterableIterator<[K, V]>; | ||
[Symbol.iterator](): IterableIterator<[K, V]>; | ||
clear(): void; | ||
/** | ||
* The constructor initializes a HashMap object with an optional initial set of key-value pairs. | ||
* @param hashMap - The `hashMap` parameter is an optional parameter of type `HashMapOptions<[K, | ||
* V]>`. It is an array of key-value pairs, where each pair is represented as an array `[K, V]`. The | ||
* `K` represents the type of the key and `V` represents the | ||
*/ | ||
constructor(hashMap?: HashMapOptions<[K, V]>); | ||
/** | ||
* Time Complexity: O(1) | ||
* Space Complexity: O(1) | ||
* | ||
* The `set` function adds a new key-value pair to a data structure, either using an object key or a | ||
* string key. | ||
* @param {K} key - The `key` parameter is the key to be set in the data structure. It can be of any | ||
* type, but typically it is a string or symbol. | ||
* @param {V} [value] - The `value` parameter is an optional parameter of type `V`. It represents the | ||
* value associated with the key being set in the data structure. | ||
* @param {boolean} isObjectKey - A boolean flag indicating whether the key is an object key or not. | ||
* @returns the size of the data structure after the key-value pair has been set. | ||
*/ | ||
set(key: K, value?: V, isObjectKey?: boolean): number; | ||
/** | ||
* Time Complexity: O(1) | ||
* Space Complexity: O(1) | ||
* | ||
* The function `get` retrieves the value associated with a given key from a map, either by using the | ||
* key directly or by using an index stored in the key object. | ||
* @param {K} key - The `key` parameter is the key used to retrieve a value from the map. It can be | ||
* of any type, but typically it is a string or symbol. | ||
* @param {boolean} isObjectKey - The `isObjectKey` parameter is a boolean flag that indicates | ||
* whether the `key` parameter is an object key or not. If `isObjectKey` is `true`, it means that | ||
* `key` is an object key. If `isObjectKey` is `false`, it means that `key` | ||
* @returns The value associated with the given key is being returned. If the key is an object key, | ||
* the value is retrieved from the `_nodes` array using the index stored in the `OBJ_KEY_INDEX` | ||
* property of the key. If the key is a string key, the value is retrieved from the `_orgMap` object | ||
* using the key itself. If the key is not found, `undefined` is | ||
*/ | ||
get(key: K, isObjectKey?: boolean): V | undefined; | ||
/** | ||
* Time Complexity: O(n), where n is the index. | ||
* Space Complexity: O(1) | ||
* | ||
* The function `getAt` retrieves the key-value pair at a specified index in a linked list. | ||
* @param {number} index - The index parameter is a number that represents the position of the | ||
* element we want to retrieve from the data structure. | ||
* @returns The method `getAt(index: number)` is returning an array containing the key-value pair at | ||
* the specified index in the data structure. The key-value pair is represented as a tuple `[K, V]`, | ||
* where `K` is the key and `V` is the value. | ||
*/ | ||
getAt(index: number): [K, V]; | ||
/** | ||
* Time Complexity: O(1) | ||
* Space Complexity: O(1) | ||
* | ||
* The function `getIterator` returns a new instance of `HashMapIterator` based on the provided key | ||
* and whether it is an object key or not. | ||
* @param {K} key - The `key` parameter is the key used to retrieve the iterator from the HashMap. It | ||
* can be of any type, depending on how the HashMap is implemented. | ||
* @param {boolean} [isObjectKey] - The `isObjectKey` parameter is an optional boolean parameter that | ||
* indicates whether the `key` parameter is an object key. If `isObjectKey` is `true`, it means that | ||
* the `key` parameter is an object and needs to be handled differently. If `isObjectKey` is `false` | ||
* @returns a new instance of the `HashMapIterator` class. | ||
*/ | ||
getIterator(key: K, isObjectKey?: boolean): HashMapIterator<K, V>; | ||
/** | ||
* Time Complexity: O(1) | ||
* Space Complexity: O(1) | ||
* | ||
* The `delete` function removes a key-value pair from a map-like data structure. | ||
* @param {K} key - The `key` parameter is the key that you want to delete from the data structure. | ||
* It can be of any type, but typically it is a string or an object. | ||
* @param {boolean} isObjectKey - The `isObjectKey` parameter is a boolean flag that indicates | ||
* whether the `key` parameter is an object key or not. If `isObjectKey` is `true`, it means that the | ||
* `key` parameter is an object key. If `isObjectKey` is `false`, it means that the | ||
* @returns a boolean value. It returns `true` if the deletion was successful, and `false` if the key | ||
* was not found. | ||
*/ | ||
delete(key: K, isObjectKey?: boolean): boolean; | ||
/** | ||
* Time Complexity: O(n), where n is the index. | ||
* Space Complexity: O(1) | ||
* | ||
* The `deleteAt` function deletes a node at a specified index in a linked list. | ||
* @param {number} index - The index parameter represents the position at which the node should be | ||
* deleted in the linked list. | ||
* @returns The size of the list after deleting the element at the specified index. | ||
*/ | ||
deleteAt(index: number): number; | ||
/** | ||
* Time Complexity: O(1) | ||
* Space Complexity: O(1) | ||
* | ||
* The function checks if a data structure is empty by comparing its size to zero. | ||
* @returns The method is returning a boolean value indicating whether the size of the object is 0 or | ||
* not. | ||
*/ | ||
isEmpty(): boolean; | ||
protected _hash(key: K): number; | ||
/** | ||
* The `resizeTable` function resizes the table used in a hash map by creating a new table with a specified capacity and | ||
* rehashing the key-value pairs from the old table into the new table. | ||
* @param {number} newCapacity - The newCapacity parameter is the desired capacity for the resized table. It represents | ||
* the number of buckets that the new table should have. | ||
* Time Complexity: O(1) | ||
* Space Complexity: O(1) | ||
* | ||
* The `clear` function clears all the elements in a data structure and resets its properties. | ||
*/ | ||
protected resizeTable(newCapacity: number): void; | ||
clear(): void; | ||
/** | ||
* Time Complexity: O(1) | ||
* Space Complexity: O(1) | ||
* | ||
* The function returns a new iterator object for a HashMap. | ||
* @returns A new instance of the HashMapIterator class is being returned. | ||
*/ | ||
get begin(): HashMapIterator<K, V>; | ||
/** | ||
* Time Complexity: O(1) | ||
* Space Complexity: O(1) | ||
* | ||
* The function returns a new HashMapIterator object with the _sentinel value as both the start and | ||
* end values. | ||
* @returns A new instance of the HashMapIterator class is being returned. | ||
*/ | ||
get end(): HashMapIterator<K, V>; | ||
/** | ||
* Time Complexity: O(1) | ||
* Space Complexity: O(1) | ||
* | ||
* The reverseBegin function returns a new HashMapIterator object that iterates over the elements of | ||
* a HashMap in reverse order. | ||
* @returns A new instance of the HashMapIterator class is being returned. | ||
*/ | ||
get reverseBegin(): HashMapIterator<K, V>; | ||
/** | ||
* Time Complexity: O(1) | ||
* Space Complexity: O(1) | ||
* | ||
* The reverseEnd function returns a new HashMapIterator object that iterates over the elements of a | ||
* HashMap in reverse order. | ||
* @returns A new instance of the HashMapIterator class is being returned. | ||
*/ | ||
get reverseEnd(): HashMapIterator<K, V>; | ||
/** | ||
* Time Complexity: O(1) | ||
* Space Complexity: O(1) | ||
* | ||
* The function returns the key-value pair at the front of a data structure. | ||
* @returns The front element of the data structure, represented as a tuple with a key (K) and a | ||
* value (V). | ||
*/ | ||
get front(): [K, V] | undefined; | ||
/** | ||
* Time Complexity: O(1) | ||
* Space Complexity: O(1) | ||
* | ||
* The function returns the key-value pair at the end of a data structure. | ||
* @returns The method is returning an array containing the key-value pair of the tail element in the | ||
* data structure. | ||
*/ | ||
get back(): [K, V] | undefined; | ||
/** | ||
* Time Complexity: O(n), where n is the number of elements in the HashMap. | ||
* Space Complexity: O(1) | ||
* | ||
* The `forEach` function iterates over each element in a HashMap and executes a callback function on | ||
* each element. | ||
* @param callback - The callback parameter is a function that will be called for each element in the | ||
* HashMap. It takes three arguments: | ||
*/ | ||
forEach(callback: (element: [K, V], index: number, hashMap: HashMap<K, V>) => void): void; | ||
/** | ||
* Time Complexity: O(n), where n is the number of elements in the HashMap. | ||
* Space Complexity: O(1) | ||
* | ||
* The above function is an iterator that yields key-value pairs from a linked list. | ||
*/ | ||
[Symbol.iterator](): Generator<[K, V], void, unknown>; | ||
/** | ||
* Time Complexity: O(1) | ||
* Space Complexity: O(1) | ||
* | ||
* The `_deleteNode` function removes a node from a doubly linked list and updates the head and tail | ||
* pointers if necessary. | ||
* @param node - The `node` parameter is an instance of the `HashMapLinkedNode` class, which | ||
* represents a node in a linked list. It contains a key-value pair and references to the previous | ||
* and next nodes in the list. | ||
*/ | ||
protected _deleteNode(node: HashMapLinkedNode<K, V>): void; | ||
} |
"use strict"; | ||
Object.defineProperty(exports, "__esModule", { value: true }); | ||
exports.HashMap = void 0; | ||
/** | ||
@@ -11,144 +9,458 @@ * data-structure-typed | ||
*/ | ||
class HashMap { | ||
Object.defineProperty(exports, "__esModule", { value: true }); | ||
exports.HashMap = exports.HashMapIterator = void 0; | ||
const utils_1 = require("../../utils"); | ||
/** | ||
* Because the implementation of HashMap relies on JavaScript's built-in objects and arrays, | ||
* these underlying structures have already dealt with dynamic expansion and hash collisions. | ||
* Therefore, there is no need for additional logic to handle these issues. | ||
*/ | ||
class HashMapIterator { | ||
/** | ||
* The constructor initializes the properties of a hash table, including the initial capacity, load factor, capacity | ||
* multiplier, size, table array, and hash function. | ||
* @param [initialCapacity=16] - The initial capacity is the initial size of the hash table. It determines the number of | ||
* buckets or slots available for storing key-value pairs. The default value is 16. | ||
* @param [loadFactor=0.75] - The load factor is a measure of how full the hash table can be before it is resized. It is | ||
* a value between 0 and 1, where 1 means the hash table is completely full and 0 means it is completely empty. When the | ||
* load factor is reached, the hash table will | ||
* @param [hashFn] - The `hashFn` parameter is an optional parameter that represents the hash function used to calculate | ||
* the index of a key in the hash table. If a custom hash function is not provided, a default hash function is used. The | ||
* default hash function converts the key to a string, calculates the sum of the | ||
* This is a constructor function for a linked list iterator in a HashMap data structure. | ||
* @param node - The `node` parameter is a reference to a `HashMapLinkedNode` object. This object | ||
* represents a node in a linked list used in a hash map data structure. It contains a key-value pair | ||
* and references to the previous and next nodes in the linked list. | ||
* @param sentinel - The `sentinel` parameter is a reference to a special node in a linked list. It | ||
* is used to mark the beginning or end of the list and is typically used in data structures like | ||
* hash maps or linked lists to simplify operations and boundary checks. | ||
* @param hashMap - A HashMap object that stores key-value pairs. | ||
* @param {IterateDirection} iterateDirection - The `iterateDirection` parameter is an optional | ||
* parameter that specifies the direction in which the iterator should iterate over the elements of | ||
* the HashMap. It can take one of the following values: | ||
* @returns The constructor does not return anything. It is used to initialize the properties and | ||
* methods of the object being created. | ||
*/ | ||
constructor(initialCapacity = 16, loadFactor = 0.75, hashFn) { | ||
this._initialCapacity = initialCapacity; | ||
this._loadFactor = loadFactor; | ||
this._capacityMultiplier = 2; | ||
this._size = 0; | ||
this._table = new Array(initialCapacity); | ||
this._hashFn = | ||
hashFn || | ||
((key) => { | ||
const strKey = String(key); | ||
let hash = 0; | ||
for (let i = 0; i < strKey.length; i++) { | ||
hash += strKey.charCodeAt(i); | ||
} | ||
return hash % this.table.length; | ||
}); | ||
constructor(node, sentinel, hashMap, iterateDirection = 0 /* IterateDirection.DEFAULT */) { | ||
this._node = node; | ||
this._sentinel = sentinel; | ||
this.iterateDirection = iterateDirection; | ||
if (this.iterateDirection === 0 /* IterateDirection.DEFAULT */) { | ||
this.prev = function () { | ||
if (this._node.prev === this._sentinel) { | ||
(0, utils_1.throwRangeError)(); | ||
} | ||
this._node = this._node.prev; | ||
return this; | ||
}; | ||
this.next = function () { | ||
if (this._node === this._sentinel) { | ||
(0, utils_1.throwRangeError)(); | ||
} | ||
this._node = this._node.next; | ||
return this; | ||
}; | ||
} | ||
else { | ||
this.prev = function () { | ||
if (this._node.next === this._sentinel) { | ||
(0, utils_1.throwRangeError)(); | ||
} | ||
this._node = this._node.next; | ||
return this; | ||
}; | ||
this.next = function () { | ||
if (this._node === this._sentinel) { | ||
(0, utils_1.throwRangeError)(); | ||
} | ||
this._node = this._node.prev; | ||
return this; | ||
}; | ||
} | ||
this.hashMap = hashMap; | ||
} | ||
get initialCapacity() { | ||
return this._initialCapacity; | ||
/** | ||
* The above function returns a Proxy object that allows access to the key and value of a node in a | ||
* data structure. | ||
* @returns The code is returning a Proxy object. | ||
*/ | ||
get current() { | ||
if (this._node === this._sentinel) { | ||
(0, utils_1.throwRangeError)(); | ||
} | ||
return new Proxy([], { | ||
get: (target, prop) => { | ||
if (prop === '0') | ||
return this._node.key; | ||
else if (prop === '1') | ||
return this._node.value; | ||
target[0] = this._node.key; | ||
target[1] = this._node.value; | ||
return target[prop]; | ||
}, | ||
set: (_, prop, newValue) => { | ||
if (prop !== '1') { | ||
throw new TypeError(`prop should be string '1'`); | ||
} | ||
this._node.value = newValue; | ||
return true; | ||
} | ||
}); | ||
} | ||
get loadFactor() { | ||
return this._loadFactor; | ||
/** | ||
* The function checks if a node is accessible. | ||
* @returns a boolean value indicating whether the `_node` is not equal to the `_sentinel`. | ||
*/ | ||
isAccessible() { | ||
return this._node !== this._sentinel; | ||
} | ||
get capacityMultiplier() { | ||
return this._capacityMultiplier; | ||
prev() { | ||
return this; | ||
} | ||
next() { | ||
return this; | ||
} | ||
} | ||
exports.HashMapIterator = HashMapIterator; | ||
class HashMap { | ||
get size() { | ||
return this._size; | ||
} | ||
get table() { | ||
return this._table; | ||
/** | ||
* The constructor initializes a HashMap object with an optional initial set of key-value pairs. | ||
* @param hashMap - The `hashMap` parameter is an optional parameter of type `HashMapOptions<[K, | ||
* V]>`. It is an array of key-value pairs, where each pair is represented as an array `[K, V]`. The | ||
* `K` represents the type of the key and `V` represents the | ||
*/ | ||
constructor(hashMap = []) { | ||
this._nodes = []; | ||
this._orgMap = {}; | ||
this.OBJ_KEY_INDEX = Symbol('OBJ_KEY_INDEX'); | ||
this._size = 0; | ||
Object.setPrototypeOf(this._orgMap, null); | ||
this._sentinel = {}; | ||
this._sentinel.prev = this._sentinel.next = this._head = this._tail = this._sentinel; | ||
hashMap.forEach(el => { | ||
this.set(el[0], el[1]); | ||
}); | ||
} | ||
get hashFn() { | ||
return this._hashFn; | ||
} | ||
set(key, value) { | ||
const loadFactor = this.size / this.table.length; | ||
if (loadFactor >= this.loadFactor) { | ||
this.resizeTable(this.table.length * this.capacityMultiplier); | ||
/** | ||
* Time Complexity: O(1) | ||
* Space Complexity: O(1) | ||
* | ||
* The `set` function adds a new key-value pair to a data structure, either using an object key or a | ||
* string key. | ||
* @param {K} key - The `key` parameter is the key to be set in the data structure. It can be of any | ||
* type, but typically it is a string or symbol. | ||
* @param {V} [value] - The `value` parameter is an optional parameter of type `V`. It represents the | ||
* value associated with the key being set in the data structure. | ||
* @param {boolean} isObjectKey - A boolean flag indicating whether the key is an object key or not. | ||
* @returns the size of the data structure after the key-value pair has been set. | ||
*/ | ||
set(key, value, isObjectKey = (0, utils_1.isObjOrFunc)(key)) { | ||
let newTail; | ||
if (isObjectKey) { | ||
const index = key[this.OBJ_KEY_INDEX]; | ||
if (index !== undefined) { | ||
this._nodes[index].value = value; | ||
return this._size; | ||
} | ||
Object.defineProperty(key, this.OBJ_KEY_INDEX, { | ||
value: this._nodes.length, | ||
configurable: true | ||
}); | ||
newTail = { | ||
key: key, | ||
value: value, | ||
prev: this._tail, | ||
next: this._sentinel | ||
}; | ||
this._nodes.push(newTail); | ||
} | ||
const index = this._hash(key); | ||
if (!this.table[index]) { | ||
this.table[index] = []; | ||
} | ||
// Check if the key already exists in the bucket | ||
for (let i = 0; i < this.table[index].length; i++) { | ||
if (this.table[index][i][0] === key) { | ||
this.table[index][i][1] = value; | ||
return; | ||
else { | ||
const node = this._orgMap[key]; | ||
if (node) { | ||
node.value = value; | ||
return this._size; | ||
} | ||
this._orgMap[key] = newTail = { | ||
key: key, | ||
value: value, | ||
prev: this._tail, | ||
next: this._sentinel | ||
}; | ||
} | ||
this.table[index].push([key, value]); | ||
this._size++; | ||
if (this._size === 0) { | ||
this._head = newTail; | ||
this._sentinel.next = newTail; | ||
} | ||
else { | ||
this._tail.next = newTail; | ||
} | ||
this._tail = newTail; | ||
this._sentinel.prev = newTail; | ||
return ++this._size; | ||
} | ||
get(key) { | ||
const index = this._hash(key); | ||
if (!this.table[index]) { | ||
return undefined; | ||
/** | ||
* Time Complexity: O(1) | ||
* Space Complexity: O(1) | ||
* | ||
* The function `get` retrieves the value associated with a given key from a map, either by using the | ||
* key directly or by using an index stored in the key object. | ||
* @param {K} key - The `key` parameter is the key used to retrieve a value from the map. It can be | ||
* of any type, but typically it is a string or symbol. | ||
* @param {boolean} isObjectKey - The `isObjectKey` parameter is a boolean flag that indicates | ||
* whether the `key` parameter is an object key or not. If `isObjectKey` is `true`, it means that | ||
* `key` is an object key. If `isObjectKey` is `false`, it means that `key` | ||
* @returns The value associated with the given key is being returned. If the key is an object key, | ||
* the value is retrieved from the `_nodes` array using the index stored in the `OBJ_KEY_INDEX` | ||
* property of the key. If the key is a string key, the value is retrieved from the `_orgMap` object | ||
* using the key itself. If the key is not found, `undefined` is | ||
*/ | ||
get(key, isObjectKey = (0, utils_1.isObjOrFunc)(key)) { | ||
if (isObjectKey) { | ||
const index = key[this.OBJ_KEY_INDEX]; | ||
return index !== undefined ? this._nodes[index].value : undefined; | ||
} | ||
for (const [k, v] of this.table[index]) { | ||
if (k === key) { | ||
return v; | ||
const node = this._orgMap[key]; | ||
return node ? node.value : undefined; | ||
} | ||
/** | ||
* Time Complexity: O(n), where n is the index. | ||
* Space Complexity: O(1) | ||
* | ||
* The function `getAt` retrieves the key-value pair at a specified index in a linked list. | ||
* @param {number} index - The index parameter is a number that represents the position of the | ||
* element we want to retrieve from the data structure. | ||
* @returns The method `getAt(index: number)` is returning an array containing the key-value pair at | ||
* the specified index in the data structure. The key-value pair is represented as a tuple `[K, V]`, | ||
* where `K` is the key and `V` is the value. | ||
*/ | ||
getAt(index) { | ||
(0, utils_1.rangeCheck)(index, 0, this._size - 1); | ||
let node = this._head; | ||
while (index--) { | ||
node = node.next; | ||
} | ||
return [node.key, node.value]; | ||
} | ||
/** | ||
* Time Complexity: O(1) | ||
* Space Complexity: O(1) | ||
* | ||
* The function `getIterator` returns a new instance of `HashMapIterator` based on the provided key | ||
* and whether it is an object key or not. | ||
* @param {K} key - The `key` parameter is the key used to retrieve the iterator from the HashMap. It | ||
* can be of any type, depending on how the HashMap is implemented. | ||
* @param {boolean} [isObjectKey] - The `isObjectKey` parameter is an optional boolean parameter that | ||
* indicates whether the `key` parameter is an object key. If `isObjectKey` is `true`, it means that | ||
* the `key` parameter is an object and needs to be handled differently. If `isObjectKey` is `false` | ||
* @returns a new instance of the `HashMapIterator` class. | ||
*/ | ||
getIterator(key, isObjectKey) { | ||
let node; | ||
if (isObjectKey) { | ||
const index = key[this.OBJ_KEY_INDEX]; | ||
if (index === undefined) { | ||
node = this._sentinel; | ||
} | ||
else { | ||
node = this._nodes[index]; | ||
} | ||
} | ||
return undefined; | ||
else { | ||
node = this._orgMap[key] || this._sentinel; | ||
} | ||
return new HashMapIterator(node, this._sentinel, this); | ||
} | ||
delete(key) { | ||
const index = this._hash(key); | ||
if (!this.table[index]) { | ||
return; | ||
/** | ||
* Time Complexity: O(1) | ||
* Space Complexity: O(1) | ||
* | ||
* The `delete` function removes a key-value pair from a map-like data structure. | ||
* @param {K} key - The `key` parameter is the key that you want to delete from the data structure. | ||
* It can be of any type, but typically it is a string or an object. | ||
* @param {boolean} isObjectKey - The `isObjectKey` parameter is a boolean flag that indicates | ||
* whether the `key` parameter is an object key or not. If `isObjectKey` is `true`, it means that the | ||
* `key` parameter is an object key. If `isObjectKey` is `false`, it means that the | ||
* @returns a boolean value. It returns `true` if the deletion was successful, and `false` if the key | ||
* was not found. | ||
*/ | ||
delete(key, isObjectKey = (0, utils_1.isObjOrFunc)(key)) { | ||
let node; | ||
if (isObjectKey) { | ||
const index = key[this.OBJ_KEY_INDEX]; | ||
if (index === undefined) | ||
return false; | ||
delete key[this.OBJ_KEY_INDEX]; | ||
node = this._nodes[index]; | ||
delete this._nodes[index]; | ||
} | ||
for (let i = 0; i < this.table[index].length; i++) { | ||
if (this.table[index][i][0] === key) { | ||
this.table[index].splice(i, 1); | ||
this._size--; | ||
// Check if the table needs to be resized down | ||
const loadFactor = this.size / this.table.length; | ||
if (loadFactor < this.loadFactor / this.capacityMultiplier) { | ||
this.resizeTable(this.table.length / this.capacityMultiplier); | ||
} | ||
return; | ||
} | ||
else { | ||
node = this._orgMap[key]; | ||
if (node === undefined) | ||
return false; | ||
delete this._orgMap[key]; | ||
} | ||
this._deleteNode(node); | ||
return true; | ||
} | ||
*entries() { | ||
for (const bucket of this.table) { | ||
if (bucket) { | ||
for (const [key, value] of bucket) { | ||
yield [key, value]; | ||
} | ||
} | ||
/** | ||
* Time Complexity: O(n), where n is the index. | ||
* Space Complexity: O(1) | ||
* | ||
* The `deleteAt` function deletes a node at a specified index in a linked list. | ||
* @param {number} index - The index parameter represents the position at which the node should be | ||
* deleted in the linked list. | ||
* @returns The size of the list after deleting the element at the specified index. | ||
*/ | ||
deleteAt(index) { | ||
(0, utils_1.rangeCheck)(index, 0, this._size - 1); | ||
let node = this._head; | ||
while (index--) { | ||
node = node.next; | ||
} | ||
this._deleteNode(node); | ||
return this._size; | ||
} | ||
[Symbol.iterator]() { | ||
return this.entries(); | ||
/** | ||
* Time Complexity: O(1) | ||
* Space Complexity: O(1) | ||
* | ||
* The function checks if a data structure is empty by comparing its size to zero. | ||
* @returns The method is returning a boolean value indicating whether the size of the object is 0 or | ||
* not. | ||
*/ | ||
isEmpty() { | ||
return this._size === 0; | ||
} | ||
/** | ||
* Time Complexity: O(1) | ||
* Space Complexity: O(1) | ||
* | ||
* The `clear` function clears all the elements in a data structure and resets its properties. | ||
*/ | ||
clear() { | ||
// const OBJ_KEY_INDEX = this.OBJ_KEY_INDEX; | ||
// this._nodes.forEach(el => { | ||
// delete (<Record<symbol, number>><unknown>el.key)[OBJ_KEY_INDEX]; | ||
// }); | ||
this._nodes = []; | ||
this._orgMap = {}; | ||
Object.setPrototypeOf(this._orgMap, null); | ||
this._size = 0; | ||
this._table = new Array(this.initialCapacity); | ||
this._head = this._tail = this._sentinel.prev = this._sentinel.next = this._sentinel; | ||
} | ||
isEmpty() { | ||
return this.size === 0; | ||
/** | ||
* Time Complexity: O(1) | ||
* Space Complexity: O(1) | ||
* | ||
* The function returns a new iterator object for a HashMap. | ||
* @returns A new instance of the HashMapIterator class is being returned. | ||
*/ | ||
get begin() { | ||
return new HashMapIterator(this._head, this._sentinel, this); | ||
} | ||
_hash(key) { | ||
return this._hashFn(key); | ||
/** | ||
* Time Complexity: O(1) | ||
* Space Complexity: O(1) | ||
* | ||
* The function returns a new HashMapIterator object with the _sentinel value as both the start and | ||
* end values. | ||
* @returns A new instance of the HashMapIterator class is being returned. | ||
*/ | ||
get end() { | ||
return new HashMapIterator(this._sentinel, this._sentinel, this); | ||
} | ||
/** | ||
* The `resizeTable` function resizes the table used in a hash map by creating a new table with a specified capacity and | ||
* rehashing the key-value pairs from the old table into the new table. | ||
* @param {number} newCapacity - The newCapacity parameter is the desired capacity for the resized table. It represents | ||
* the number of buckets that the new table should have. | ||
* Time Complexity: O(1) | ||
* Space Complexity: O(1) | ||
* | ||
* The reverseBegin function returns a new HashMapIterator object that iterates over the elements of | ||
* a HashMap in reverse order. | ||
* @returns A new instance of the HashMapIterator class is being returned. | ||
*/ | ||
resizeTable(newCapacity) { | ||
const newTable = new Array(newCapacity); | ||
for (const bucket of this._table) { | ||
// Note that this is this._table | ||
if (bucket) { | ||
for (const [key, value] of bucket) { | ||
const newIndex = this._hash(key) % newCapacity; | ||
if (!newTable[newIndex]) { | ||
newTable[newIndex] = []; | ||
} | ||
newTable[newIndex].push([key, value]); | ||
} | ||
} | ||
get reverseBegin() { | ||
return new HashMapIterator(this._tail, this._sentinel, this, 1 /* IterateDirection.REVERSE */); | ||
} | ||
/** | ||
* Time Complexity: O(1) | ||
* Space Complexity: O(1) | ||
* | ||
* The reverseEnd function returns a new HashMapIterator object that iterates over the elements of a | ||
* HashMap in reverse order. | ||
* @returns A new instance of the HashMapIterator class is being returned. | ||
*/ | ||
get reverseEnd() { | ||
return new HashMapIterator(this._sentinel, this._sentinel, this, 1 /* IterateDirection.REVERSE */); | ||
} | ||
/** | ||
* Time Complexity: O(1) | ||
* Space Complexity: O(1) | ||
* | ||
* The function returns the key-value pair at the front of a data structure. | ||
* @returns The front element of the data structure, represented as a tuple with a key (K) and a | ||
* value (V). | ||
*/ | ||
get front() { | ||
if (this._size === 0) | ||
return; | ||
return [this._head.key, this._head.value]; | ||
} | ||
/** | ||
* Time Complexity: O(1) | ||
* Space Complexity: O(1) | ||
* | ||
* The function returns the key-value pair at the end of a data structure. | ||
* @returns The method is returning an array containing the key-value pair of the tail element in the | ||
* data structure. | ||
*/ | ||
get back() { | ||
if (this._size === 0) | ||
return; | ||
return [this._tail.key, this._tail.value]; | ||
} | ||
/** | ||
* Time Complexity: O(n), where n is the number of elements in the HashMap. | ||
* Space Complexity: O(1) | ||
* | ||
* The `forEach` function iterates over each element in a HashMap and executes a callback function on | ||
* each element. | ||
* @param callback - The callback parameter is a function that will be called for each element in the | ||
* HashMap. It takes three arguments: | ||
*/ | ||
forEach(callback) { | ||
let index = 0; | ||
let node = this._head; | ||
while (node !== this._sentinel) { | ||
callback([node.key, node.value], index++, this); | ||
node = node.next; | ||
} | ||
this._table = newTable; // Again, here is this._table | ||
} | ||
/** | ||
* Time Complexity: O(n), where n is the number of elements in the HashMap. | ||
* Space Complexity: O(1) | ||
* | ||
* The above function is an iterator that yields key-value pairs from a linked list. | ||
*/ | ||
*[Symbol.iterator]() { | ||
let node = this._head; | ||
while (node !== this._sentinel) { | ||
yield [node.key, node.value]; | ||
node = node.next; | ||
} | ||
} | ||
/** | ||
* Time Complexity: O(1) | ||
* Space Complexity: O(1) | ||
* | ||
* The `_deleteNode` function removes a node from a doubly linked list and updates the head and tail | ||
* pointers if necessary. | ||
* @param node - The `node` parameter is an instance of the `HashMapLinkedNode` class, which | ||
* represents a node in a linked list. It contains a key-value pair and references to the previous | ||
* and next nodes in the list. | ||
*/ | ||
_deleteNode(node) { | ||
const { prev, next } = node; | ||
prev.next = next; | ||
next.prev = prev; | ||
if (node === this._head) { | ||
this._head = next; | ||
} | ||
if (node === this._tail) { | ||
this._tail = prev; | ||
} | ||
this._size -= 1; | ||
} | ||
} | ||
exports.HashMap = HashMap; |
@@ -1,1 +0,15 @@ | ||
export {}; | ||
export declare const enum IterateDirection { | ||
DEFAULT = 0, | ||
REVERSE = 1 | ||
} | ||
export type HashMapOptions<T> = { | ||
sizeFunction?: number | (() => number); | ||
fixedLength?: number; | ||
forEach: (callback: (el: T) => void) => void; | ||
}; | ||
export type HashMapLinkedNode<K, V> = { | ||
key: K; | ||
value: V; | ||
next: HashMapLinkedNode<K, V>; | ||
prev: HashMapLinkedNode<K, V>; | ||
}; |
@@ -0,1 +1,7 @@ | ||
export * from './coordinate-map'; | ||
export * from './coordinate-set'; | ||
export * from './hash-map'; | ||
export * from './hash-table'; | ||
export * from './tree-map'; | ||
export * from './tree-set'; | ||
export type HashFunction<K> = (key: K) => number; |
"use strict"; | ||
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) { | ||
if (k2 === undefined) k2 = k; | ||
var desc = Object.getOwnPropertyDescriptor(m, k); | ||
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) { | ||
desc = { enumerable: true, get: function() { return m[k]; } }; | ||
} | ||
Object.defineProperty(o, k2, desc); | ||
}) : (function(o, m, k, k2) { | ||
if (k2 === undefined) k2 = k; | ||
o[k2] = m[k]; | ||
})); | ||
var __exportStar = (this && this.__exportStar) || function(m, exports) { | ||
for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p); | ||
}; | ||
Object.defineProperty(exports, "__esModule", { value: true }); | ||
__exportStar(require("./coordinate-map"), exports); | ||
__exportStar(require("./coordinate-set"), exports); | ||
__exportStar(require("./hash-map"), exports); | ||
__exportStar(require("./hash-table"), exports); | ||
__exportStar(require("./tree-map"), exports); | ||
__exportStar(require("./tree-set"), exports); |
@@ -21,1 +21,4 @@ /** | ||
export declare const getMSB: (value: number) => number; | ||
export declare const rangeCheck: (index: number, min: number, max: number, message?: string) => void; | ||
export declare const throwRangeError: (message?: string) => void; | ||
export declare const isObjOrFunc: (input: unknown) => input is Record<string, unknown> | ((...args: any[]) => any); |
@@ -12,3 +12,3 @@ "use strict"; | ||
Object.defineProperty(exports, "__esModule", { value: true }); | ||
exports.getMSB = exports.trampolineAsync = exports.trampoline = exports.toThunk = exports.isThunk = exports.THUNK_SYMBOL = exports.arrayRemove = exports.uuidV4 = void 0; | ||
exports.isObjOrFunc = exports.throwRangeError = exports.rangeCheck = exports.getMSB = exports.trampolineAsync = exports.trampoline = exports.toThunk = exports.isThunk = exports.THUNK_SYMBOL = exports.arrayRemove = exports.uuidV4 = void 0; | ||
const uuidV4 = function () { | ||
@@ -75,1 +75,15 @@ return 'xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx'.replace(/[x]/g, function (c) { | ||
exports.getMSB = getMSB; | ||
const rangeCheck = (index, min, max, message = 'Index out of bounds.') => { | ||
if (index < min || index > max) | ||
throw new RangeError(message); | ||
}; | ||
exports.rangeCheck = rangeCheck; | ||
const throwRangeError = (message = 'The value is off-limits.') => { | ||
throw new RangeError(message); | ||
}; | ||
exports.throwRangeError = throwRangeError; | ||
const isObjOrFunc = (input) => { | ||
const inputType = typeof input; | ||
return (inputType === 'object' && input !== null) || inputType === 'function'; | ||
}; | ||
exports.isObjOrFunc = isObjOrFunc; |
{ | ||
"name": "heap-typed", | ||
"version": "1.44.1", | ||
"version": "1.45.0", | ||
"description": "Heap. Javascript & Typescript Data Structure.", | ||
@@ -134,4 +134,4 @@ "main": "dist/index.js", | ||
"dependencies": { | ||
"data-structure-typed": "^1.44.1" | ||
"data-structure-typed": "^1.45.0" | ||
} | ||
} |
@@ -1,3 +0,1 @@ | ||
import {HashFunction} from '../../types'; | ||
/** | ||
@@ -10,177 +8,486 @@ * data-structure-typed | ||
*/ | ||
export class HashMap<K, V> { | ||
import {isObjOrFunc, rangeCheck, throwRangeError} from "../../utils"; | ||
import {HashMapLinkedNode, HashMapOptions, IterateDirection} from "../../types"; | ||
/** | ||
* Because the implementation of HashMap relies on JavaScript's built-in objects and arrays, | ||
* these underlying structures have already dealt with dynamic expansion and hash collisions. | ||
* Therefore, there is no need for additional logic to handle these issues. | ||
*/ | ||
export class HashMapIterator<K, V> { | ||
readonly hashMap: HashMap<K, V>; | ||
protected _node: HashMapLinkedNode<K, V>; | ||
readonly iterateDirection: IterateDirection; | ||
protected readonly _sentinel: HashMapLinkedNode<K, V>; | ||
/** | ||
* The constructor initializes the properties of a hash table, including the initial capacity, load factor, capacity | ||
* multiplier, size, table array, and hash function. | ||
* @param [initialCapacity=16] - The initial capacity is the initial size of the hash table. It determines the number of | ||
* buckets or slots available for storing key-value pairs. The default value is 16. | ||
* @param [loadFactor=0.75] - The load factor is a measure of how full the hash table can be before it is resized. It is | ||
* a value between 0 and 1, where 1 means the hash table is completely full and 0 means it is completely empty. When the | ||
* load factor is reached, the hash table will | ||
* @param [hashFn] - The `hashFn` parameter is an optional parameter that represents the hash function used to calculate | ||
* the index of a key in the hash table. If a custom hash function is not provided, a default hash function is used. The | ||
* default hash function converts the key to a string, calculates the sum of the | ||
* This is a constructor function for a linked list iterator in a HashMap data structure. | ||
* @param node - The `node` parameter is a reference to a `HashMapLinkedNode` object. This object | ||
* represents a node in a linked list used in a hash map data structure. It contains a key-value pair | ||
* and references to the previous and next nodes in the linked list. | ||
* @param sentinel - The `sentinel` parameter is a reference to a special node in a linked list. It | ||
* is used to mark the beginning or end of the list and is typically used in data structures like | ||
* hash maps or linked lists to simplify operations and boundary checks. | ||
* @param hashMap - A HashMap object that stores key-value pairs. | ||
* @param {IterateDirection} iterateDirection - The `iterateDirection` parameter is an optional | ||
* parameter that specifies the direction in which the iterator should iterate over the elements of | ||
* the HashMap. It can take one of the following values: | ||
* @returns The constructor does not return anything. It is used to initialize the properties and | ||
* methods of the object being created. | ||
*/ | ||
constructor(initialCapacity = 16, loadFactor = 0.75, hashFn?: HashFunction<K>) { | ||
this._initialCapacity = initialCapacity; | ||
this._loadFactor = loadFactor; | ||
this._capacityMultiplier = 2; | ||
this._size = 0; | ||
this._table = new Array(initialCapacity); | ||
this._hashFn = | ||
hashFn || | ||
((key: K) => { | ||
const strKey = String(key); | ||
let hash = 0; | ||
for (let i = 0; i < strKey.length; i++) { | ||
hash += strKey.charCodeAt(i); | ||
constructor(node: HashMapLinkedNode<K, V>, sentinel: HashMapLinkedNode<K, V>, | ||
hashMap: HashMap<K, V>, iterateDirection: IterateDirection = IterateDirection.DEFAULT) { | ||
this._node = node; | ||
this._sentinel = sentinel; | ||
this.iterateDirection = iterateDirection; | ||
if (this.iterateDirection === IterateDirection.DEFAULT) { | ||
this.prev = function () { | ||
if (this._node.prev === this._sentinel) { | ||
throwRangeError(); | ||
} | ||
return hash % this.table.length; | ||
}); | ||
this._node = this._node.prev; | ||
return this; | ||
}; | ||
this.next = function () { | ||
if (this._node === this._sentinel) { | ||
throwRangeError(); | ||
} | ||
this._node = this._node.next; | ||
return this; | ||
}; | ||
} else { | ||
this.prev = function () { | ||
if (this._node.next === this._sentinel) { | ||
throwRangeError(); | ||
} | ||
this._node = this._node.next; | ||
return this; | ||
}; | ||
this.next = function () { | ||
if (this._node === this._sentinel) { | ||
throwRangeError(); | ||
} | ||
this._node = this._node.prev; | ||
return this; | ||
}; | ||
} | ||
this.hashMap = hashMap; | ||
} | ||
protected _initialCapacity: number; | ||
/** | ||
* The above function returns a Proxy object that allows access to the key and value of a node in a | ||
* data structure. | ||
* @returns The code is returning a Proxy object. | ||
*/ | ||
get current() { | ||
if (this._node === this._sentinel) { | ||
throwRangeError(); | ||
} | ||
get initialCapacity(): number { | ||
return this._initialCapacity; | ||
return new Proxy(<[K, V]><unknown>[], { | ||
get: (target, prop: '0' | '1') => { | ||
if (prop === '0') return this._node.key; | ||
else if (prop === '1') return this._node.value; | ||
target[0] = this._node.key; | ||
target[1] = this._node.value; | ||
return target[prop]; | ||
}, | ||
set: (_, prop: '1', newValue: V) => { | ||
if (prop !== '1') { | ||
throw new TypeError(`prop should be string '1'`); | ||
} | ||
this._node.value = newValue; | ||
return true; | ||
} | ||
}); | ||
} | ||
protected _loadFactor: number; | ||
get loadFactor(): number { | ||
return this._loadFactor; | ||
/** | ||
* The function checks if a node is accessible. | ||
* @returns a boolean value indicating whether the `_node` is not equal to the `_sentinel`. | ||
*/ | ||
isAccessible() { | ||
return this._node !== this._sentinel; | ||
} | ||
protected _capacityMultiplier: number; | ||
get capacityMultiplier(): number { | ||
return this._capacityMultiplier; | ||
prev() { | ||
return this; | ||
} | ||
protected _size: number; | ||
next() { | ||
return this; | ||
} | ||
} | ||
get size(): number { | ||
export class HashMap<K = any, V = any> { | ||
protected _nodes: HashMapLinkedNode<K, V>[] = []; | ||
protected _orgMap: Record<string, HashMapLinkedNode<K, V>> = {}; | ||
protected _head: HashMapLinkedNode<K, V>; | ||
protected _tail: HashMapLinkedNode<K, V>; | ||
protected readonly _sentinel: HashMapLinkedNode<K, V>; | ||
readonly OBJ_KEY_INDEX = Symbol('OBJ_KEY_INDEX'); | ||
protected _size = 0; | ||
get size() { | ||
return this._size; | ||
} | ||
protected _table: Array<Array<[K, V]>>; | ||
/** | ||
* The constructor initializes a HashMap object with an optional initial set of key-value pairs. | ||
* @param hashMap - The `hashMap` parameter is an optional parameter of type `HashMapOptions<[K, | ||
* V]>`. It is an array of key-value pairs, where each pair is represented as an array `[K, V]`. The | ||
* `K` represents the type of the key and `V` represents the | ||
*/ | ||
constructor(hashMap: HashMapOptions<[K, V]> = []) { | ||
Object.setPrototypeOf(this._orgMap, null); | ||
this._sentinel = <HashMapLinkedNode<K, V>>{}; | ||
this._sentinel.prev = this._sentinel.next = this._head = this._tail = this._sentinel; | ||
get table(): Array<Array<[K, V]>> { | ||
return this._table; | ||
hashMap.forEach(el => { | ||
this.set(el[0], el[1]); | ||
}); | ||
} | ||
protected _hashFn: HashFunction<K>; | ||
get hashFn(): HashFunction<K> { | ||
return this._hashFn; | ||
/** | ||
* Time Complexity: O(1) | ||
* Space Complexity: O(1) | ||
* | ||
* The `set` function adds a new key-value pair to a data structure, either using an object key or a | ||
* string key. | ||
* @param {K} key - The `key` parameter is the key to be set in the data structure. It can be of any | ||
* type, but typically it is a string or symbol. | ||
* @param {V} [value] - The `value` parameter is an optional parameter of type `V`. It represents the | ||
* value associated with the key being set in the data structure. | ||
* @param {boolean} isObjectKey - A boolean flag indicating whether the key is an object key or not. | ||
* @returns the size of the data structure after the key-value pair has been set. | ||
*/ | ||
set(key: K, value?: V, isObjectKey: boolean = isObjOrFunc(key)) { | ||
let newTail; | ||
if (isObjectKey) { | ||
const index = (<Record<symbol, number>><unknown>key)[this.OBJ_KEY_INDEX]; | ||
if (index !== undefined) { | ||
this._nodes[<number>index].value = <V>value; | ||
return this._size; | ||
} | ||
Object.defineProperty(key, this.OBJ_KEY_INDEX, { | ||
value: this._nodes.length, | ||
configurable: true | ||
}); | ||
newTail = { | ||
key: key, | ||
value: <V>value, | ||
prev: this._tail, | ||
next: this._sentinel | ||
}; | ||
this._nodes.push(newTail); | ||
} else { | ||
const node = this._orgMap[<string><unknown>key]; | ||
if (node) { | ||
node.value = <V>value; | ||
return this._size; | ||
} | ||
this._orgMap[<string><unknown>key] = newTail = { | ||
key: key, | ||
value: <V>value, | ||
prev: this._tail, | ||
next: this._sentinel | ||
}; | ||
} | ||
if (this._size === 0) { | ||
this._head = newTail; | ||
this._sentinel.next = newTail; | ||
} else { | ||
this._tail.next = newTail; | ||
} | ||
this._tail = newTail; | ||
this._sentinel.prev = newTail; | ||
return ++this._size; | ||
} | ||
set(key: K, value: V): void { | ||
const loadFactor = this.size / this.table.length; | ||
if (loadFactor >= this.loadFactor) { | ||
this.resizeTable(this.table.length * this.capacityMultiplier); | ||
/** | ||
* Time Complexity: O(1) | ||
* Space Complexity: O(1) | ||
* | ||
* The function `get` retrieves the value associated with a given key from a map, either by using the | ||
* key directly or by using an index stored in the key object. | ||
* @param {K} key - The `key` parameter is the key used to retrieve a value from the map. It can be | ||
* of any type, but typically it is a string or symbol. | ||
* @param {boolean} isObjectKey - The `isObjectKey` parameter is a boolean flag that indicates | ||
* whether the `key` parameter is an object key or not. If `isObjectKey` is `true`, it means that | ||
* `key` is an object key. If `isObjectKey` is `false`, it means that `key` | ||
* @returns The value associated with the given key is being returned. If the key is an object key, | ||
* the value is retrieved from the `_nodes` array using the index stored in the `OBJ_KEY_INDEX` | ||
* property of the key. If the key is a string key, the value is retrieved from the `_orgMap` object | ||
* using the key itself. If the key is not found, `undefined` is | ||
*/ | ||
get(key: K, isObjectKey: boolean = isObjOrFunc(key)) { | ||
if (isObjectKey) { | ||
const index = (<Record<symbol, number>><unknown>key)[this.OBJ_KEY_INDEX]; | ||
return index !== undefined ? this._nodes[index].value : undefined; | ||
} | ||
const node = this._orgMap[<string><unknown>key]; | ||
return node ? node.value : undefined; | ||
} | ||
const index = this._hash(key); | ||
if (!this.table[index]) { | ||
this.table[index] = []; | ||
/** | ||
* Time Complexity: O(n), where n is the index. | ||
* Space Complexity: O(1) | ||
* | ||
* The function `getAt` retrieves the key-value pair at a specified index in a linked list. | ||
* @param {number} index - The index parameter is a number that represents the position of the | ||
* element we want to retrieve from the data structure. | ||
* @returns The method `getAt(index: number)` is returning an array containing the key-value pair at | ||
* the specified index in the data structure. The key-value pair is represented as a tuple `[K, V]`, | ||
* where `K` is the key and `V` is the value. | ||
*/ | ||
getAt(index: number) { | ||
rangeCheck(index, 0, this._size - 1); | ||
let node = this._head; | ||
while (index--) { | ||
node = node.next; | ||
} | ||
return <[K, V]>[node.key, node.value]; | ||
} | ||
// Check if the key already exists in the bucket | ||
for (let i = 0; i < this.table[index].length; i++) { | ||
if (this.table[index][i][0] === key) { | ||
this.table[index][i][1] = value; | ||
return; | ||
/** | ||
* Time Complexity: O(1) | ||
* Space Complexity: O(1) | ||
* | ||
* The function `getIterator` returns a new instance of `HashMapIterator` based on the provided key | ||
* and whether it is an object key or not. | ||
* @param {K} key - The `key` parameter is the key used to retrieve the iterator from the HashMap. It | ||
* can be of any type, depending on how the HashMap is implemented. | ||
* @param {boolean} [isObjectKey] - The `isObjectKey` parameter is an optional boolean parameter that | ||
* indicates whether the `key` parameter is an object key. If `isObjectKey` is `true`, it means that | ||
* the `key` parameter is an object and needs to be handled differently. If `isObjectKey` is `false` | ||
* @returns a new instance of the `HashMapIterator` class. | ||
*/ | ||
getIterator(key: K, isObjectKey?: boolean) { | ||
let node: HashMapLinkedNode<K, V> | ||
if (isObjectKey) { | ||
const index = (<Record<symbol, number>><unknown>key)[this.OBJ_KEY_INDEX]; | ||
if (index === undefined) { | ||
node = this._sentinel | ||
} else { | ||
node = this._nodes[index]; | ||
} | ||
} else { | ||
node = this._orgMap[<string><unknown>key] || this._sentinel; | ||
} | ||
this.table[index].push([key, value]); | ||
this._size++; | ||
return new HashMapIterator<K, V>(node, this._sentinel, this); | ||
} | ||
get(key: K): V | undefined { | ||
const index = this._hash(key); | ||
if (!this.table[index]) { | ||
return undefined; | ||
/** | ||
* Time Complexity: O(1) | ||
* Space Complexity: O(1) | ||
* | ||
* The `delete` function removes a key-value pair from a map-like data structure. | ||
* @param {K} key - The `key` parameter is the key that you want to delete from the data structure. | ||
* It can be of any type, but typically it is a string or an object. | ||
* @param {boolean} isObjectKey - The `isObjectKey` parameter is a boolean flag that indicates | ||
* whether the `key` parameter is an object key or not. If `isObjectKey` is `true`, it means that the | ||
* `key` parameter is an object key. If `isObjectKey` is `false`, it means that the | ||
* @returns a boolean value. It returns `true` if the deletion was successful, and `false` if the key | ||
* was not found. | ||
*/ | ||
delete(key: K, isObjectKey: boolean = isObjOrFunc(key)) { | ||
let node; | ||
if (isObjectKey) { | ||
const index = (<Record<symbol, number>><unknown>key)[this.OBJ_KEY_INDEX]; | ||
if (index === undefined) return false; | ||
delete (<Record<symbol, number>><unknown>key)[this.OBJ_KEY_INDEX]; | ||
node = this._nodes[index]; | ||
delete this._nodes[index]; | ||
} else { | ||
node = this._orgMap[<string><unknown>key]; | ||
if (node === undefined) return false; | ||
delete this._orgMap[<string><unknown>key]; | ||
} | ||
this._deleteNode(node); | ||
return true; | ||
} | ||
for (const [k, v] of this.table[index]) { | ||
if (k === key) { | ||
return v; | ||
} | ||
/** | ||
* Time Complexity: O(n), where n is the index. | ||
* Space Complexity: O(1) | ||
* | ||
* The `deleteAt` function deletes a node at a specified index in a linked list. | ||
* @param {number} index - The index parameter represents the position at which the node should be | ||
* deleted in the linked list. | ||
* @returns The size of the list after deleting the element at the specified index. | ||
*/ | ||
deleteAt(index: number) { | ||
rangeCheck(index, 0, this._size - 1); | ||
let node = this._head; | ||
while (index--) { | ||
node = node.next; | ||
} | ||
this._deleteNode(node); | ||
return this._size; | ||
} | ||
return undefined; | ||
/** | ||
* Time Complexity: O(1) | ||
* Space Complexity: O(1) | ||
* | ||
* The function checks if a data structure is empty by comparing its size to zero. | ||
* @returns The method is returning a boolean value indicating whether the size of the object is 0 or | ||
* not. | ||
*/ | ||
isEmpty() { | ||
return this._size === 0; | ||
} | ||
delete(key: K): void { | ||
const index = this._hash(key); | ||
if (!this.table[index]) { | ||
return; | ||
} | ||
/** | ||
* Time Complexity: O(1) | ||
* Space Complexity: O(1) | ||
* | ||
* The `clear` function clears all the elements in a data structure and resets its properties. | ||
*/ | ||
clear() { | ||
// const OBJ_KEY_INDEX = this.OBJ_KEY_INDEX; | ||
// this._nodes.forEach(el => { | ||
// delete (<Record<symbol, number>><unknown>el.key)[OBJ_KEY_INDEX]; | ||
// }); | ||
this._nodes = []; | ||
this._orgMap = {}; | ||
Object.setPrototypeOf(this._orgMap, null); | ||
this._size = 0; | ||
this._head = this._tail = this._sentinel.prev = this._sentinel.next = this._sentinel; | ||
} | ||
for (let i = 0; i < this.table[index].length; i++) { | ||
if (this.table[index][i][0] === key) { | ||
this.table[index].splice(i, 1); | ||
this._size--; | ||
/** | ||
* Time Complexity: O(1) | ||
* Space Complexity: O(1) | ||
* | ||
* The function returns a new iterator object for a HashMap. | ||
* @returns A new instance of the HashMapIterator class is being returned. | ||
*/ | ||
get begin() { | ||
return new HashMapIterator<K, V>(this._head, this._sentinel, this); | ||
} | ||
// Check if the table needs to be resized down | ||
const loadFactor = this.size / this.table.length; | ||
if (loadFactor < this.loadFactor / this.capacityMultiplier) { | ||
this.resizeTable(this.table.length / this.capacityMultiplier); | ||
} | ||
return; | ||
} | ||
} | ||
/** | ||
* Time Complexity: O(1) | ||
* Space Complexity: O(1) | ||
* | ||
* The function returns a new HashMapIterator object with the _sentinel value as both the start and | ||
* end values. | ||
* @returns A new instance of the HashMapIterator class is being returned. | ||
*/ | ||
get end() { | ||
return new HashMapIterator<K, V>(this._sentinel, this._sentinel, this); | ||
} | ||
*entries(): IterableIterator<[K, V]> { | ||
for (const bucket of this.table) { | ||
if (bucket) { | ||
for (const [key, value] of bucket) { | ||
yield [key, value]; | ||
} | ||
} | ||
} | ||
/** | ||
* Time Complexity: O(1) | ||
* Space Complexity: O(1) | ||
* | ||
* The reverseBegin function returns a new HashMapIterator object that iterates over the elements of | ||
* a HashMap in reverse order. | ||
* @returns A new instance of the HashMapIterator class is being returned. | ||
*/ | ||
get reverseBegin() { | ||
return new HashMapIterator<K, V>(this._tail, this._sentinel, this, IterateDirection.REVERSE); | ||
} | ||
[Symbol.iterator](): IterableIterator<[K, V]> { | ||
return this.entries(); | ||
/** | ||
* Time Complexity: O(1) | ||
* Space Complexity: O(1) | ||
* | ||
* The reverseEnd function returns a new HashMapIterator object that iterates over the elements of a | ||
* HashMap in reverse order. | ||
* @returns A new instance of the HashMapIterator class is being returned. | ||
*/ | ||
get reverseEnd() { | ||
return new HashMapIterator<K, V>(this._sentinel, this._sentinel, this, IterateDirection.REVERSE); | ||
} | ||
clear(): void { | ||
this._size = 0; | ||
this._table = new Array(this.initialCapacity); | ||
/** | ||
* Time Complexity: O(1) | ||
* Space Complexity: O(1) | ||
* | ||
* The function returns the key-value pair at the front of a data structure. | ||
* @returns The front element of the data structure, represented as a tuple with a key (K) and a | ||
* value (V). | ||
*/ | ||
get front() { | ||
if (this._size === 0) return; | ||
return <[K, V]>[this._head.key, this._head.value]; | ||
} | ||
isEmpty(): boolean { | ||
return this.size === 0; | ||
/** | ||
* Time Complexity: O(1) | ||
* Space Complexity: O(1) | ||
* | ||
* The function returns the key-value pair at the end of a data structure. | ||
* @returns The method is returning an array containing the key-value pair of the tail element in the | ||
* data structure. | ||
*/ | ||
get back() { | ||
if (this._size === 0) return; | ||
return <[K, V]>[this._tail.key, this._tail.value]; | ||
} | ||
protected _hash(key: K): number { | ||
return this._hashFn(key); | ||
/** | ||
* Time Complexity: O(n), where n is the number of elements in the HashMap. | ||
* Space Complexity: O(1) | ||
* | ||
* The `forEach` function iterates over each element in a HashMap and executes a callback function on | ||
* each element. | ||
* @param callback - The callback parameter is a function that will be called for each element in the | ||
* HashMap. It takes three arguments: | ||
*/ | ||
forEach(callback: (element: [K, V], index: number, hashMap: HashMap<K, V>) => void) { | ||
let index = 0; | ||
let node = this._head; | ||
while (node !== this._sentinel) { | ||
callback(<[K, V]>[node.key, node.value], index++, this); | ||
node = node.next; | ||
} | ||
} | ||
/** | ||
* The `resizeTable` function resizes the table used in a hash map by creating a new table with a specified capacity and | ||
* rehashing the key-value pairs from the old table into the new table. | ||
* @param {number} newCapacity - The newCapacity parameter is the desired capacity for the resized table. It represents | ||
* the number of buckets that the new table should have. | ||
* Time Complexity: O(n), where n is the number of elements in the HashMap. | ||
* Space Complexity: O(1) | ||
* | ||
* The above function is an iterator that yields key-value pairs from a linked list. | ||
*/ | ||
protected resizeTable(newCapacity: number): void { | ||
const newTable = new Array(newCapacity); | ||
for (const bucket of this._table) { | ||
// Note that this is this._table | ||
if (bucket) { | ||
for (const [key, value] of bucket) { | ||
const newIndex = this._hash(key) % newCapacity; | ||
if (!newTable[newIndex]) { | ||
newTable[newIndex] = []; | ||
} | ||
newTable[newIndex].push([key, value]); | ||
} | ||
} | ||
* [Symbol.iterator]() { | ||
let node = this._head; | ||
while (node !== this._sentinel) { | ||
yield <[K, V]>[node.key, node.value]; | ||
node = node.next; | ||
} | ||
this._table = newTable; // Again, here is this._table | ||
} | ||
/** | ||
* Time Complexity: O(1) | ||
* Space Complexity: O(1) | ||
* | ||
* The `_deleteNode` function removes a node from a doubly linked list and updates the head and tail | ||
* pointers if necessary. | ||
* @param node - The `node` parameter is an instance of the `HashMapLinkedNode` class, which | ||
* represents a node in a linked list. It contains a key-value pair and references to the previous | ||
* and next nodes in the list. | ||
*/ | ||
protected _deleteNode(node: HashMapLinkedNode<K, V>) { | ||
const {prev, next} = node; | ||
prev.next = next; | ||
next.prev = prev; | ||
if (node === this._head) { | ||
this._head = next; | ||
} | ||
if (node === this._tail) { | ||
this._tail = prev; | ||
} | ||
this._size -= 1; | ||
} | ||
} |
@@ -1,1 +0,17 @@ | ||
export {}; | ||
export const enum IterateDirection { | ||
DEFAULT = 0, | ||
REVERSE = 1 | ||
} | ||
export type HashMapOptions<T> = { | ||
sizeFunction?: number | (() => number); | ||
fixedLength?: number; | ||
forEach: (callback: (el: T) => void) => void; | ||
} | ||
export type HashMapLinkedNode<K, V> = { | ||
key: K | ||
value: V | ||
next: HashMapLinkedNode<K, V> | ||
prev: HashMapLinkedNode<K, V> | ||
} |
@@ -0,1 +1,8 @@ | ||
export * from './coordinate-map'; | ||
export * from './coordinate-set'; | ||
export * from './hash-map'; | ||
export * from './hash-table'; | ||
export * from './tree-map'; | ||
export * from './tree-set'; | ||
export type HashFunction<K> = (key: K) => number; |
@@ -87,1 +87,14 @@ /** | ||
}; | ||
export const rangeCheck = (index: number, min: number, max: number, message = 'Index out of bounds.'): void => { | ||
if (index < min || index > max) throw new RangeError(message); | ||
} | ||
export const throwRangeError = (message = 'The value is off-limits.'): void => { | ||
throw new RangeError(message); | ||
} | ||
export const isObjOrFunc = (input: unknown): input is Record<string, unknown> | ((...args: any[]) => any) => { | ||
const inputType = typeof input; | ||
return (inputType === 'object' && input !== null) || inputType === 'function'; | ||
} |
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
1766758
32139
Updateddata-structure-typed@^1.45.0