data-structure-typed 1.33.6 → 1.33.8
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.
- package/.github/workflows/ci.yml +1 -0
- package/CHANGELOG.md +1 -1
- package/README.md +42 -38
- package/coverage/coverage-final.json +64 -63
- package/coverage/coverage-summary.json +8 -7
- package/dist/data-structures/binary-tree/segment-tree.js +24 -6
- package/dist/data-structures/binary-tree/segment-tree.js.map +1 -1
- package/dist/data-structures/hash/hash-map.js +306 -0
- package/dist/data-structures/hash/hash-map.js.map +1 -0
- package/dist/data-structures/hash/hash-table.js +128 -38
- package/dist/data-structures/hash/hash-table.js.map +1 -1
- package/dist/data-structures/hash/index.js +1 -0
- package/dist/data-structures/hash/index.js.map +1 -1
- package/dist/data-structures/linked-list/skip-linked-list.js +122 -5
- package/dist/data-structures/linked-list/skip-linked-list.js.map +1 -1
- package/dist/types/data-structures/hash.js +3 -0
- package/dist/types/data-structures/hash.js.map +1 -0
- package/dist/types/data-structures/index.js +1 -0
- package/dist/types/data-structures/index.js.map +1 -1
- package/docs/index.html +35 -37
- package/docs/modules.html +10 -4
- package/lib/data-structures/binary-tree/segment-tree.d.ts +4 -4
- package/lib/data-structures/binary-tree/segment-tree.js +30 -14
- package/lib/data-structures/hash/hash-map.d.ts +56 -0
- package/lib/data-structures/hash/hash-map.js +167 -0
- package/lib/data-structures/hash/hash-table.d.ts +67 -23
- package/lib/data-structures/hash/hash-table.js +154 -52
- package/lib/data-structures/hash/index.d.ts +1 -0
- package/lib/data-structures/hash/index.js +1 -0
- package/lib/data-structures/linked-list/skip-linked-list.d.ts +60 -1
- package/lib/data-structures/linked-list/skip-linked-list.js +136 -1
- package/lib/types/data-structures/hash.d.ts +1 -0
- package/lib/types/data-structures/hash.js +1 -0
- package/lib/types/data-structures/index.d.ts +1 -0
- package/lib/types/data-structures/index.js +1 -0
- package/package.json +22 -22
- package/src/data-structures/binary-tree/segment-tree.ts +32 -14
- package/src/data-structures/hash/hash-map.ts +203 -0
- package/src/data-structures/hash/hash-table.ts +176 -56
- package/src/data-structures/hash/index.ts +1 -0
- package/src/data-structures/linked-list/skip-linked-list.ts +166 -1
- package/src/types/data-structures/hash.ts +1 -0
- package/src/types/data-structures/index.ts +1 -0
- package/test/integration/index.html +26 -18
- package/test/unit/data-structures/binary-tree/segment-tree.test.ts +50 -0
- package/test/unit/data-structures/hash/hash-map.test.ts +104 -0
- package/test/unit/data-structures/hash/hash-table.test.ts +97 -10
- package/test/unit/data-structures/linked-list/skip-list.test.ts +55 -0
- package/umd/bundle.min.js +1 -1
- package/umd/bundle.min.js.map +1 -1
- 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/
|
|
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/
|
|
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/
|
|
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/
|
|
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
|
|
51
|
-
*
|
|
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
|
|
55
|
-
*
|
|
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
|
-
|
|
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
|
|
92
|
-
*
|
|
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
|
|
96
|
-
*
|
|
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
|
|
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
|
-
//
|
|
188
|
-
|
|
189
|
-
|
|
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
|
-
|
|
192
|
-
|
|
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
|
|
8
|
+
export declare class HashTableNode<K, V> {
|
|
9
9
|
key: K;
|
|
10
10
|
val: V;
|
|
11
|
-
next:
|
|
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
|
|
16
|
-
set
|
|
17
|
-
get
|
|
18
|
-
set
|
|
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
|
|
26
|
-
* @param
|
|
27
|
-
*
|
|
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
|
-
|
|
58
|
+
protected _hash(key: K): number;
|
|
30
59
|
/**
|
|
31
|
-
* The
|
|
32
|
-
*
|
|
33
|
-
*
|
|
34
|
-
*
|
|
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
|
-
|
|
65
|
+
protected _stringHash(key: string): number;
|
|
38
66
|
/**
|
|
39
|
-
* The
|
|
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
|
|
42
|
-
* @param {V} val - The `val`
|
|
43
|
-
*
|
|
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
|
-
|
|
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
|
|
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
|
|
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
|
}
|