data-structure-typed 1.44.1 → 1.45.0
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/CHANGELOG.md +1 -1
- package/README.md +15 -15
- package/benchmark/report.html +15 -15
- package/benchmark/report.json +121 -121
- package/dist/cjs/data-structures/hash/hash-map.d.ts +230 -37
- package/dist/cjs/data-structures/hash/hash-map.js +430 -118
- package/dist/cjs/data-structures/hash/hash-map.js.map +1 -1
- package/dist/cjs/types/data-structures/hash/hash-map.d.ts +15 -1
- package/dist/cjs/types/data-structures/hash/index.d.ts +6 -0
- package/dist/cjs/types/data-structures/hash/index.js +20 -0
- package/dist/cjs/types/data-structures/hash/index.js.map +1 -1
- package/dist/cjs/utils/utils.d.ts +3 -0
- package/dist/cjs/utils/utils.js +15 -1
- package/dist/cjs/utils/utils.js.map +1 -1
- package/dist/mjs/data-structures/hash/hash-map.d.ts +230 -37
- package/dist/mjs/data-structures/hash/hash-map.js +435 -123
- package/dist/mjs/types/data-structures/hash/hash-map.d.ts +15 -1
- package/dist/mjs/types/data-structures/hash/index.d.ts +6 -0
- package/dist/mjs/types/data-structures/hash/index.js +6 -1
- package/dist/mjs/utils/utils.d.ts +3 -0
- package/dist/mjs/utils/utils.js +11 -0
- package/dist/umd/data-structure-typed.js +532 -208
- package/dist/umd/data-structure-typed.min.js +1 -1
- package/dist/umd/data-structure-typed.min.js.map +1 -1
- package/package.json +2 -2
- package/src/data-structures/hash/hash-map.ts +432 -125
- package/src/types/data-structures/hash/hash-map.ts +17 -1
- package/src/types/data-structures/hash/index.ts +7 -0
- package/src/utils/utils.ts +13 -0
- package/test/config.ts +1 -1
- package/test/unit/data-structures/binary-tree/avl-tree.test.ts +2 -2
- package/test/unit/data-structures/binary-tree/bst.test.ts +6 -6
- package/test/unit/data-structures/binary-tree/overall.test.ts +1 -1
- package/test/unit/data-structures/binary-tree/rb-tree.test.ts +12 -12
- package/test/unit/data-structures/binary-tree/tree-multimap.test.ts +2 -2
- package/test/unit/data-structures/graph/abstract-graph.test.ts +2 -1
- package/test/unit/data-structures/graph/undirected-graph.test.ts +1 -1
- package/test/unit/data-structures/hash/hash-map.test.ts +151 -20
- package/test/unit/data-structures/heap/heap.test.ts +8 -8
- package/test/unit/data-structures/heap/max-heap.test.ts +4 -4
- package/test/unit/data-structures/heap/min-heap.test.ts +4 -4
- package/test/unit/data-structures/linked-list/doubly-linked-list.test.ts +1 -1
- package/test/unit/data-structures/linked-list/singly-linked-list.test.ts +2 -2
- package/test/unit/data-structures/linked-list/skip-list.test.ts +4 -4
- package/test/unit/data-structures/priority-queue/max-priority-queue.test.ts +2 -2
- package/test/unit/data-structures/priority-queue/priority-queue.test.ts +8 -2
- package/test/unit/data-structures/queue/deque.test.ts +25 -25
- package/test/unit/data-structures/trie/trie.test.ts +9 -9
- package/test/utils/array.ts +1 -1
- package/test/utils/number.ts +1 -1
package/src/utils/utils.ts
CHANGED
|
@@ -84,3 +84,16 @@ export const getMSB = (value: number): number => {
|
|
|
84
84
|
}
|
|
85
85
|
return 1 << (31 - Math.clz32(value));
|
|
86
86
|
};
|
|
87
|
+
|
|
88
|
+
export const rangeCheck = (index: number, min: number, max: number, message = 'Index out of bounds.'): void => {
|
|
89
|
+
if (index < min || index > max) throw new RangeError(message);
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
export const throwRangeError = (message = 'The value is off-limits.'): void => {
|
|
93
|
+
throw new RangeError(message);
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
export const isObjOrFunc = (input: unknown): input is Record<string, unknown> | ((...args: any[]) => any) => {
|
|
97
|
+
const inputType = typeof input;
|
|
98
|
+
return (inputType === 'object' && input !== null) || inputType === 'function';
|
|
99
|
+
}
|
package/test/config.ts
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
1
|
export const isDebugTest: boolean = false;
|
|
2
|
-
export const isCompetitor: boolean =
|
|
2
|
+
export const isCompetitor: boolean = false;
|
|
@@ -219,7 +219,7 @@ describe('AVL Tree Test recursively', () => {
|
|
|
219
219
|
});
|
|
220
220
|
|
|
221
221
|
describe('AVLTree APIs test', () => {
|
|
222
|
-
const avl = new AVLTree<{id: number; text: string}>();
|
|
222
|
+
const avl = new AVLTree<{ id: number; text: string }>();
|
|
223
223
|
beforeEach(() => {
|
|
224
224
|
avl.clear();
|
|
225
225
|
});
|
|
@@ -268,7 +268,7 @@ describe('AVLTree', () => {
|
|
|
268
268
|
});
|
|
269
269
|
|
|
270
270
|
describe('BinaryTree APIs test', () => {
|
|
271
|
-
const avl = new AVLTree<{id: number; text: string}>();
|
|
271
|
+
const avl = new AVLTree<{ id: number; text: string }>();
|
|
272
272
|
beforeEach(() => {
|
|
273
273
|
avl.clear();
|
|
274
274
|
});
|
|
@@ -189,7 +189,7 @@ describe('BST operations test', () => {
|
|
|
189
189
|
});
|
|
190
190
|
|
|
191
191
|
it('should perform various operations on a Binary Search Tree with object values', () => {
|
|
192
|
-
const objBST = new BST<{key: number; keyA: number}>();
|
|
192
|
+
const objBST = new BST<{ key: number; keyA: number }>();
|
|
193
193
|
expect(objBST).toBeInstanceOf(BST);
|
|
194
194
|
objBST.add(11, {key: 11, keyA: 11});
|
|
195
195
|
objBST.add(3, {key: 3, keyA: 3});
|
|
@@ -260,7 +260,7 @@ describe('BST operations test', () => {
|
|
|
260
260
|
objBST.perfectlyBalance();
|
|
261
261
|
expect(objBST.isPerfectlyBalanced()).toBe(true);
|
|
262
262
|
|
|
263
|
-
const bfsNodesAfterBalanced: BSTNode<{key: number; keyA: number}>[] = [];
|
|
263
|
+
const bfsNodesAfterBalanced: BSTNode<{ key: number; keyA: number }>[] = [];
|
|
264
264
|
objBST.bfs(node => bfsNodesAfterBalanced.push(node));
|
|
265
265
|
expect(bfsNodesAfterBalanced[0].key).toBe(8);
|
|
266
266
|
expect(bfsNodesAfterBalanced[bfsNodesAfterBalanced.length - 1].key).toBe(16);
|
|
@@ -385,7 +385,7 @@ describe('BST operations test', () => {
|
|
|
385
385
|
expect(bfsIDs[1]).toBe(12);
|
|
386
386
|
expect(bfsIDs[2]).toBe(16);
|
|
387
387
|
|
|
388
|
-
const bfsNodes: BSTNode<{key: number; keyA: number}>[] = [];
|
|
388
|
+
const bfsNodes: BSTNode<{ key: number; keyA: number }>[] = [];
|
|
389
389
|
objBST.bfs(node => bfsNodes.push(node));
|
|
390
390
|
expect(bfsNodes[0].key).toBe(2);
|
|
391
391
|
expect(bfsNodes[1].key).toBe(12);
|
|
@@ -580,7 +580,7 @@ describe('BST operations test recursively', () => {
|
|
|
580
580
|
});
|
|
581
581
|
|
|
582
582
|
it('should perform various operations on a Binary Search Tree with object values', () => {
|
|
583
|
-
const objBST = new BST<{key: number; keyA: number}>();
|
|
583
|
+
const objBST = new BST<{ key: number; keyA: number }>();
|
|
584
584
|
expect(objBST).toBeInstanceOf(BST);
|
|
585
585
|
objBST.add(11, {key: 11, keyA: 11});
|
|
586
586
|
objBST.add(3, {key: 3, keyA: 3});
|
|
@@ -652,7 +652,7 @@ describe('BST operations test recursively', () => {
|
|
|
652
652
|
objBST.perfectlyBalance();
|
|
653
653
|
expect(objBST.isPerfectlyBalanced()).toBe(true);
|
|
654
654
|
|
|
655
|
-
const bfsNodesAfterBalanced: BSTNode<{key: number; keyA: number}>[] = [];
|
|
655
|
+
const bfsNodesAfterBalanced: BSTNode<{ key: number; keyA: number }>[] = [];
|
|
656
656
|
objBST.bfs(node => bfsNodesAfterBalanced.push(node));
|
|
657
657
|
expect(bfsNodesAfterBalanced[0].key).toBe(8);
|
|
658
658
|
expect(bfsNodesAfterBalanced[bfsNodesAfterBalanced.length - 1].key).toBe(16);
|
|
@@ -777,7 +777,7 @@ describe('BST operations test recursively', () => {
|
|
|
777
777
|
expect(bfsIDs[1]).toBe(12);
|
|
778
778
|
expect(bfsIDs[2]).toBe(16);
|
|
779
779
|
|
|
780
|
-
const bfsNodes: BSTNode<{key: number; keyA: number}>[] = [];
|
|
780
|
+
const bfsNodes: BSTNode<{ key: number; keyA: number }>[] = [];
|
|
781
781
|
objBST.bfs(node => bfsNodes.push(node));
|
|
782
782
|
expect(bfsNodes[0].key).toBe(2);
|
|
783
783
|
expect(bfsNodes[1].key).toBe(12);
|
|
@@ -29,7 +29,7 @@ describe('Overall BinaryTree Test', () => {
|
|
|
29
29
|
bfsIDs[0] === 11; // true
|
|
30
30
|
expect(bfsIDs[0]).toBe(11);
|
|
31
31
|
|
|
32
|
-
const objBST = new BST<{key: number; keyA: number}>();
|
|
32
|
+
const objBST = new BST<{ key: number; keyA: number }>();
|
|
33
33
|
objBST.add(11, {key: 11, keyA: 11});
|
|
34
34
|
objBST.add(3, {key: 3, keyA: 3});
|
|
35
35
|
|
|
@@ -13,7 +13,7 @@ describe('RedBlackTree', () => {
|
|
|
13
13
|
});
|
|
14
14
|
|
|
15
15
|
describe('add and getNode', () => {
|
|
16
|
-
|
|
16
|
+
it('should add and find a node in the tree', () => {
|
|
17
17
|
tree.add(10);
|
|
18
18
|
tree.add(20);
|
|
19
19
|
tree.add(5);
|
|
@@ -24,7 +24,7 @@ describe('RedBlackTree', () => {
|
|
|
24
24
|
expect(tree.getNode(15)).toBe(undefined);
|
|
25
25
|
});
|
|
26
26
|
|
|
27
|
-
|
|
27
|
+
it('should add and find nodes with negative keys', () => {
|
|
28
28
|
tree.add(-10);
|
|
29
29
|
tree.add(-20);
|
|
30
30
|
|
|
@@ -34,7 +34,7 @@ describe('RedBlackTree', () => {
|
|
|
34
34
|
});
|
|
35
35
|
|
|
36
36
|
describe('deleteNode', () => {
|
|
37
|
-
|
|
37
|
+
it('should delete a node from the tree', () => {
|
|
38
38
|
tree.add(10);
|
|
39
39
|
tree.add(20);
|
|
40
40
|
tree.add(5);
|
|
@@ -43,7 +43,7 @@ describe('RedBlackTree', () => {
|
|
|
43
43
|
expect(tree.getNode(20)).toBe(undefined);
|
|
44
44
|
});
|
|
45
45
|
|
|
46
|
-
|
|
46
|
+
it('should handle deleting a non-existent node', () => {
|
|
47
47
|
tree.add(10);
|
|
48
48
|
tree.add(20);
|
|
49
49
|
tree.add(5);
|
|
@@ -54,7 +54,7 @@ describe('RedBlackTree', () => {
|
|
|
54
54
|
});
|
|
55
55
|
|
|
56
56
|
describe('minimum', () => {
|
|
57
|
-
|
|
57
|
+
it('should find the minimum node in the tree', () => {
|
|
58
58
|
tree.add(10);
|
|
59
59
|
tree.add(20);
|
|
60
60
|
tree.add(5);
|
|
@@ -65,14 +65,14 @@ describe('RedBlackTree', () => {
|
|
|
65
65
|
expect(minNode?.key).toBe(3);
|
|
66
66
|
});
|
|
67
67
|
|
|
68
|
-
|
|
68
|
+
it('should handle an empty tree', () => {
|
|
69
69
|
const minNode = tree.getLeftMost(tree.root);
|
|
70
70
|
expect(minNode).toBe(tree.NIL);
|
|
71
71
|
});
|
|
72
72
|
});
|
|
73
73
|
|
|
74
74
|
describe('getRightMost', () => {
|
|
75
|
-
|
|
75
|
+
it('should find the getRightMost node in the tree', () => {
|
|
76
76
|
tree.add(10);
|
|
77
77
|
tree.add(20);
|
|
78
78
|
tree.add(5);
|
|
@@ -83,14 +83,14 @@ describe('RedBlackTree', () => {
|
|
|
83
83
|
expect(maxNode?.key).toBe(25);
|
|
84
84
|
});
|
|
85
85
|
|
|
86
|
-
|
|
86
|
+
it('should handle an empty tree', () => {
|
|
87
87
|
const maxNode = tree.getRightMost(tree.root);
|
|
88
88
|
expect(maxNode).toBe(tree.NIL);
|
|
89
89
|
});
|
|
90
90
|
});
|
|
91
91
|
|
|
92
92
|
describe('getSuccessor', () => {
|
|
93
|
-
|
|
93
|
+
it('should find the getSuccessor of a node', () => {
|
|
94
94
|
tree.add(10);
|
|
95
95
|
tree.add(20);
|
|
96
96
|
tree.add(5);
|
|
@@ -103,7 +103,7 @@ describe('RedBlackTree', () => {
|
|
|
103
103
|
expect(successorNode?.key).toBe(20);
|
|
104
104
|
});
|
|
105
105
|
|
|
106
|
-
|
|
106
|
+
it('should handle a node with no getSuccessor', () => {
|
|
107
107
|
tree.add(10);
|
|
108
108
|
tree.add(5);
|
|
109
109
|
|
|
@@ -115,7 +115,7 @@ describe('RedBlackTree', () => {
|
|
|
115
115
|
});
|
|
116
116
|
|
|
117
117
|
describe('getPredecessor', () => {
|
|
118
|
-
|
|
118
|
+
it('should find the getPredecessor of a node', () => {
|
|
119
119
|
tree.add(10);
|
|
120
120
|
tree.add(20);
|
|
121
121
|
tree.add(5);
|
|
@@ -128,7 +128,7 @@ describe('RedBlackTree', () => {
|
|
|
128
128
|
expect(predecessorNode?.key).toBe(15);
|
|
129
129
|
});
|
|
130
130
|
|
|
131
|
-
|
|
131
|
+
it('should handle a node with no getPredecessor', () => {
|
|
132
132
|
tree.add(10);
|
|
133
133
|
tree.add(20);
|
|
134
134
|
|
|
@@ -207,7 +207,7 @@ describe('TreeMultimap operations test', () => {
|
|
|
207
207
|
});
|
|
208
208
|
|
|
209
209
|
it('should perform various operations on a Binary Search Tree with object values', () => {
|
|
210
|
-
const objTreeMultimap = new TreeMultimap<{key: number; keyA: number}>();
|
|
210
|
+
const objTreeMultimap = new TreeMultimap<{ key: number; keyA: number }>();
|
|
211
211
|
expect(objTreeMultimap).toBeInstanceOf(TreeMultimap);
|
|
212
212
|
objTreeMultimap.add(11, {key: 11, keyA: 11});
|
|
213
213
|
objTreeMultimap.add(3, {key: 3, keyA: 3});
|
|
@@ -447,7 +447,7 @@ describe('TreeMultimap operations test recursively', () => {
|
|
|
447
447
|
});
|
|
448
448
|
|
|
449
449
|
it('should perform various operations on a Binary Search Tree with object values', () => {
|
|
450
|
-
const objTreeMultimap = new TreeMultimap<{key: number; keyA: number}>();
|
|
450
|
+
const objTreeMultimap = new TreeMultimap<{ key: number; keyA: number }>();
|
|
451
451
|
expect(objTreeMultimap).toBeInstanceOf(TreeMultimap);
|
|
452
452
|
objTreeMultimap.add(11, {key: 11, keyA: 11});
|
|
453
453
|
objTreeMultimap.add(3, {key: 3, keyA: 3});
|
|
@@ -74,7 +74,8 @@ class MyGraph<V = any, E = any, VO extends MyVertex<V> = MyVertex<V>, EO extends
|
|
|
74
74
|
describe('AbstractGraph Operation Test', () => {
|
|
75
75
|
const myGraph: MyGraph<number, string> = new MyGraph<number, string>();
|
|
76
76
|
|
|
77
|
-
beforeEach(() => {
|
|
77
|
+
beforeEach(() => {
|
|
78
|
+
});
|
|
78
79
|
it('should edge cases', function () {
|
|
79
80
|
myGraph.addVertex('A', 1);
|
|
80
81
|
myGraph.addVertex('B', 2);
|
|
@@ -150,7 +150,7 @@ describe('UndirectedGraph', () => {
|
|
|
150
150
|
});
|
|
151
151
|
|
|
152
152
|
it('should getAllPathsBetween work well in 66 vertexes 97 edges graph', () => {
|
|
153
|
-
const graph = new UndirectedGraph<{name: string}, number>();
|
|
153
|
+
const graph = new UndirectedGraph<{ name: string }, number>();
|
|
154
154
|
for (const v of saltyVertexes) {
|
|
155
155
|
graph.addVertex(v.name, v);
|
|
156
156
|
}
|
|
@@ -1,4 +1,6 @@
|
|
|
1
1
|
import {HashMap} from '../../../../src';
|
|
2
|
+
import {getRandomInt, getRandomIntArray} from "../../../utils";
|
|
3
|
+
|
|
2
4
|
|
|
3
5
|
describe('HashMap', () => {
|
|
4
6
|
let hashMap: HashMap<string, number>;
|
|
@@ -9,10 +11,10 @@ describe('HashMap', () => {
|
|
|
9
11
|
|
|
10
12
|
it('should initialize correctly', () => {
|
|
11
13
|
expect(hashMap.size).toBe(0);
|
|
12
|
-
expect(hashMap.table.length).toBe(16);
|
|
13
|
-
expect(hashMap.loadFactor).toBe(0.75);
|
|
14
|
-
expect(hashMap.capacityMultiplier).toBe(2);
|
|
15
|
-
expect(hashMap.initialCapacity).toBe(16);
|
|
14
|
+
// expect(hashMap.table.length).toBe(16);
|
|
15
|
+
// expect(hashMap.loadFactor).toBe(0.75);
|
|
16
|
+
// expect(hashMap.capacityMultiplier).toBe(2);
|
|
17
|
+
// expect(hashMap.initialCapacity).toBe(16);
|
|
16
18
|
expect(hashMap.isEmpty()).toBe(true);
|
|
17
19
|
});
|
|
18
20
|
|
|
@@ -58,26 +60,23 @@ describe('HashMap', () => {
|
|
|
58
60
|
hashMap.set('two', 2);
|
|
59
61
|
hashMap.set('three', 3);
|
|
60
62
|
|
|
61
|
-
const entries = Array.from(hashMap.entries());
|
|
62
|
-
expect(entries).
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
['two', 2],
|
|
66
|
-
['three', 3]
|
|
67
|
-
])
|
|
68
|
-
);
|
|
63
|
+
// const entries = Array.from(hashMap.entries());
|
|
64
|
+
// expect(entries).toContainEqual(['one', 1]);
|
|
65
|
+
// expect(entries).toContainEqual(['two', 2]);
|
|
66
|
+
// expect(entries).toContainEqual(['three', 3]);
|
|
69
67
|
});
|
|
70
68
|
|
|
69
|
+
|
|
71
70
|
it('should resize the table when load factor is exceeded', () => {
|
|
72
71
|
// Set a small initial capacity for testing resizing
|
|
73
|
-
hashMap = new HashMap<string, number>(
|
|
72
|
+
hashMap = new HashMap<string, number>();
|
|
74
73
|
|
|
75
74
|
hashMap.set('one', 1);
|
|
76
75
|
hashMap.set('two', 2);
|
|
77
76
|
hashMap.set('three', 3);
|
|
78
77
|
hashMap.set('four', 4); // This should trigger a resize
|
|
79
78
|
|
|
80
|
-
expect(hashMap.table.length).toBe(8);
|
|
79
|
+
// expect(hashMap.table.length).toBe(8);
|
|
81
80
|
expect(hashMap.get('one')).toBe(1);
|
|
82
81
|
expect(hashMap.get('two')).toBe(2);
|
|
83
82
|
expect(hashMap.get('three')).toBe(3);
|
|
@@ -85,11 +84,8 @@ describe('HashMap', () => {
|
|
|
85
84
|
});
|
|
86
85
|
|
|
87
86
|
it('should allow using a custom hash function', () => {
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
return 0;
|
|
91
|
-
};
|
|
92
|
-
hashMap = new HashMap<string, number>(16, 0.75, customHashFn);
|
|
87
|
+
|
|
88
|
+
hashMap = new HashMap<string, number>();
|
|
93
89
|
|
|
94
90
|
hashMap.set('one', 1);
|
|
95
91
|
hashMap.set('two', 2);
|
|
@@ -98,6 +94,141 @@ describe('HashMap', () => {
|
|
|
98
94
|
expect(hashMap.get('two')).toBe(2);
|
|
99
95
|
// Since the custom hash function always returns 0, these keys will collide.
|
|
100
96
|
// Make sure they are stored separately.
|
|
101
|
-
expect(hashMap.table[0].length).toBe(2);
|
|
97
|
+
// expect(hashMap.table[0].length).toBe(2);
|
|
102
98
|
});
|
|
103
99
|
});
|
|
100
|
+
|
|
101
|
+
describe('HashMap', () => {
|
|
102
|
+
let hashMap: HashMap;
|
|
103
|
+
|
|
104
|
+
beforeEach(() => {
|
|
105
|
+
hashMap = new HashMap();
|
|
106
|
+
});
|
|
107
|
+
|
|
108
|
+
it('should create an empty map', () => {
|
|
109
|
+
expect(hashMap.size).toBe(0);
|
|
110
|
+
});
|
|
111
|
+
|
|
112
|
+
it('should add a key-value pair', () => {
|
|
113
|
+
hashMap.set('key1', 'value1');
|
|
114
|
+
expect(hashMap.get('key1')).toBe('value1');
|
|
115
|
+
});
|
|
116
|
+
|
|
117
|
+
it('should handle object keys correctly', () => {
|
|
118
|
+
const keyObj = {id: 1};
|
|
119
|
+
hashMap.set(keyObj, 'objectValue');
|
|
120
|
+
expect(hashMap.get(keyObj)).toBe('objectValue');
|
|
121
|
+
});
|
|
122
|
+
|
|
123
|
+
it('should handle number keys correctly', () => {
|
|
124
|
+
hashMap.set(999, {a: '999Value'});
|
|
125
|
+
expect(hashMap.get(999)).toEqual({a: '999Value'});
|
|
126
|
+
});
|
|
127
|
+
|
|
128
|
+
it('should update the value for an existing key', () => {
|
|
129
|
+
hashMap.set('key1', 'value1');
|
|
130
|
+
hashMap.set('key1', 'newValue');
|
|
131
|
+
expect(hashMap.get('key1')).toBe('newValue');
|
|
132
|
+
});
|
|
133
|
+
|
|
134
|
+
it('should return undefined for a non-existent key', () => {
|
|
135
|
+
expect(hashMap.get('nonExistentKey')).toBeUndefined();
|
|
136
|
+
});
|
|
137
|
+
|
|
138
|
+
it('should remove a key-value pair', () => {
|
|
139
|
+
hashMap.set('key1', 'value1');
|
|
140
|
+
hashMap.delete('key1');
|
|
141
|
+
expect(hashMap.get('key1')).toBeUndefined();
|
|
142
|
+
});
|
|
143
|
+
|
|
144
|
+
it('should clear the map', () => {
|
|
145
|
+
hashMap.set('key1', 'value1');
|
|
146
|
+
expect(hashMap.size).toBe(1);
|
|
147
|
+
|
|
148
|
+
hashMap.clear();
|
|
149
|
+
expect(hashMap.size).toBe(0);
|
|
150
|
+
});
|
|
151
|
+
|
|
152
|
+
it('should iterate over values', () => {
|
|
153
|
+
hashMap.set('key1', 'value1');
|
|
154
|
+
hashMap.set('key2', 'value2');
|
|
155
|
+
const values = [];
|
|
156
|
+
for (const value of hashMap) {
|
|
157
|
+
values.push(value);
|
|
158
|
+
}
|
|
159
|
+
expect(values).toEqual([['key1', 'value1'], ['key2', 'value2']]);
|
|
160
|
+
});
|
|
161
|
+
|
|
162
|
+
// test('should delete element at specific index', () => {
|
|
163
|
+
// hashMap.set('key1', 'value1');
|
|
164
|
+
// hashMap.set('key2', 'value2');
|
|
165
|
+
// hashMap.deleteAt(0);
|
|
166
|
+
// expect(hashMap.get('key1')).toBeUndefined();
|
|
167
|
+
// expect(hashMap.size).toBe(1);
|
|
168
|
+
// });
|
|
169
|
+
function compareHashMaps(hashMap: HashMap<unknown, unknown>, stdMap: Map<unknown, unknown>) {
|
|
170
|
+
expect(hashMap.size).toEqual(stdMap.size);
|
|
171
|
+
let index = 0;
|
|
172
|
+
stdMap.forEach((value, key) => {
|
|
173
|
+
if (index === 0) {
|
|
174
|
+
expect(hashMap.front).toEqual([key, value]);
|
|
175
|
+
expect(hashMap.begin.current[0]).toEqual(key);
|
|
176
|
+
} else if (index === hashMap.size - 1) {
|
|
177
|
+
expect(hashMap.back).toEqual([key, value]);
|
|
178
|
+
expect(hashMap.reverseBegin.current[0]).toEqual(key);
|
|
179
|
+
} else if (index <= 1000) {
|
|
180
|
+
expect(hashMap.getAt(index)).toEqual([key, value]);
|
|
181
|
+
}
|
|
182
|
+
expect(hashMap.get(key)).toEqual(value);
|
|
183
|
+
expect(hashMap.getIterator(key).current[1]).toEqual(value);
|
|
184
|
+
index++;
|
|
185
|
+
});
|
|
186
|
+
}
|
|
187
|
+
|
|
188
|
+
const stdMap: Map<unknown, unknown> = new Map();
|
|
189
|
+
const arr: number[] = getRandomIntArray(1000, 1, 10000);
|
|
190
|
+
|
|
191
|
+
it('delete test', () => {
|
|
192
|
+
for (const item of arr) {
|
|
193
|
+
stdMap.set(item, item);
|
|
194
|
+
hashMap.set(item, item);
|
|
195
|
+
}
|
|
196
|
+
for (const item of arr) {
|
|
197
|
+
if (Math.random() > 0.6) {
|
|
198
|
+
expect(hashMap.delete(item)).toEqual(stdMap.delete(item));
|
|
199
|
+
}
|
|
200
|
+
}
|
|
201
|
+
compareHashMaps(hashMap, stdMap);
|
|
202
|
+
|
|
203
|
+
for (let i = 0; i < 1000; ++i) {
|
|
204
|
+
const random = getRandomInt(0, 100);
|
|
205
|
+
expect(hashMap.delete(random)).toEqual(stdMap.delete(random));
|
|
206
|
+
}
|
|
207
|
+
compareHashMaps(hashMap, stdMap);
|
|
208
|
+
});
|
|
209
|
+
|
|
210
|
+
test('should iterate correctly with reverse iterators', () => {
|
|
211
|
+
hashMap.set('key1', 'value1');
|
|
212
|
+
hashMap.set('key2', 'value2');
|
|
213
|
+
const iterator = hashMap.reverseBegin;
|
|
214
|
+
expect(iterator.next().current).toEqual(['key1', 'value1']);
|
|
215
|
+
|
|
216
|
+
});
|
|
217
|
+
|
|
218
|
+
test('should return the last element', () => {
|
|
219
|
+
hashMap.set('key1', 'value1');
|
|
220
|
+
hashMap.set('key2', 'value2');
|
|
221
|
+
expect(hashMap.back).toEqual(['key2', 'value2']);
|
|
222
|
+
});
|
|
223
|
+
|
|
224
|
+
test('should return undefined for empty map', () => {
|
|
225
|
+
expect(hashMap.back).toBeUndefined();
|
|
226
|
+
});
|
|
227
|
+
|
|
228
|
+
test('should get element at specific index', () => {
|
|
229
|
+
hashMap.set('key1', 'value1');
|
|
230
|
+
hashMap.set('key2', 'value2');
|
|
231
|
+
expect(hashMap.getAt(1)).toEqual(['key2', 'value2']);
|
|
232
|
+
});
|
|
233
|
+
})
|
|
234
|
+
|
|
@@ -22,7 +22,7 @@ describe('Heap Operation Test', () => {
|
|
|
22
22
|
});
|
|
23
23
|
|
|
24
24
|
it('should object heap work well', function () {
|
|
25
|
-
const minHeap = new MinHeap<{a: string; key: number}>({comparator: (a, b) => a.key - b.key});
|
|
25
|
+
const minHeap = new MinHeap<{ a: string; key: number }>({comparator: (a, b) => a.key - b.key});
|
|
26
26
|
minHeap.add({key: 1, a: 'a1'});
|
|
27
27
|
minHeap.add({key: 6, a: 'a6'});
|
|
28
28
|
minHeap.add({key: 2, a: 'a2'});
|
|
@@ -37,7 +37,7 @@ describe('Heap Operation Test', () => {
|
|
|
37
37
|
i++;
|
|
38
38
|
}
|
|
39
39
|
|
|
40
|
-
const maxHeap = new MaxHeap<{key: number; a: string}>({comparator: (a, b) => b.key - a.key});
|
|
40
|
+
const maxHeap = new MaxHeap<{ key: number; a: string }>({comparator: (a, b) => b.key - a.key});
|
|
41
41
|
maxHeap.add({key: 1, a: 'a1'});
|
|
42
42
|
maxHeap.add({key: 6, a: 'a6'});
|
|
43
43
|
maxHeap.add({key: 5, a: 'a5'});
|
|
@@ -62,13 +62,13 @@ describe('FibonacciHeap', () => {
|
|
|
62
62
|
heap = new FibonacciHeap<number>();
|
|
63
63
|
});
|
|
64
64
|
|
|
65
|
-
|
|
65
|
+
it('push & peek', () => {
|
|
66
66
|
heap.push(10);
|
|
67
67
|
heap.push(5);
|
|
68
68
|
expect(heap.peek()).toBe(5);
|
|
69
69
|
});
|
|
70
70
|
|
|
71
|
-
|
|
71
|
+
it('pop', () => {
|
|
72
72
|
heap.push(10);
|
|
73
73
|
heap.push(5);
|
|
74
74
|
heap.push(15);
|
|
@@ -77,11 +77,11 @@ describe('FibonacciHeap', () => {
|
|
|
77
77
|
expect(heap.pop()).toBe(15);
|
|
78
78
|
});
|
|
79
79
|
|
|
80
|
-
|
|
80
|
+
it('pop on an empty heap', () => {
|
|
81
81
|
expect(heap.pop()).toBeUndefined();
|
|
82
82
|
});
|
|
83
83
|
|
|
84
|
-
|
|
84
|
+
it('size', () => {
|
|
85
85
|
expect(heap.size).toBe(0);
|
|
86
86
|
heap.push(10);
|
|
87
87
|
expect(heap.size).toBe(1);
|
|
@@ -89,7 +89,7 @@ describe('FibonacciHeap', () => {
|
|
|
89
89
|
expect(heap.size).toBe(0);
|
|
90
90
|
});
|
|
91
91
|
|
|
92
|
-
|
|
92
|
+
it('clear', () => {
|
|
93
93
|
heap.push(10);
|
|
94
94
|
heap.push(5);
|
|
95
95
|
heap.clear();
|
|
@@ -97,7 +97,7 @@ describe('FibonacciHeap', () => {
|
|
|
97
97
|
expect(heap.peek()).toBeUndefined();
|
|
98
98
|
});
|
|
99
99
|
|
|
100
|
-
|
|
100
|
+
it('custom comparator', () => {
|
|
101
101
|
const maxHeap = new FibonacciHeap<number>((a, b) => b - a);
|
|
102
102
|
maxHeap.push(10);
|
|
103
103
|
maxHeap.push(5);
|
|
@@ -8,7 +8,7 @@ describe('MaxHeap', () => {
|
|
|
8
8
|
maxHeap = new MaxHeap({comparator: numberComparator});
|
|
9
9
|
});
|
|
10
10
|
|
|
11
|
-
|
|
11
|
+
it('add and poll elements in descending order', () => {
|
|
12
12
|
maxHeap.add(3);
|
|
13
13
|
maxHeap.add(1);
|
|
14
14
|
maxHeap.add(4);
|
|
@@ -20,7 +20,7 @@ describe('MaxHeap', () => {
|
|
|
20
20
|
expect(maxHeap.poll()).toBe(1);
|
|
21
21
|
});
|
|
22
22
|
|
|
23
|
-
|
|
23
|
+
it('peek at the top element without removing it', () => {
|
|
24
24
|
maxHeap.add(3);
|
|
25
25
|
maxHeap.add(1);
|
|
26
26
|
maxHeap.add(4);
|
|
@@ -30,7 +30,7 @@ describe('MaxHeap', () => {
|
|
|
30
30
|
expect(maxHeap.size).toBe(4);
|
|
31
31
|
});
|
|
32
32
|
|
|
33
|
-
|
|
33
|
+
it('sort elements in descending order', () => {
|
|
34
34
|
maxHeap.add(3);
|
|
35
35
|
maxHeap.add(1);
|
|
36
36
|
maxHeap.add(4);
|
|
@@ -40,7 +40,7 @@ describe('MaxHeap', () => {
|
|
|
40
40
|
expect(sortedArray).toEqual([4, 3, 2, 1]);
|
|
41
41
|
});
|
|
42
42
|
|
|
43
|
-
|
|
43
|
+
it('check if the heap is empty', () => {
|
|
44
44
|
expect(maxHeap.isEmpty()).toBe(true);
|
|
45
45
|
|
|
46
46
|
maxHeap.add(5);
|
|
@@ -8,7 +8,7 @@ describe('MinHeap', () => {
|
|
|
8
8
|
minHeap = new MinHeap({comparator: numberComparator});
|
|
9
9
|
});
|
|
10
10
|
|
|
11
|
-
|
|
11
|
+
it('add and poll elements in ascending order', () => {
|
|
12
12
|
minHeap.add(3);
|
|
13
13
|
minHeap.add(1);
|
|
14
14
|
minHeap.add(4);
|
|
@@ -20,7 +20,7 @@ describe('MinHeap', () => {
|
|
|
20
20
|
expect(minHeap.poll()).toBe(4);
|
|
21
21
|
});
|
|
22
22
|
|
|
23
|
-
|
|
23
|
+
it('peek at the top element without removing it', () => {
|
|
24
24
|
minHeap.add(3);
|
|
25
25
|
minHeap.add(1);
|
|
26
26
|
minHeap.add(4);
|
|
@@ -30,7 +30,7 @@ describe('MinHeap', () => {
|
|
|
30
30
|
expect(minHeap.size).toBe(4);
|
|
31
31
|
});
|
|
32
32
|
|
|
33
|
-
|
|
33
|
+
it('sort elements in ascending order', () => {
|
|
34
34
|
minHeap.add(3);
|
|
35
35
|
minHeap.add(1);
|
|
36
36
|
minHeap.add(4);
|
|
@@ -40,7 +40,7 @@ describe('MinHeap', () => {
|
|
|
40
40
|
expect(sortedArray).toEqual([1, 2, 3, 4]);
|
|
41
41
|
});
|
|
42
42
|
|
|
43
|
-
|
|
43
|
+
it('check if the heap is empty', () => {
|
|
44
44
|
expect(minHeap.isEmpty()).toBe(true);
|
|
45
45
|
|
|
46
46
|
minHeap.add(5);
|
|
@@ -60,7 +60,7 @@ describe('DoublyLinkedList Operation Test', () => {
|
|
|
60
60
|
|
|
61
61
|
describe('DoublyLinkedList Operation Test', () => {
|
|
62
62
|
let list: DoublyLinkedList<number>;
|
|
63
|
-
let objectList: DoublyLinkedList<{keyA: number}>;
|
|
63
|
+
let objectList: DoublyLinkedList<{ keyA: number }>;
|
|
64
64
|
|
|
65
65
|
beforeEach(() => {
|
|
66
66
|
list = new DoublyLinkedList();
|
|
@@ -11,10 +11,10 @@ describe('SinglyLinkedListNode', () => {
|
|
|
11
11
|
|
|
12
12
|
describe('SinglyLinkedList Operation Test', () => {
|
|
13
13
|
let list: SinglyLinkedList<number>;
|
|
14
|
-
let objectList: SinglyLinkedList<{keyA: number}>;
|
|
14
|
+
let objectList: SinglyLinkedList<{ keyA: number }>;
|
|
15
15
|
beforeEach(() => {
|
|
16
16
|
list = new SinglyLinkedList<number>();
|
|
17
|
-
objectList = new SinglyLinkedList<{keyA: number}>();
|
|
17
|
+
objectList = new SinglyLinkedList<{ keyA: number }>();
|
|
18
18
|
});
|
|
19
19
|
|
|
20
20
|
describe('push', () => {
|
|
@@ -65,21 +65,21 @@ describe('SkipList', () => {
|
|
|
65
65
|
skipList.add(4, 'Four');
|
|
66
66
|
});
|
|
67
67
|
|
|
68
|
-
|
|
68
|
+
it('getFirst() should return the getFirst element', () => {
|
|
69
69
|
expect(skipList.getFirst()).toBe('One');
|
|
70
70
|
});
|
|
71
71
|
|
|
72
|
-
|
|
72
|
+
it('getLast() should return the getLast element', () => {
|
|
73
73
|
expect(skipList.getLast()).toBe('Four');
|
|
74
74
|
});
|
|
75
75
|
|
|
76
|
-
|
|
76
|
+
it('higher(key) should return the getFirst element greater than the given key', () => {
|
|
77
77
|
expect(skipList.higher(2)).toBe('Three');
|
|
78
78
|
expect(skipList.higher(3)).toBe('Four');
|
|
79
79
|
expect(skipList.higher(4)).toBeUndefined();
|
|
80
80
|
});
|
|
81
81
|
|
|
82
|
-
|
|
82
|
+
it('lower(key) should return the getLast element less than the given key', () => {
|
|
83
83
|
expect(skipList.lower(2)).toBe('One');
|
|
84
84
|
expect(skipList.lower(1)).toBe(null);
|
|
85
85
|
});
|
|
@@ -16,7 +16,7 @@ describe('MaxPriorityQueue Operation Test', () => {
|
|
|
16
16
|
});
|
|
17
17
|
|
|
18
18
|
it('should add elements and maintain heap property in a object MaxPriorityQueue', () => {
|
|
19
|
-
const priorityQueue = new MaxPriorityQueue<{keyA: number}>({comparator: (a, b) => b.keyA - a.keyA});
|
|
19
|
+
const priorityQueue = new MaxPriorityQueue<{ keyA: number }>({comparator: (a, b) => b.keyA - a.keyA});
|
|
20
20
|
priorityQueue.refill([{keyA: 5}, {keyA: 3}, {keyA: 1}]);
|
|
21
21
|
priorityQueue.add({keyA: 7});
|
|
22
22
|
|
|
@@ -63,7 +63,7 @@ describe('MaxPriorityQueue Operation Test', () => {
|
|
|
63
63
|
|
|
64
64
|
it('should correctly heapify an object array', () => {
|
|
65
65
|
const nodes = [{keyA: 5}, {keyA: 3}, {keyA: 7}, {keyA: 1}];
|
|
66
|
-
const maxPQ = MaxPriorityQueue.heapify<{keyA: number}>({nodes: nodes, comparator: (a, b) => b.keyA - a.keyA});
|
|
66
|
+
const maxPQ = MaxPriorityQueue.heapify<{ keyA: number }>({nodes: nodes, comparator: (a, b) => b.keyA - a.keyA});
|
|
67
67
|
|
|
68
68
|
expect(maxPQ.poll()?.keyA).toBe(7);
|
|
69
69
|
expect(maxPQ.poll()?.keyA).toBe(5);
|