data-structure-typed 1.33.6 → 1.33.7

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 (50) hide show
  1. package/.github/workflows/ci.yml +1 -0
  2. package/CHANGELOG.md +1 -1
  3. package/README.md +17 -24
  4. package/coverage/coverage-final.json +64 -63
  5. package/coverage/coverage-summary.json +8 -7
  6. package/dist/data-structures/binary-tree/segment-tree.js +24 -6
  7. package/dist/data-structures/binary-tree/segment-tree.js.map +1 -1
  8. package/dist/data-structures/hash/hash-map.js +306 -0
  9. package/dist/data-structures/hash/hash-map.js.map +1 -0
  10. package/dist/data-structures/hash/hash-table.js +128 -38
  11. package/dist/data-structures/hash/hash-table.js.map +1 -1
  12. package/dist/data-structures/hash/index.js +1 -0
  13. package/dist/data-structures/hash/index.js.map +1 -1
  14. package/dist/data-structures/linked-list/skip-linked-list.js +122 -5
  15. package/dist/data-structures/linked-list/skip-linked-list.js.map +1 -1
  16. package/dist/types/data-structures/hash.js +3 -0
  17. package/dist/types/data-structures/hash.js.map +1 -0
  18. package/dist/types/data-structures/index.js +1 -0
  19. package/dist/types/data-structures/index.js.map +1 -1
  20. package/docs/index.html +22 -26
  21. package/docs/modules.html +10 -4
  22. package/lib/data-structures/binary-tree/segment-tree.d.ts +4 -4
  23. package/lib/data-structures/binary-tree/segment-tree.js +30 -14
  24. package/lib/data-structures/hash/hash-map.d.ts +56 -0
  25. package/lib/data-structures/hash/hash-map.js +167 -0
  26. package/lib/data-structures/hash/hash-table.d.ts +67 -23
  27. package/lib/data-structures/hash/hash-table.js +154 -52
  28. package/lib/data-structures/hash/index.d.ts +1 -0
  29. package/lib/data-structures/hash/index.js +1 -0
  30. package/lib/data-structures/linked-list/skip-linked-list.d.ts +60 -1
  31. package/lib/data-structures/linked-list/skip-linked-list.js +136 -1
  32. package/lib/types/data-structures/hash.d.ts +1 -0
  33. package/lib/types/data-structures/hash.js +1 -0
  34. package/lib/types/data-structures/index.d.ts +1 -0
  35. package/lib/types/data-structures/index.js +1 -0
  36. package/package.json +1 -1
  37. package/src/data-structures/binary-tree/segment-tree.ts +32 -14
  38. package/src/data-structures/hash/hash-map.ts +203 -0
  39. package/src/data-structures/hash/hash-table.ts +176 -56
  40. package/src/data-structures/hash/index.ts +1 -0
  41. package/src/data-structures/linked-list/skip-linked-list.ts +166 -1
  42. package/src/types/data-structures/hash.ts +1 -0
  43. package/src/types/data-structures/index.ts +1 -0
  44. package/test/unit/data-structures/binary-tree/segment-tree.test.ts +50 -0
  45. package/test/unit/data-structures/hash/hash-map.test.ts +104 -0
  46. package/test/unit/data-structures/hash/hash-table.test.ts +97 -10
  47. package/test/unit/data-structures/linked-list/skip-list.test.ts +55 -0
  48. package/umd/bundle.min.js +1 -1
  49. package/umd/bundle.min.js.map +1 -1
  50. package/tsconfig.prod.json +0 -25
package/docs/modules.html CHANGED
@@ -49,8 +49,9 @@
49
49
  <a href="classes/DirectedVertex.html" class="tsd-index-link"><svg class="tsd-kind-icon" viewBox="0 0 24 24"><use href="#icon-128"></use></svg><span>Directed<wbr/>Vertex</span></a>
50
50
  <a href="classes/DoublyLinkedList.html" class="tsd-index-link"><svg class="tsd-kind-icon" viewBox="0 0 24 24"><use href="#icon-128"></use></svg><span>Doubly<wbr/>Linked<wbr/>List</span></a>
51
51
  <a href="classes/DoublyLinkedListNode.html" class="tsd-index-link"><svg class="tsd-kind-icon" viewBox="0 0 24 24"><use href="#icon-128"></use></svg><span>Doubly<wbr/>Linked<wbr/>List<wbr/>Node</span></a>
52
- <a href="classes/HashNode.html" class="tsd-index-link"><svg class="tsd-kind-icon" viewBox="0 0 24 24"><use href="#icon-128"></use></svg><span>Hash<wbr/>Node</span></a>
52
+ <a href="classes/HashMap.html" class="tsd-index-link"><svg class="tsd-kind-icon" viewBox="0 0 24 24"><use href="#icon-128"></use></svg><span>Hash<wbr/>Map</span></a>
53
53
  <a href="classes/HashTable.html" class="tsd-index-link"><svg class="tsd-kind-icon" viewBox="0 0 24 24"><use href="#icon-128"></use></svg><span>Hash<wbr/>Table</span></a>
54
+ <a href="classes/HashTableNode.html" class="tsd-index-link"><svg class="tsd-kind-icon" viewBox="0 0 24 24"><use href="#icon-128"></use></svg><span>Hash<wbr/>Table<wbr/>Node</span></a>
54
55
  <a href="classes/Heap.html" class="tsd-index-link"><svg class="tsd-kind-icon" viewBox="0 0 24 24"><use href="#icon-128"></use></svg><span>Heap</span></a>
55
56
  <a href="classes/HeapItem.html" class="tsd-index-link"><svg class="tsd-kind-icon" viewBox="0 0 24 24"><use href="#icon-128"></use></svg><span>Heap<wbr/>Item</span></a>
56
57
  <a href="classes/LinkedListQueue.html" class="tsd-index-link"><svg class="tsd-kind-icon" viewBox="0 0 24 24"><use href="#icon-128"></use></svg><span>Linked<wbr/>List<wbr/>Queue</span></a>
@@ -74,7 +75,8 @@
74
75
  <a href="classes/SegmentTreeNode.html" class="tsd-index-link"><svg class="tsd-kind-icon" viewBox="0 0 24 24"><use href="#icon-128"></use></svg><span>Segment<wbr/>Tree<wbr/>Node</span></a>
75
76
  <a href="classes/SinglyLinkedList.html" class="tsd-index-link"><svg class="tsd-kind-icon" viewBox="0 0 24 24"><use href="#icon-128"></use></svg><span>Singly<wbr/>Linked<wbr/>List</span></a>
76
77
  <a href="classes/SinglyLinkedListNode.html" class="tsd-index-link"><svg class="tsd-kind-icon" viewBox="0 0 24 24"><use href="#icon-128"></use></svg><span>Singly<wbr/>Linked<wbr/>List<wbr/>Node</span></a>
77
- <a href="classes/SkipLinkedList.html" class="tsd-index-link"><svg class="tsd-kind-icon" viewBox="0 0 24 24"><use href="#icon-128"></use></svg><span>Skip<wbr/>Linked<wbr/>List</span></a>
78
+ <a href="classes/SkipList.html" class="tsd-index-link"><svg class="tsd-kind-icon" viewBox="0 0 24 24"><use href="#icon-128"></use></svg><span>Skip<wbr/>List</span></a>
79
+ <a href="classes/SkipListNode.html" class="tsd-index-link"><svg class="tsd-kind-icon" viewBox="0 0 24 24"><use href="#icon-128"></use></svg><span>Skip<wbr/>List<wbr/>Node</span></a>
78
80
  <a href="classes/SplayTree.html" class="tsd-index-link"><svg class="tsd-kind-icon" viewBox="0 0 24 24"><use href="#icon-128"></use></svg><span>Splay<wbr/>Tree</span></a>
79
81
  <a href="classes/Stack.html" class="tsd-index-link"><svg class="tsd-kind-icon" viewBox="0 0 24 24"><use href="#icon-128"></use></svg><span>Stack</span></a>
80
82
  <a href="classes/TreeMap.html" class="tsd-index-link"><svg class="tsd-kind-icon" viewBox="0 0 24 24"><use href="#icon-128"></use></svg><span>Tree<wbr/>Map</span></a>
@@ -122,6 +124,7 @@
122
124
  <a href="types/Direction.html" class="tsd-index-link"><svg class="tsd-kind-icon" viewBox="0 0 24 24"><use href="#icon-4194304"></use></svg><span>Direction</span></a>
123
125
  <a href="types/DummyAny.html" class="tsd-index-link"><svg class="tsd-kind-icon" viewBox="0 0 24 24"><use href="#icon-4194304"></use></svg><span>Dummy<wbr/>Any</span></a>
124
126
  <a href="types/EdgeId.html" class="tsd-index-link"><svg class="tsd-kind-icon" viewBox="0 0 24 24"><use href="#icon-4194304"></use></svg><span>Edge<wbr/>Id</span></a>
127
+ <a href="types/HashFunction.html" class="tsd-index-link"><svg class="tsd-kind-icon" viewBox="0 0 24 24"><use href="#icon-4194304"></use></svg><span>Hash<wbr/>Function</span></a>
125
128
  <a href="types/HeapOptions.html" class="tsd-index-link"><svg class="tsd-kind-icon" viewBox="0 0 24 24"><use href="#icon-4194304"></use></svg><span>Heap<wbr/>Options</span></a>
126
129
  <a href="types/IAVLTreeNode.html" class="tsd-index-link"><svg class="tsd-kind-icon" viewBox="0 0 24 24"><use href="#icon-4194304"></use></svg><span>IAVLTree<wbr/>Node</span></a>
127
130
  <a href="types/IBSTNode.html" class="tsd-index-link"><svg class="tsd-kind-icon" viewBox="0 0 24 24"><use href="#icon-4194304"></use></svg><span>IBSTNode</span></a>
@@ -217,8 +220,9 @@
217
220
  <li><a href="classes/DirectedVertex.html"><svg class="tsd-kind-icon" viewBox="0 0 24 24"><use href="#icon-128"></use></svg><span>Directed<wbr/>Vertex</span></a></li>
218
221
  <li><a href="classes/DoublyLinkedList.html"><svg class="tsd-kind-icon" viewBox="0 0 24 24"><use href="#icon-128"></use></svg><span>Doubly<wbr/>Linked<wbr/>List</span></a></li>
219
222
  <li><a href="classes/DoublyLinkedListNode.html"><svg class="tsd-kind-icon" viewBox="0 0 24 24"><use href="#icon-128"></use></svg><span>Doubly<wbr/>Linked<wbr/>List<wbr/>Node</span></a></li>
220
- <li><a href="classes/HashNode.html"><svg class="tsd-kind-icon" viewBox="0 0 24 24"><use href="#icon-128"></use></svg><span>Hash<wbr/>Node</span></a></li>
223
+ <li><a href="classes/HashMap.html"><svg class="tsd-kind-icon" viewBox="0 0 24 24"><use href="#icon-128"></use></svg><span>Hash<wbr/>Map</span></a></li>
221
224
  <li><a href="classes/HashTable.html"><svg class="tsd-kind-icon" viewBox="0 0 24 24"><use href="#icon-128"></use></svg><span>Hash<wbr/>Table</span></a></li>
225
+ <li><a href="classes/HashTableNode.html"><svg class="tsd-kind-icon" viewBox="0 0 24 24"><use href="#icon-128"></use></svg><span>Hash<wbr/>Table<wbr/>Node</span></a></li>
222
226
  <li><a href="classes/Heap.html"><svg class="tsd-kind-icon" viewBox="0 0 24 24"><use href="#icon-128"></use></svg><span>Heap</span></a></li>
223
227
  <li><a href="classes/HeapItem.html"><svg class="tsd-kind-icon" viewBox="0 0 24 24"><use href="#icon-128"></use></svg><span>Heap<wbr/>Item</span></a></li>
224
228
  <li><a href="classes/LinkedListQueue.html"><svg class="tsd-kind-icon" viewBox="0 0 24 24"><use href="#icon-128"></use></svg><span>Linked<wbr/>List<wbr/>Queue</span></a></li>
@@ -242,7 +246,8 @@
242
246
  <li><a href="classes/SegmentTreeNode.html"><svg class="tsd-kind-icon" viewBox="0 0 24 24"><use href="#icon-128"></use></svg><span>Segment<wbr/>Tree<wbr/>Node</span></a></li>
243
247
  <li><a href="classes/SinglyLinkedList.html"><svg class="tsd-kind-icon" viewBox="0 0 24 24"><use href="#icon-128"></use></svg><span>Singly<wbr/>Linked<wbr/>List</span></a></li>
244
248
  <li><a href="classes/SinglyLinkedListNode.html"><svg class="tsd-kind-icon" viewBox="0 0 24 24"><use href="#icon-128"></use></svg><span>Singly<wbr/>Linked<wbr/>List<wbr/>Node</span></a></li>
245
- <li><a href="classes/SkipLinkedList.html"><svg class="tsd-kind-icon" viewBox="0 0 24 24"><use href="#icon-128"></use></svg><span>Skip<wbr/>Linked<wbr/>List</span></a></li>
249
+ <li><a href="classes/SkipList.html"><svg class="tsd-kind-icon" viewBox="0 0 24 24"><use href="#icon-128"></use></svg><span>Skip<wbr/>List</span></a></li>
250
+ <li><a href="classes/SkipListNode.html"><svg class="tsd-kind-icon" viewBox="0 0 24 24"><use href="#icon-128"></use></svg><span>Skip<wbr/>List<wbr/>Node</span></a></li>
246
251
  <li><a href="classes/SplayTree.html"><svg class="tsd-kind-icon" viewBox="0 0 24 24"><use href="#icon-128"></use></svg><span>Splay<wbr/>Tree</span></a></li>
247
252
  <li><a href="classes/Stack.html"><svg class="tsd-kind-icon" viewBox="0 0 24 24"><use href="#icon-128"></use></svg><span>Stack</span></a></li>
248
253
  <li><a href="classes/TreeMap.html"><svg class="tsd-kind-icon" viewBox="0 0 24 24"><use href="#icon-128"></use></svg><span>Tree<wbr/>Map</span></a></li>
@@ -284,6 +289,7 @@
284
289
  <li><a href="types/Direction.html"><svg class="tsd-kind-icon" viewBox="0 0 24 24"><use href="#icon-4194304"></use></svg><span>Direction</span></a></li>
285
290
  <li><a href="types/DummyAny.html"><svg class="tsd-kind-icon" viewBox="0 0 24 24"><use href="#icon-4194304"></use></svg><span>Dummy<wbr/>Any</span></a></li>
286
291
  <li><a href="types/EdgeId.html"><svg class="tsd-kind-icon" viewBox="0 0 24 24"><use href="#icon-4194304"></use></svg><span>Edge<wbr/>Id</span></a></li>
292
+ <li><a href="types/HashFunction.html"><svg class="tsd-kind-icon" viewBox="0 0 24 24"><use href="#icon-4194304"></use></svg><span>Hash<wbr/>Function</span></a></li>
287
293
  <li><a href="types/HeapOptions.html"><svg class="tsd-kind-icon" viewBox="0 0 24 24"><use href="#icon-4194304"></use></svg><span>Heap<wbr/>Options</span></a></li>
288
294
  <li><a href="types/IAVLTreeNode.html"><svg class="tsd-kind-icon" viewBox="0 0 24 24"><use href="#icon-4194304"></use></svg><span>IAVLTree<wbr/>Node</span></a></li>
289
295
  <li><a href="types/IBSTNode.html"><svg class="tsd-kind-icon" viewBox="0 0 24 24"><use href="#icon-4194304"></use></svg><span>IBSTNode</span></a></li>
@@ -47,12 +47,12 @@ export declare class SegmentTree {
47
47
  private _root;
48
48
  get root(): SegmentTreeNode | null;
49
49
  /**
50
- * The function builds a segment tree by recursively dividing the given range into smaller segments and creating nodes
51
- * for each segment.
50
+ * The build function creates a segment tree by recursively dividing the given range into smaller segments and assigning
51
+ * the sum of values to each segment.
52
52
  * @param {number} start - The `start` parameter represents the starting index of the segment or range for which we are
53
53
  * building the segment tree.
54
- * @param {number} end - The `end` parameter represents the ending index of the segment or range for which we are
55
- * building the segment tree.
54
+ * @param {number} end - The "end" parameter represents the ending index of the segment or range for which we want to
55
+ * build a segment tree.
56
56
  * @returns a SegmentTreeNode object.
57
57
  */
58
58
  build(start: number, end: number): SegmentTreeNode;
@@ -68,12 +68,21 @@ export class SegmentTree {
68
68
  constructor(values, start, end) {
69
69
  this._values = [];
70
70
  this._start = 0;
71
+ console.log('values.length:', values.length);
71
72
  start = start || 0;
72
73
  end = end || values.length - 1;
73
74
  this._values = values;
74
75
  this._start = start;
75
76
  this._end = end;
76
- this._root = this.build(start, end);
77
+ if (values.length > 0) {
78
+ console.log('Initializing with non-empty array');
79
+ this._root = this.build(start, end);
80
+ }
81
+ else {
82
+ console.log('Initializing with empty array');
83
+ this._root = null;
84
+ this._values = [];
85
+ }
77
86
  }
78
87
  get values() {
79
88
  return this._values;
@@ -88,15 +97,18 @@ export class SegmentTree {
88
97
  return this._root;
89
98
  }
90
99
  /**
91
- * The function builds a segment tree by recursively dividing the given range into smaller segments and creating nodes
92
- * for each segment.
100
+ * The build function creates a segment tree by recursively dividing the given range into smaller segments and assigning
101
+ * the sum of values to each segment.
93
102
  * @param {number} start - The `start` parameter represents the starting index of the segment or range for which we are
94
103
  * building the segment tree.
95
- * @param {number} end - The `end` parameter represents the ending index of the segment or range for which we are
96
- * building the segment tree.
104
+ * @param {number} end - The "end" parameter represents the ending index of the segment or range for which we want to
105
+ * build a segment tree.
97
106
  * @returns a SegmentTreeNode object.
98
107
  */
99
108
  build(start, end) {
109
+ if (start > end) {
110
+ return new SegmentTreeNode(start, end, 0);
111
+ }
100
112
  if (start === end)
101
113
  return new SegmentTreeNode(start, end, this._values[start]);
102
114
  const mid = start + Math.floor((end - start) / 2);
@@ -159,13 +171,16 @@ export class SegmentTree {
159
171
  if (!root) {
160
172
  return 0;
161
173
  }
174
+ if (indexA < 0 || indexB >= this.values.length || indexA > indexB) {
175
+ return NaN;
176
+ }
162
177
  const dfs = (cur, i, j) => {
163
- if (cur.start === i && cur.end === j) {
178
+ if (i <= cur.start && j >= cur.end) {
179
+ // The range [i, j] completely covers the current node's range [cur.start, cur.end]
164
180
  return cur.sum;
165
181
  }
166
182
  const mid = cur.start + Math.floor((cur.end - cur.start) / 2);
167
183
  if (j <= mid) {
168
- // TODO after no-non-null-assertion not ensure the logic
169
184
  if (cur.left) {
170
185
  return dfs(cur.left, i, j);
171
186
  }
@@ -174,9 +189,7 @@ export class SegmentTree {
174
189
  }
175
190
  }
176
191
  else if (i > mid) {
177
- // TODO after no-non-null-assertion not ensure the logic
178
192
  if (cur.right) {
179
- // TODO after no-non-null-assertion not ensure the logic
180
193
  return dfs(cur.right, i, j);
181
194
  }
182
195
  else {
@@ -184,13 +197,16 @@ export class SegmentTree {
184
197
  }
185
198
  }
186
199
  else {
187
- // TODO after no-non-null-assertion not ensure the logic
188
- if (cur.left && cur.right) {
189
- return dfs(cur.left, i, mid) + dfs(cur.right, mid + 1, j);
200
+ // Query both left and right subtrees
201
+ let leftSum = 0;
202
+ let rightSum = 0;
203
+ if (cur.left) {
204
+ leftSum = dfs(cur.left, i, mid);
190
205
  }
191
- else {
192
- return NaN;
206
+ if (cur.right) {
207
+ rightSum = dfs(cur.right, mid + 1, j);
193
208
  }
209
+ return leftSum + rightSum;
194
210
  }
195
211
  };
196
212
  return dfs(root, indexA, indexB);
@@ -0,0 +1,56 @@
1
+ import { HashFunction } from '../../types';
2
+ /**
3
+ * data-structure-typed
4
+ *
5
+ * @author Tyler Zeng
6
+ * @copyright Copyright (c) 2022 Tyler Zeng <zrwusa@gmail.com>
7
+ * @license MIT License
8
+ */
9
+ export declare class HashMap<K, V> {
10
+ get hashFn(): HashFunction<K>;
11
+ set hashFn(value: HashFunction<K>);
12
+ get table(): Array<Array<[K, V]>>;
13
+ set table(value: Array<Array<[K, V]>>);
14
+ get capacityMultiplier(): number;
15
+ set capacityMultiplier(value: number);
16
+ get loadFactor(): number;
17
+ set loadFactor(value: number);
18
+ get initialCapacity(): number;
19
+ set initialCapacity(value: number);
20
+ get size(): number;
21
+ set size(value: number);
22
+ private _initialCapacity;
23
+ private _loadFactor;
24
+ private _capacityMultiplier;
25
+ private _size;
26
+ private _table;
27
+ private _hashFn;
28
+ /**
29
+ * The constructor initializes the properties of a hash table, including the initial capacity, load factor, capacity
30
+ * multiplier, size, table array, and hash function.
31
+ * @param [initialCapacity=16] - The initial capacity is the initial size of the hash table. It determines the number of
32
+ * buckets or slots available for storing key-value pairs. The default value is 16.
33
+ * @param [loadFactor=0.75] - The load factor is a measure of how full the hash table can be before it is resized. It is
34
+ * a value between 0 and 1, where 1 means the hash table is completely full and 0 means it is completely empty. When the
35
+ * load factor is reached, the hash table will
36
+ * @param [hashFn] - The `hashFn` parameter is an optional parameter that represents the hash function used to calculate
37
+ * the index of a key in the hash table. If a custom hash function is not provided, a default hash function is used. The
38
+ * default hash function converts the key to a string, calculates the sum of the
39
+ */
40
+ constructor(initialCapacity?: number, loadFactor?: number, hashFn?: HashFunction<K>);
41
+ private _hash;
42
+ /**
43
+ * The `resizeTable` function resizes the table used in a hash map by creating a new table with a specified capacity and
44
+ * rehashing the key-value pairs from the old table into the new table.
45
+ * @param {number} newCapacity - The newCapacity parameter is the desired capacity for the resized table. It represents
46
+ * the number of buckets that the new table should have.
47
+ */
48
+ private resizeTable;
49
+ set(key: K, value: V): void;
50
+ get(key: K): V | undefined;
51
+ remove(key: K): void;
52
+ entries(): IterableIterator<[K, V]>;
53
+ [Symbol.iterator](): IterableIterator<[K, V]>;
54
+ clear(): void;
55
+ isEmpty(): boolean;
56
+ }
@@ -0,0 +1,167 @@
1
+ /**
2
+ * data-structure-typed
3
+ *
4
+ * @author Tyler Zeng
5
+ * @copyright Copyright (c) 2022 Tyler Zeng <zrwusa@gmail.com>
6
+ * @license MIT License
7
+ */
8
+ export class HashMap {
9
+ get hashFn() {
10
+ return this._hashFn;
11
+ }
12
+ set hashFn(value) {
13
+ this._hashFn = value;
14
+ }
15
+ get table() {
16
+ return this._table;
17
+ }
18
+ set table(value) {
19
+ this._table = value;
20
+ }
21
+ get capacityMultiplier() {
22
+ return this._capacityMultiplier;
23
+ }
24
+ set capacityMultiplier(value) {
25
+ this._capacityMultiplier = value;
26
+ }
27
+ get loadFactor() {
28
+ return this._loadFactor;
29
+ }
30
+ set loadFactor(value) {
31
+ this._loadFactor = value;
32
+ }
33
+ get initialCapacity() {
34
+ return this._initialCapacity;
35
+ }
36
+ set initialCapacity(value) {
37
+ this._initialCapacity = value;
38
+ }
39
+ get size() {
40
+ return this._size;
41
+ }
42
+ set size(value) {
43
+ this._size = value;
44
+ }
45
+ /**
46
+ * The constructor initializes the properties of a hash table, including the initial capacity, load factor, capacity
47
+ * multiplier, size, table array, and hash function.
48
+ * @param [initialCapacity=16] - The initial capacity is the initial size of the hash table. It determines the number of
49
+ * buckets or slots available for storing key-value pairs. The default value is 16.
50
+ * @param [loadFactor=0.75] - The load factor is a measure of how full the hash table can be before it is resized. It is
51
+ * a value between 0 and 1, where 1 means the hash table is completely full and 0 means it is completely empty. When the
52
+ * load factor is reached, the hash table will
53
+ * @param [hashFn] - The `hashFn` parameter is an optional parameter that represents the hash function used to calculate
54
+ * the index of a key in the hash table. If a custom hash function is not provided, a default hash function is used. The
55
+ * default hash function converts the key to a string, calculates the sum of the
56
+ */
57
+ constructor(initialCapacity = 16, loadFactor = 0.75, hashFn) {
58
+ this._initialCapacity = initialCapacity;
59
+ this._loadFactor = loadFactor;
60
+ this._capacityMultiplier = 2;
61
+ this._size = 0;
62
+ this._table = new Array(initialCapacity);
63
+ this._hashFn =
64
+ hashFn ||
65
+ ((key) => {
66
+ const strKey = String(key);
67
+ let hash = 0;
68
+ for (let i = 0; i < strKey.length; i++) {
69
+ hash += strKey.charCodeAt(i);
70
+ }
71
+ return hash % this.table.length;
72
+ });
73
+ }
74
+ _hash(key) {
75
+ return this._hashFn(key);
76
+ }
77
+ /**
78
+ * The `resizeTable` function resizes the table used in a hash map by creating a new table with a specified capacity and
79
+ * rehashing the key-value pairs from the old table into the new table.
80
+ * @param {number} newCapacity - The newCapacity parameter is the desired capacity for the resized table. It represents
81
+ * the number of buckets that the new table should have.
82
+ */
83
+ resizeTable(newCapacity) {
84
+ const newTable = new Array(newCapacity);
85
+ for (const bucket of this._table) {
86
+ // Note that this is this._table
87
+ if (bucket) {
88
+ for (const [key, value] of bucket) {
89
+ const newIndex = this._hash(key) % newCapacity;
90
+ if (!newTable[newIndex]) {
91
+ newTable[newIndex] = [];
92
+ }
93
+ newTable[newIndex].push([key, value]);
94
+ }
95
+ }
96
+ }
97
+ this._table = newTable; // Again, here is this._table
98
+ }
99
+ set(key, value) {
100
+ const loadFactor = this.size / this.table.length;
101
+ if (loadFactor >= this.loadFactor) {
102
+ this.resizeTable(this.table.length * this.capacityMultiplier);
103
+ }
104
+ const index = this._hash(key);
105
+ if (!this.table[index]) {
106
+ this.table[index] = [];
107
+ }
108
+ // Check if the key already exists in the bucket
109
+ for (let i = 0; i < this.table[index].length; i++) {
110
+ if (this.table[index][i][0] === key) {
111
+ this.table[index][i][1] = value;
112
+ return;
113
+ }
114
+ }
115
+ this.table[index].push([key, value]);
116
+ this.size++;
117
+ }
118
+ get(key) {
119
+ const index = this._hash(key);
120
+ if (!this.table[index]) {
121
+ return undefined;
122
+ }
123
+ for (const [k, v] of this.table[index]) {
124
+ if (k === key) {
125
+ return v;
126
+ }
127
+ }
128
+ return undefined;
129
+ }
130
+ remove(key) {
131
+ const index = this._hash(key);
132
+ if (!this.table[index]) {
133
+ return;
134
+ }
135
+ for (let i = 0; i < this.table[index].length; i++) {
136
+ if (this.table[index][i][0] === key) {
137
+ this.table[index].splice(i, 1);
138
+ this.size--;
139
+ // Check if the table needs to be resized down
140
+ const loadFactor = this.size / this.table.length;
141
+ if (loadFactor < this.loadFactor / this.capacityMultiplier) {
142
+ this.resizeTable(this.table.length / this.capacityMultiplier);
143
+ }
144
+ return;
145
+ }
146
+ }
147
+ }
148
+ *entries() {
149
+ for (const bucket of this.table) {
150
+ if (bucket) {
151
+ for (const [key, value] of bucket) {
152
+ yield [key, value];
153
+ }
154
+ }
155
+ }
156
+ }
157
+ [Symbol.iterator]() {
158
+ return this.entries();
159
+ }
160
+ clear() {
161
+ this.size = 0;
162
+ this.table = new Array(this.initialCapacity);
163
+ }
164
+ isEmpty() {
165
+ return this.size === 0;
166
+ }
167
+ }
@@ -5,58 +5,102 @@
5
5
  * @copyright Copyright (c) 2022 Tyler Zeng <zrwusa@gmail.com>
6
6
  * @license MIT License
7
7
  */
8
- export declare class HashNode<K, V> {
8
+ export declare class HashTableNode<K, V> {
9
9
  key: K;
10
10
  val: V;
11
- next: HashNode<K, V> | null;
11
+ next: HashTableNode<K, V> | null;
12
12
  constructor(key: K, val: V);
13
13
  }
14
+ import { HashFunction } from '../../types';
14
15
  export declare class HashTable<K, V> {
15
- get buckets(): Array<HashNode<K, V> | null>;
16
- set buckets(value: Array<HashNode<K, V> | null>);
17
- get size(): number;
18
- set size(value: number);
16
+ get hashFn(): HashFunction<K>;
17
+ set hashFn(value: HashFunction<K>);
18
+ get buckets(): Array<HashTableNode<K, V> | null>;
19
+ set buckets(value: Array<HashTableNode<K, V> | null>);
19
20
  get capacity(): number;
20
21
  set capacity(value: number);
22
+ private static readonly DEFAULT_CAPACITY;
23
+ private static readonly LOAD_FACTOR;
21
24
  private _capacity;
22
25
  private _size;
23
26
  private _buckets;
27
+ private _hashFn;
28
+ constructor(capacity?: number, hashFn?: HashFunction<K>);
29
+ /**
30
+ * The function `_defaultHashFn` calculates the hash value of a given key and returns the remainder when divided by the
31
+ * capacity of the data structure.
32
+ * @param {K} key - The `key` parameter is the input value that needs to be hashed. It can be of any type, but in this
33
+ * code snippet, it is checked whether the key is a string or an object. If it is a string, the `_murmurStringHashFn`
34
+ * function is used to
35
+ * @returns the hash value of the key modulo the capacity of the data structure.
36
+ */
37
+ protected _defaultHashFn(key: K): number;
38
+ /**
39
+ * The `_multiplicativeStringHashFn` function calculates a hash value for a given string key using the multiplicative
40
+ * string hash function.
41
+ * @param {K} key - The `key` parameter is the input value for which we want to calculate the hash. It can be of any
42
+ * type, as it is generic (`K`). The function converts the `key` to a string using the `String()` function.
43
+ * @returns a number, which is the result of the multiplicative string hash function applied to the input key.
44
+ */
45
+ protected _multiplicativeStringHashFn<K>(key: K): number;
46
+ /**
47
+ * The function `_murmurStringHashFn` calculates a hash value for a given string key using the MurmurHash algorithm.
48
+ * @param {K} key - The `key` parameter is the input value for which you want to calculate the hash. It can be of any
49
+ * type, but it will be converted to a string using the `String()` function before calculating the hash.
50
+ * @returns a number, which is the hash value calculated for the given key.
51
+ */
52
+ protected _murmurStringHashFn<K>(key: K): number;
24
53
  /**
25
- * The constructor initializes the capacity, size, and buckets of an object.
26
- * @param [capacity=1000] - The `capacity` parameter represents the maximum number of elements that the data structure
27
- * can hold. It is an optional parameter with a default value of 1000.
54
+ * The _hash function takes a key and returns a number.
55
+ * @param {K} key - The parameter "key" is of type K, which represents the type of the key that will be hashed.
56
+ * @returns The hash function is returning a number.
28
57
  */
29
- constructor(capacity?: number);
58
+ protected _hash(key: K): number;
30
59
  /**
31
- * The hash function takes a key, converts it to a string, calculates the sum of the ASCII values of its characters, and
32
- * returns the remainder when divided by the capacity of the data structure.
33
- * @param {K} key - The `key` parameter represents the key that needs to be hashed. It is of type `K`, which means it can
34
- * be any data type that can be converted to a string.
35
- * @returns The hash value of the key modulo the capacity of the data structure.
60
+ * The function calculates a hash value for a given string using the djb2 algorithm.
61
+ * @param {string} key - The `key` parameter in the `stringHash` function is a string value that represents the input for
62
+ * which we want to calculate the hash value.
63
+ * @returns a number, which is the hash value of the input string.
36
64
  */
37
- private hash;
65
+ protected _stringHash(key: string): number;
38
66
  /**
39
- * The put function adds a key-value pair to a hash table, handling collisions by chaining.
67
+ * The function `_objectHash` takes a key and returns a hash value, using a custom hash function for objects.
68
+ * @param {K} key - The parameter "key" is of type "K", which means it can be any type. It could be a string, number,
69
+ * boolean, object, or any other type of value. The purpose of the objectHash function is to generate a hash value for
70
+ * the key, which can be used for
71
+ * @returns a number, which is the hash value of the key.
72
+ */
73
+ protected _objectHash(key: K): number;
74
+ /**
75
+ * The set function adds a key-value pair to the hash table, handling collisions and resizing if necessary.
40
76
  * @param {K} key - The key parameter represents the key of the key-value pair that you want to insert into the hash
41
- * table. It is of type K, which can be any data type that can be used as a key, such as a string, number, or object.
42
- * @param {V} val - The `val` parameter represents the value associated with the key in the hash table.
43
- * @returns Nothing is being returned. The return type of the function is void, which means it does not return any value.
77
+ * table. It is of type K, which is a generic type representing the key's data type.
78
+ * @param {V} val - The parameter `val` represents the value that you want to associate with the given key in the hash
79
+ * table.
80
+ * @returns Nothing is being returned. The return type of the `put` method is `void`, which means it does not return any
81
+ * value.
44
82
  */
45
- put(key: K, val: V): void;
83
+ set(key: K, val: V): void;
46
84
  /**
47
85
  * The `get` function retrieves the value associated with a given key from a hash table.
48
- * @param {K} key - The parameter "key" represents the key of the element that we want to retrieve from the data
86
+ * @param {K} key - The `key` parameter represents the key of the element that we want to retrieve from the data
49
87
  * structure.
50
88
  * @returns The method is returning the value associated with the given key if it exists in the hash table. If the key is
51
89
  * not found, it returns `undefined`.
52
90
  */
53
91
  get(key: K): V | undefined;
54
92
  /**
55
- * The `remove` function removes a key-value pair from a hash table.
93
+ * The remove function removes a key-value pair from a hash table.
56
94
  * @param {K} key - The `key` parameter represents the key of the key-value pair that needs to be removed from the hash
57
95
  * table.
58
96
  * @returns Nothing is being returned. The `remove` method has a return type of `void`, which means it does not return
59
97
  * any value.
60
98
  */
61
99
  remove(key: K): void;
100
+ /**
101
+ * The `expand` function increases the capacity of a hash table by creating a new array of buckets with double the
102
+ * capacity and rehashing all the existing key-value pairs into the new buckets.
103
+ */
104
+ protected _expand(): void;
105
+ get size(): number;
62
106
  }