linked-list-typed 1.44.1 → 1.45.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (52) hide show
  1. package/dist/data-structures/hash/hash-map.d.ts +230 -37
  2. package/dist/data-structures/hash/hash-map.js +427 -115
  3. package/dist/types/data-structures/hash/hash-map.d.ts +15 -1
  4. package/dist/types/data-structures/hash/index.d.ts +6 -0
  5. package/dist/types/data-structures/hash/index.js +20 -0
  6. package/dist/utils/utils.d.ts +3 -0
  7. package/dist/utils/utils.js +15 -1
  8. package/package.json +2 -2
  9. package/src/data-structures/binary-tree/avl-tree.ts +7 -7
  10. package/src/data-structures/binary-tree/binary-indexed-tree.ts +3 -3
  11. package/src/data-structures/binary-tree/binary-tree.ts +39 -31
  12. package/src/data-structures/binary-tree/bst.ts +12 -8
  13. package/src/data-structures/binary-tree/rb-tree.ts +17 -6
  14. package/src/data-structures/binary-tree/segment-tree.ts +1 -1
  15. package/src/data-structures/binary-tree/tree-multimap.ts +12 -9
  16. package/src/data-structures/graph/abstract-graph.ts +46 -31
  17. package/src/data-structures/graph/directed-graph.ts +10 -5
  18. package/src/data-structures/graph/map-graph.ts +8 -8
  19. package/src/data-structures/graph/undirected-graph.ts +9 -9
  20. package/src/data-structures/hash/hash-map.ts +430 -123
  21. package/src/data-structures/hash/hash-table.ts +1 -1
  22. package/src/data-structures/hash/tree-map.ts +2 -1
  23. package/src/data-structures/hash/tree-set.ts +2 -1
  24. package/src/data-structures/heap/heap.ts +8 -5
  25. package/src/data-structures/heap/max-heap.ts +3 -3
  26. package/src/data-structures/heap/min-heap.ts +3 -3
  27. package/src/data-structures/linked-list/doubly-linked-list.ts +1 -1
  28. package/src/data-structures/linked-list/singly-linked-list.ts +1 -1
  29. package/src/data-structures/matrix/matrix.ts +2 -2
  30. package/src/data-structures/matrix/matrix2d.ts +1 -1
  31. package/src/data-structures/matrix/navigator.ts +3 -3
  32. package/src/data-structures/matrix/vector2d.ts +2 -1
  33. package/src/data-structures/priority-queue/max-priority-queue.ts +3 -3
  34. package/src/data-structures/priority-queue/min-priority-queue.ts +3 -3
  35. package/src/data-structures/priority-queue/priority-queue.ts +3 -3
  36. package/src/data-structures/queue/deque.ts +5 -4
  37. package/src/data-structures/queue/queue.ts +2 -2
  38. package/src/data-structures/tree/tree.ts +1 -1
  39. package/src/data-structures/trie/trie.ts +1 -1
  40. package/src/interfaces/binary-tree.ts +2 -2
  41. package/src/interfaces/graph.ts +1 -1
  42. package/src/types/data-structures/binary-tree/avl-tree.ts +2 -2
  43. package/src/types/data-structures/binary-tree/binary-tree.ts +1 -1
  44. package/src/types/data-structures/binary-tree/bst.ts +2 -2
  45. package/src/types/data-structures/binary-tree/rb-tree.ts +2 -2
  46. package/src/types/data-structures/binary-tree/tree-multimap.ts +2 -2
  47. package/src/types/data-structures/hash/hash-map.ts +17 -1
  48. package/src/types/data-structures/hash/index.ts +7 -0
  49. package/src/types/data-structures/matrix/navigator.ts +1 -1
  50. package/src/types/utils/utils.ts +1 -1
  51. package/src/types/utils/validate-type.ts +18 -4
  52. package/src/utils/utils.ts +16 -3
@@ -5,10 +5,10 @@
5
5
  * @copyright Copyright (c) 2022 Tyler Zeng <zrwusa@gmail.com>
6
6
  * @license MIT License
7
7
  */
8
- import {arrayRemove} from '../../utils';
9
- import {AbstractEdge, AbstractGraph, AbstractVertex} from './abstract-graph';
10
- import type {VertexKey} from '../../types';
11
- import {IGraph} from '../../interfaces';
8
+ import { arrayRemove } from '../../utils';
9
+ import { AbstractEdge, AbstractGraph, AbstractVertex } from './abstract-graph';
10
+ import type { VertexKey } from '../../types';
11
+ import { IGraph } from '../../interfaces';
12
12
 
13
13
  export class UndirectedVertex<V = any> extends AbstractVertex<V> {
14
14
  /**
@@ -43,11 +43,11 @@ export class UndirectedEdge<E = number> extends AbstractEdge<E> {
43
43
  }
44
44
 
45
45
  export class UndirectedGraph<
46
- V = any,
47
- E = any,
48
- VO extends UndirectedVertex<V> = UndirectedVertex<V>,
49
- EO extends UndirectedEdge<E> = UndirectedEdge<E>
50
- >
46
+ V = any,
47
+ E = any,
48
+ VO extends UndirectedVertex<V> = UndirectedVertex<V>,
49
+ EO extends UndirectedEdge<E> = UndirectedEdge<E>
50
+ >
51
51
  extends AbstractGraph<V, E, VO, EO>
52
52
  implements IGraph<V, E, VO, EO> {
53
53
  /**
@@ -1,5 +1,3 @@
1
- import {HashFunction} from '../../types';
2
-
3
1
  /**
4
2
  * data-structure-typed
5
3
  *
@@ -7,179 +5,488 @@ import {HashFunction} from '../../types';
7
5
  * @copyright Copyright (c) 2022 Tyler Zeng <zrwusa@gmail.com>
8
6
  * @license MIT License
9
7
  */
10
- export class HashMap<K, V> {
11
- /**
12
- * The constructor initializes the properties of a hash table, including the initial capacity, load factor, capacity
13
- * multiplier, size, table array, and hash function.
14
- * @param [initialCapacity=16] - The initial capacity is the initial size of the hash table. It determines the number of
15
- * buckets or slots available for storing key-value pairs. The default value is 16.
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
17
- * a value between 0 and 1, where 1 means the hash table is completely full and 0 means it is completely empty. When the
18
- * load factor is reached, the hash table will
19
- * @param [hashFn] - The `hashFn` parameter is an optional parameter that represents the hash function used to calculate
20
- * the index of a key in the hash table. If a custom hash function is not provided, a default hash function is used. The
21
- * default hash function converts the key to a string, calculates the sum of the
22
- */
23
- constructor(initialCapacity = 16, loadFactor = 0.75, hashFn?: HashFunction<K>) {
24
- this._initialCapacity = initialCapacity;
25
- this._loadFactor = loadFactor;
26
- this._capacityMultiplier = 2;
27
- this._size = 0;
28
- this._table = new Array(initialCapacity);
29
- this._hashFn =
30
- hashFn ||
31
- ((key: K) => {
32
- const strKey = String(key);
33
- let hash = 0;
34
- for (let i = 0; i < strKey.length; i++) {
35
- hash += strKey.charCodeAt(i);
8
+
9
+ import { isObjOrFunc, rangeCheck, throwRangeError } from '../../utils';
10
+ import { HashMapLinkedNode, HashMapOptions, IterateDirection } from '../../types';
11
+
12
+ /**
13
+ * Because the implementation of HashMap relies on JavaScript's built-in objects and arrays,
14
+ * these underlying structures have already dealt with dynamic expansion and hash collisions.
15
+ * Therefore, there is no need for additional logic to handle these issues.
16
+ */
17
+ export class HashMapIterator<K, V> {
18
+ readonly hashMap: HashMap<K, V>;
19
+ readonly iterateDirection: IterateDirection;
20
+ protected _node: HashMapLinkedNode<K, V>;
21
+ protected readonly _sentinel: HashMapLinkedNode<K, V>;
22
+
23
+ /**
24
+ * This is a constructor function for a linked list iterator in a HashMap data structure.
25
+ * @param node - The `node` parameter is a reference to a `HashMapLinkedNode` object. This object
26
+ * represents a node in a linked list used in a hash map data structure. It contains a key-value pair
27
+ * and references to the previous and next nodes in the linked list.
28
+ * @param sentinel - The `sentinel` parameter is a reference to a special node in a linked list. It
29
+ * is used to mark the beginning or end of the list and is typically used in data structures like
30
+ * hash maps or linked lists to simplify operations and boundary checks.
31
+ * @param hashMap - A HashMap object that stores key-value pairs.
32
+ * @param {IterateDirection} iterateDirection - The `iterateDirection` parameter is an optional
33
+ * parameter that specifies the direction in which the iterator should iterate over the elements of
34
+ * the HashMap. It can take one of the following values:
35
+ * @returns The constructor does not return anything. It is used to initialize the properties and
36
+ * methods of the object being created.
37
+ */
38
+ constructor(
39
+ node: HashMapLinkedNode<K, V>,
40
+ sentinel: HashMapLinkedNode<K, V>,
41
+ hashMap: HashMap<K, V>,
42
+ iterateDirection: IterateDirection = IterateDirection.DEFAULT
43
+ ) {
44
+ this._node = node;
45
+ this._sentinel = sentinel;
46
+ this.iterateDirection = iterateDirection;
47
+
48
+ if (this.iterateDirection === IterateDirection.DEFAULT) {
49
+ this.prev = function () {
50
+ if (this._node.prev === this._sentinel) {
51
+ throwRangeError();
36
52
  }
37
- return hash % this.table.length;
38
- });
53
+ this._node = this._node.prev;
54
+ return this;
55
+ };
56
+ this.next = function () {
57
+ if (this._node === this._sentinel) {
58
+ throwRangeError();
59
+ }
60
+ this._node = this._node.next;
61
+ return this;
62
+ };
63
+ } else {
64
+ this.prev = function () {
65
+ if (this._node.next === this._sentinel) {
66
+ throwRangeError();
67
+ }
68
+ this._node = this._node.next;
69
+ return this;
70
+ };
71
+ this.next = function () {
72
+ if (this._node === this._sentinel) {
73
+ throwRangeError();
74
+ }
75
+ this._node = this._node.prev;
76
+ return this;
77
+ };
78
+ }
79
+ this.hashMap = hashMap;
39
80
  }
40
81
 
41
- protected _initialCapacity: number;
82
+ /**
83
+ * The above function returns a Proxy object that allows access to the key and value of a node in a
84
+ * data structure.
85
+ * @returns The code is returning a Proxy object.
86
+ */
87
+ get current() {
88
+ if (this._node === this._sentinel) {
89
+ throwRangeError();
90
+ }
91
+
92
+ return new Proxy(<[K, V]>(<unknown>[]), {
93
+ get: (target, prop: '0' | '1') => {
94
+ if (prop === '0') return this._node.key;
95
+ else if (prop === '1') return this._node.value;
96
+ target[0] = this._node.key;
97
+ target[1] = this._node.value;
98
+ return target[prop];
99
+ },
100
+ set: (_, prop: '1', newValue: V) => {
101
+ if (prop !== '1') {
102
+ throw new TypeError(`prop should be string '1'`);
103
+ }
104
+ this._node.value = newValue;
105
+ return true;
106
+ }
107
+ });
108
+ }
42
109
 
43
- get initialCapacity(): number {
44
- return this._initialCapacity;
110
+ /**
111
+ * The function checks if a node is accessible.
112
+ * @returns a boolean value indicating whether the `_node` is not equal to the `_sentinel`.
113
+ */
114
+ isAccessible() {
115
+ return this._node !== this._sentinel;
45
116
  }
46
117
 
47
- protected _loadFactor: number;
118
+ prev() {
119
+ return this;
120
+ }
48
121
 
49
- get loadFactor(): number {
50
- return this._loadFactor;
122
+ next() {
123
+ return this;
51
124
  }
125
+ }
52
126
 
53
- protected _capacityMultiplier: number;
127
+ export class HashMap<K = any, V = any> {
128
+ readonly OBJ_KEY_INDEX = Symbol('OBJ_KEY_INDEX');
129
+ protected _nodes: HashMapLinkedNode<K, V>[] = [];
130
+ protected _orgMap: Record<string, HashMapLinkedNode<K, V>> = {};
131
+ protected _head: HashMapLinkedNode<K, V>;
132
+ protected _tail: HashMapLinkedNode<K, V>;
133
+ protected readonly _sentinel: HashMapLinkedNode<K, V>;
54
134
 
55
- get capacityMultiplier(): number {
56
- return this._capacityMultiplier;
135
+ /**
136
+ * The constructor initializes a HashMap object with an optional initial set of key-value pairs.
137
+ * @param hashMap - The `hashMap` parameter is an optional parameter of type `HashMapOptions<[K,
138
+ * V]>`. It is an array of key-value pairs, where each pair is represented as an array `[K, V]`. The
139
+ * `K` represents the type of the key and `V` represents the
140
+ */
141
+ constructor(hashMap: HashMapOptions<[K, V]> = []) {
142
+ Object.setPrototypeOf(this._orgMap, null);
143
+ this._sentinel = <HashMapLinkedNode<K, V>>{};
144
+ this._sentinel.prev = this._sentinel.next = this._head = this._tail = this._sentinel;
145
+
146
+ hashMap.forEach(el => {
147
+ this.set(el[0], el[1]);
148
+ });
57
149
  }
58
150
 
59
- protected _size: number;
151
+ protected _size = 0;
60
152
 
61
- get size(): number {
153
+ get size() {
62
154
  return this._size;
63
155
  }
64
156
 
65
- protected _table: Array<Array<[K, V]>>;
157
+ /**
158
+ * Time Complexity: O(1)
159
+ * Space Complexity: O(1)
160
+ *
161
+ * The function returns a new iterator object for a HashMap.
162
+ * @returns A new instance of the HashMapIterator class is being returned.
163
+ */
164
+ get begin() {
165
+ return new HashMapIterator<K, V>(this._head, this._sentinel, this);
166
+ }
66
167
 
67
- get table(): Array<Array<[K, V]>> {
68
- return this._table;
168
+ /**
169
+ * Time Complexity: O(1)
170
+ * Space Complexity: O(1)
171
+ *
172
+ * The function returns a new HashMapIterator object with the _sentinel value as both the start and
173
+ * end values.
174
+ * @returns A new instance of the HashMapIterator class is being returned.
175
+ */
176
+ get end() {
177
+ return new HashMapIterator<K, V>(this._sentinel, this._sentinel, this);
69
178
  }
70
179
 
71
- protected _hashFn: HashFunction<K>;
180
+ /**
181
+ * Time Complexity: O(1)
182
+ * Space Complexity: O(1)
183
+ *
184
+ * The reverseBegin function returns a new HashMapIterator object that iterates over the elements of
185
+ * a HashMap in reverse order.
186
+ * @returns A new instance of the HashMapIterator class is being returned.
187
+ */
188
+ get reverseBegin() {
189
+ return new HashMapIterator<K, V>(this._tail, this._sentinel, this, IterateDirection.REVERSE);
190
+ }
72
191
 
73
- get hashFn(): HashFunction<K> {
74
- return this._hashFn;
192
+ /**
193
+ * Time Complexity: O(1)
194
+ * Space Complexity: O(1)
195
+ *
196
+ * The reverseEnd function returns a new HashMapIterator object that iterates over the elements of a
197
+ * HashMap in reverse order.
198
+ * @returns A new instance of the HashMapIterator class is being returned.
199
+ */
200
+ get reverseEnd() {
201
+ return new HashMapIterator<K, V>(this._sentinel, this._sentinel, this, IterateDirection.REVERSE);
75
202
  }
76
203
 
77
- set(key: K, value: V): void {
78
- const loadFactor = this.size / this.table.length;
79
- if (loadFactor >= this.loadFactor) {
80
- this.resizeTable(this.table.length * this.capacityMultiplier);
81
- }
204
+ /**
205
+ * Time Complexity: O(1)
206
+ * Space Complexity: O(1)
207
+ *
208
+ * The function returns the key-value pair at the front of a data structure.
209
+ * @returns The front element of the data structure, represented as a tuple with a key (K) and a
210
+ * value (V).
211
+ */
212
+ get front() {
213
+ if (this._size === 0) return;
214
+ return <[K, V]>[this._head.key, this._head.value];
215
+ }
82
216
 
83
- const index = this._hash(key);
84
- if (!this.table[index]) {
85
- this.table[index] = [];
86
- }
217
+ /**
218
+ * Time Complexity: O(1)
219
+ * Space Complexity: O(1)
220
+ *
221
+ * The function returns the key-value pair at the end of a data structure.
222
+ * @returns The method is returning an array containing the key-value pair of the tail element in the
223
+ * data structure.
224
+ */
225
+ get back() {
226
+ if (this._size === 0) return;
227
+ return <[K, V]>[this._tail.key, this._tail.value];
228
+ }
87
229
 
88
- // Check if the key already exists in the bucket
89
- for (let i = 0; i < this.table[index].length; i++) {
90
- if (this.table[index][i][0] === key) {
91
- this.table[index][i][1] = value;
92
- return;
230
+ /**
231
+ * Time Complexity: O(1)
232
+ * Space Complexity: O(1)
233
+ *
234
+ * The `set` function adds a new key-value pair to a data structure, either using an object key or a
235
+ * string key.
236
+ * @param {K} key - The `key` parameter is the key to be set in the data structure. It can be of any
237
+ * type, but typically it is a string or symbol.
238
+ * @param {V} [value] - The `value` parameter is an optional parameter of type `V`. It represents the
239
+ * value associated with the key being set in the data structure.
240
+ * @param {boolean} isObjectKey - A boolean flag indicating whether the key is an object key or not.
241
+ * @returns the size of the data structure after the key-value pair has been set.
242
+ */
243
+ set(key: K, value?: V, isObjectKey: boolean = isObjOrFunc(key)) {
244
+ let newTail;
245
+ if (isObjectKey) {
246
+ const index = (<Record<symbol, number>>(<unknown>key))[this.OBJ_KEY_INDEX];
247
+ if (index !== undefined) {
248
+ this._nodes[<number>index].value = <V>value;
249
+ return this._size;
93
250
  }
251
+ Object.defineProperty(key, this.OBJ_KEY_INDEX, {
252
+ value: this._nodes.length,
253
+ configurable: true
254
+ });
255
+ newTail = {
256
+ key: key,
257
+ value: <V>value,
258
+ prev: this._tail,
259
+ next: this._sentinel
260
+ };
261
+ this._nodes.push(newTail);
262
+ } else {
263
+ const node = this._orgMap[<string>(<unknown>key)];
264
+ if (node) {
265
+ node.value = <V>value;
266
+ return this._size;
267
+ }
268
+ this._orgMap[<string>(<unknown>key)] = newTail = {
269
+ key: key,
270
+ value: <V>value,
271
+ prev: this._tail,
272
+ next: this._sentinel
273
+ };
94
274
  }
95
-
96
- this.table[index].push([key, value]);
97
- this._size++;
275
+ if (this._size === 0) {
276
+ this._head = newTail;
277
+ this._sentinel.next = newTail;
278
+ } else {
279
+ this._tail.next = newTail;
280
+ }
281
+ this._tail = newTail;
282
+ this._sentinel.prev = newTail;
283
+ return ++this._size;
98
284
  }
99
285
 
100
- get(key: K): V | undefined {
101
- const index = this._hash(key);
102
- if (!this.table[index]) {
103
- return undefined;
286
+ /**
287
+ * Time Complexity: O(1)
288
+ * Space Complexity: O(1)
289
+ *
290
+ * The function `get` retrieves the value associated with a given key from a map, either by using the
291
+ * key directly or by using an index stored in the key object.
292
+ * @param {K} key - The `key` parameter is the key used to retrieve a value from the map. It can be
293
+ * of any type, but typically it is a string or symbol.
294
+ * @param {boolean} isObjectKey - The `isObjectKey` parameter is a boolean flag that indicates
295
+ * whether the `key` parameter is an object key or not. If `isObjectKey` is `true`, it means that
296
+ * `key` is an object key. If `isObjectKey` is `false`, it means that `key`
297
+ * @returns The value associated with the given key is being returned. If the key is an object key,
298
+ * the value is retrieved from the `_nodes` array using the index stored in the `OBJ_KEY_INDEX`
299
+ * property of the key. If the key is a string key, the value is retrieved from the `_orgMap` object
300
+ * using the key itself. If the key is not found, `undefined` is
301
+ */
302
+ get(key: K, isObjectKey: boolean = isObjOrFunc(key)) {
303
+ if (isObjectKey) {
304
+ const index = (<Record<symbol, number>>(<unknown>key))[this.OBJ_KEY_INDEX];
305
+ return index !== undefined ? this._nodes[index].value : undefined;
104
306
  }
307
+ const node = this._orgMap[<string>(<unknown>key)];
308
+ return node ? node.value : undefined;
309
+ }
105
310
 
106
- for (const [k, v] of this.table[index]) {
107
- if (k === key) {
108
- return v;
109
- }
311
+ /**
312
+ * Time Complexity: O(n), where n is the index.
313
+ * Space Complexity: O(1)
314
+ *
315
+ * The function `getAt` retrieves the key-value pair at a specified index in a linked list.
316
+ * @param {number} index - The index parameter is a number that represents the position of the
317
+ * element we want to retrieve from the data structure.
318
+ * @returns The method `getAt(index: number)` is returning an array containing the key-value pair at
319
+ * the specified index in the data structure. The key-value pair is represented as a tuple `[K, V]`,
320
+ * where `K` is the key and `V` is the value.
321
+ */
322
+ getAt(index: number) {
323
+ rangeCheck(index, 0, this._size - 1);
324
+ let node = this._head;
325
+ while (index--) {
326
+ node = node.next;
110
327
  }
111
-
112
- return undefined;
328
+ return <[K, V]>[node.key, node.value];
113
329
  }
114
330
 
115
- delete(key: K): void {
116
- const index = this._hash(key);
117
- if (!this.table[index]) {
118
- return;
331
+ /**
332
+ * Time Complexity: O(1)
333
+ * Space Complexity: O(1)
334
+ *
335
+ * The function `getIterator` returns a new instance of `HashMapIterator` based on the provided key
336
+ * and whether it is an object key or not.
337
+ * @param {K} key - The `key` parameter is the key used to retrieve the iterator from the HashMap. It
338
+ * can be of any type, depending on how the HashMap is implemented.
339
+ * @param {boolean} [isObjectKey] - The `isObjectKey` parameter is an optional boolean parameter that
340
+ * indicates whether the `key` parameter is an object key. If `isObjectKey` is `true`, it means that
341
+ * the `key` parameter is an object and needs to be handled differently. If `isObjectKey` is `false`
342
+ * @returns a new instance of the `HashMapIterator` class.
343
+ */
344
+ getIterator(key: K, isObjectKey?: boolean) {
345
+ let node: HashMapLinkedNode<K, V>;
346
+ if (isObjectKey) {
347
+ const index = (<Record<symbol, number>>(<unknown>key))[this.OBJ_KEY_INDEX];
348
+ if (index === undefined) {
349
+ node = this._sentinel;
350
+ } else {
351
+ node = this._nodes[index];
352
+ }
353
+ } else {
354
+ node = this._orgMap[<string>(<unknown>key)] || this._sentinel;
119
355
  }
356
+ return new HashMapIterator<K, V>(node, this._sentinel, this);
357
+ }
120
358
 
121
- for (let i = 0; i < this.table[index].length; i++) {
122
- if (this.table[index][i][0] === key) {
123
- this.table[index].splice(i, 1);
124
- this._size--;
125
-
126
- // Check if the table needs to be resized down
127
- const loadFactor = this.size / this.table.length;
128
- if (loadFactor < this.loadFactor / this.capacityMultiplier) {
129
- this.resizeTable(this.table.length / this.capacityMultiplier);
130
- }
131
- return;
132
- }
359
+ /**
360
+ * Time Complexity: O(1)
361
+ * Space Complexity: O(1)
362
+ *
363
+ * The `delete` function removes a key-value pair from a map-like data structure.
364
+ * @param {K} key - The `key` parameter is the key that you want to delete from the data structure.
365
+ * It can be of any type, but typically it is a string or an object.
366
+ * @param {boolean} isObjectKey - The `isObjectKey` parameter is a boolean flag that indicates
367
+ * whether the `key` parameter is an object key or not. If `isObjectKey` is `true`, it means that the
368
+ * `key` parameter is an object key. If `isObjectKey` is `false`, it means that the
369
+ * @returns a boolean value. It returns `true` if the deletion was successful, and `false` if the key
370
+ * was not found.
371
+ */
372
+ delete(key: K, isObjectKey: boolean = isObjOrFunc(key)) {
373
+ let node;
374
+ if (isObjectKey) {
375
+ const index = (<Record<symbol, number>>(<unknown>key))[this.OBJ_KEY_INDEX];
376
+ if (index === undefined) return false;
377
+ delete (<Record<symbol, number>>(<unknown>key))[this.OBJ_KEY_INDEX];
378
+ node = this._nodes[index];
379
+ delete this._nodes[index];
380
+ } else {
381
+ node = this._orgMap[<string>(<unknown>key)];
382
+ if (node === undefined) return false;
383
+ delete this._orgMap[<string>(<unknown>key)];
133
384
  }
385
+ this._deleteNode(node);
386
+ return true;
134
387
  }
135
388
 
136
- *entries(): IterableIterator<[K, V]> {
137
- for (const bucket of this.table) {
138
- if (bucket) {
139
- for (const [key, value] of bucket) {
140
- yield [key, value];
141
- }
142
- }
389
+ /**
390
+ * Time Complexity: O(n), where n is the index.
391
+ * Space Complexity: O(1)
392
+ *
393
+ * The `deleteAt` function deletes a node at a specified index in a linked list.
394
+ * @param {number} index - The index parameter represents the position at which the node should be
395
+ * deleted in the linked list.
396
+ * @returns The size of the list after deleting the element at the specified index.
397
+ */
398
+ deleteAt(index: number) {
399
+ rangeCheck(index, 0, this._size - 1);
400
+ let node = this._head;
401
+ while (index--) {
402
+ node = node.next;
143
403
  }
404
+ this._deleteNode(node);
405
+ return this._size;
144
406
  }
145
407
 
146
- [Symbol.iterator](): IterableIterator<[K, V]> {
147
- return this.entries();
408
+ /**
409
+ * Time Complexity: O(1)
410
+ * Space Complexity: O(1)
411
+ *
412
+ * The function checks if a data structure is empty by comparing its size to zero.
413
+ * @returns The method is returning a boolean value indicating whether the size of the object is 0 or
414
+ * not.
415
+ */
416
+ isEmpty() {
417
+ return this._size === 0;
148
418
  }
149
419
 
150
- clear(): void {
420
+ /**
421
+ * Time Complexity: O(1)
422
+ * Space Complexity: O(1)
423
+ *
424
+ * The `clear` function clears all the elements in a data structure and resets its properties.
425
+ */
426
+ clear() {
427
+ // const OBJ_KEY_INDEX = this.OBJ_KEY_INDEX;
428
+ // this._nodes.forEach(el => {
429
+ // delete (<Record<symbol, number>><unknown>el.key)[OBJ_KEY_INDEX];
430
+ // });
431
+ this._nodes = [];
432
+ this._orgMap = {};
433
+ Object.setPrototypeOf(this._orgMap, null);
151
434
  this._size = 0;
152
- this._table = new Array(this.initialCapacity);
435
+ this._head = this._tail = this._sentinel.prev = this._sentinel.next = this._sentinel;
153
436
  }
154
437
 
155
- isEmpty(): boolean {
156
- return this.size === 0;
438
+ /**
439
+ * Time Complexity: O(n), where n is the number of elements in the HashMap.
440
+ * Space Complexity: O(1)
441
+ *
442
+ * The `forEach` function iterates over each element in a HashMap and executes a callback function on
443
+ * each element.
444
+ * @param callback - The callback parameter is a function that will be called for each element in the
445
+ * HashMap. It takes three arguments:
446
+ */
447
+ forEach(callback: (element: [K, V], index: number, hashMap: HashMap<K, V>) => void) {
448
+ let index = 0;
449
+ let node = this._head;
450
+ while (node !== this._sentinel) {
451
+ callback(<[K, V]>[node.key, node.value], index++, this);
452
+ node = node.next;
453
+ }
157
454
  }
158
455
 
159
- protected _hash(key: K): number {
160
- return this._hashFn(key);
456
+ /**
457
+ * Time Complexity: O(n), where n is the number of elements in the HashMap.
458
+ * Space Complexity: O(1)
459
+ *
460
+ * The above function is an iterator that yields key-value pairs from a linked list.
461
+ */
462
+ * [Symbol.iterator]() {
463
+ let node = this._head;
464
+ while (node !== this._sentinel) {
465
+ yield <[K, V]>[node.key, node.value];
466
+ node = node.next;
467
+ }
161
468
  }
162
469
 
163
470
  /**
164
- * The `resizeTable` function resizes the table used in a hash map by creating a new table with a specified capacity and
165
- * rehashing the key-value pairs from the old table into the new table.
166
- * @param {number} newCapacity - The newCapacity parameter is the desired capacity for the resized table. It represents
167
- * the number of buckets that the new table should have.
471
+ * Time Complexity: O(1)
472
+ * Space Complexity: O(1)
473
+ *
474
+ * The `_deleteNode` function removes a node from a doubly linked list and updates the head and tail
475
+ * pointers if necessary.
476
+ * @param node - The `node` parameter is an instance of the `HashMapLinkedNode` class, which
477
+ * represents a node in a linked list. It contains a key-value pair and references to the previous
478
+ * and next nodes in the list.
168
479
  */
169
- protected resizeTable(newCapacity: number): void {
170
- const newTable = new Array(newCapacity);
171
- for (const bucket of this._table) {
172
- // Note that this is this._table
173
- if (bucket) {
174
- for (const [key, value] of bucket) {
175
- const newIndex = this._hash(key) % newCapacity;
176
- if (!newTable[newIndex]) {
177
- newTable[newIndex] = [];
178
- }
179
- newTable[newIndex].push([key, value]);
180
- }
181
- }
480
+ protected _deleteNode(node: HashMapLinkedNode<K, V>) {
481
+ const { prev, next } = node;
482
+ prev.next = next;
483
+ next.prev = prev;
484
+ if (node === this._head) {
485
+ this._head = next;
486
+ }
487
+ if (node === this._tail) {
488
+ this._tail = prev;
182
489
  }
183
- this._table = newTable; // Again, here is this._table
490
+ this._size -= 1;
184
491
  }
185
492
  }
@@ -18,7 +18,7 @@ export class HashTableNode<K, V> {
18
18
  }
19
19
  }
20
20
 
21
- import {HashFunction} from '../../types';
21
+ import { HashFunction } from '../../types';
22
22
 
23
23
  export class HashTable<K, V> {
24
24
  protected static readonly DEFAULT_CAPACITY = 16;
@@ -1 +1,2 @@
1
- export class TreeMap {}
1
+ export class TreeMap {
2
+ }
@@ -1 +1,2 @@
1
- export class TreeSet {}
1
+ export class TreeSet {
2
+ }