data-structure-typed 1.53.6 → 1.53.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/CHANGELOG.md +1 -1
- package/README.md +16 -25
- package/benchmark/report.html +32 -5
- package/benchmark/report.json +326 -23
- package/dist/cjs/common/index.d.ts +12 -0
- package/dist/cjs/common/index.js +29 -0
- package/dist/cjs/common/index.js.map +1 -0
- package/dist/cjs/data-structures/binary-tree/avl-tree-multi-map.d.ts +1 -1
- package/dist/cjs/data-structures/binary-tree/avl-tree-multi-map.js +9 -12
- package/dist/cjs/data-structures/binary-tree/avl-tree-multi-map.js.map +1 -1
- package/dist/cjs/data-structures/binary-tree/avl-tree.js +2 -2
- package/dist/cjs/data-structures/binary-tree/avl-tree.js.map +1 -1
- package/dist/cjs/data-structures/binary-tree/binary-tree.d.ts +55 -20
- package/dist/cjs/data-structures/binary-tree/binary-tree.js +102 -68
- package/dist/cjs/data-structures/binary-tree/binary-tree.js.map +1 -1
- package/dist/cjs/data-structures/binary-tree/bst.d.ts +131 -37
- package/dist/cjs/data-structures/binary-tree/bst.js +222 -69
- package/dist/cjs/data-structures/binary-tree/bst.js.map +1 -1
- package/dist/cjs/data-structures/binary-tree/index.d.ts +1 -1
- package/dist/cjs/data-structures/binary-tree/index.js +1 -1
- package/dist/cjs/data-structures/binary-tree/index.js.map +1 -1
- package/dist/{mjs/data-structures/binary-tree/rb-tree.d.ts → cjs/data-structures/binary-tree/red-black-tree.d.ts} +56 -0
- package/dist/cjs/data-structures/binary-tree/{rb-tree.js → red-black-tree.js} +60 -4
- package/dist/cjs/data-structures/binary-tree/red-black-tree.js.map +1 -0
- package/dist/cjs/data-structures/binary-tree/tree-multi-map.d.ts +2 -2
- package/dist/cjs/data-structures/binary-tree/tree-multi-map.js +7 -7
- package/dist/cjs/data-structures/binary-tree/tree-multi-map.js.map +1 -1
- package/dist/cjs/data-structures/hash/hash-map.d.ts +30 -0
- package/dist/cjs/data-structures/hash/hash-map.js +30 -0
- package/dist/cjs/data-structures/hash/hash-map.js.map +1 -1
- package/dist/cjs/data-structures/heap/heap.d.ts +26 -9
- package/dist/cjs/data-structures/heap/heap.js +37 -17
- package/dist/cjs/data-structures/heap/heap.js.map +1 -1
- package/dist/cjs/data-structures/linked-list/doubly-linked-list.d.ts +54 -9
- package/dist/cjs/data-structures/linked-list/doubly-linked-list.js +80 -19
- package/dist/cjs/data-structures/linked-list/doubly-linked-list.js.map +1 -1
- package/dist/cjs/data-structures/linked-list/singly-linked-list.d.ts +35 -2
- package/dist/cjs/data-structures/linked-list/singly-linked-list.js +55 -11
- package/dist/cjs/data-structures/linked-list/singly-linked-list.js.map +1 -1
- package/dist/cjs/data-structures/queue/deque.d.ts +37 -8
- package/dist/cjs/data-structures/queue/deque.js +73 -29
- package/dist/cjs/data-structures/queue/deque.js.map +1 -1
- package/dist/cjs/data-structures/queue/queue.d.ts +41 -1
- package/dist/cjs/data-structures/queue/queue.js +51 -9
- package/dist/cjs/data-structures/queue/queue.js.map +1 -1
- package/dist/cjs/data-structures/stack/stack.d.ts +27 -10
- package/dist/cjs/data-structures/stack/stack.js +39 -20
- package/dist/cjs/data-structures/stack/stack.js.map +1 -1
- package/dist/cjs/data-structures/trie/trie.d.ts +111 -6
- package/dist/cjs/data-structures/trie/trie.js +123 -14
- package/dist/cjs/data-structures/trie/trie.js.map +1 -1
- package/dist/cjs/index.d.ts +1 -1
- package/dist/cjs/index.js +1 -1
- package/dist/cjs/index.js.map +1 -1
- package/dist/cjs/types/data-structures/binary-tree/binary-tree.d.ts +1 -1
- package/dist/cjs/types/data-structures/binary-tree/bst.d.ts +3 -2
- package/dist/cjs/types/data-structures/binary-tree/rb-tree.d.ts +1 -1
- package/dist/cjs/types/utils/utils.d.ts +10 -6
- package/dist/cjs/utils/utils.js +4 -2
- package/dist/cjs/utils/utils.js.map +1 -1
- package/dist/mjs/common/index.d.ts +12 -0
- package/dist/mjs/common/index.js +29 -0
- package/dist/mjs/common/index.js.map +1 -0
- package/dist/mjs/data-structures/binary-tree/avl-tree-multi-map.d.ts +1 -1
- package/dist/mjs/data-structures/binary-tree/avl-tree-multi-map.js +10 -12
- package/dist/mjs/data-structures/binary-tree/avl-tree-multi-map.js.map +1 -1
- package/dist/mjs/data-structures/binary-tree/avl-tree.js +3 -2
- package/dist/mjs/data-structures/binary-tree/avl-tree.js.map +1 -1
- package/dist/mjs/data-structures/binary-tree/binary-tree.d.ts +55 -20
- package/dist/mjs/data-structures/binary-tree/binary-tree.js +97 -63
- package/dist/mjs/data-structures/binary-tree/binary-tree.js.map +1 -1
- package/dist/mjs/data-structures/binary-tree/bst.d.ts +131 -37
- package/dist/mjs/data-structures/binary-tree/bst.js +224 -69
- package/dist/mjs/data-structures/binary-tree/bst.js.map +1 -1
- package/dist/mjs/data-structures/binary-tree/index.d.ts +1 -1
- package/dist/mjs/data-structures/binary-tree/index.js +1 -1
- package/dist/mjs/data-structures/binary-tree/index.js.map +1 -1
- package/dist/{cjs/data-structures/binary-tree/rb-tree.d.ts → mjs/data-structures/binary-tree/red-black-tree.d.ts} +56 -0
- package/dist/mjs/data-structures/binary-tree/{rb-tree.js → red-black-tree.js} +60 -4
- package/dist/mjs/data-structures/binary-tree/red-black-tree.js.map +1 -0
- package/dist/mjs/data-structures/binary-tree/tree-multi-map.d.ts +2 -2
- package/dist/mjs/data-structures/binary-tree/tree-multi-map.js +5 -5
- package/dist/mjs/data-structures/binary-tree/tree-multi-map.js.map +1 -1
- package/dist/mjs/data-structures/hash/hash-map.d.ts +30 -0
- package/dist/mjs/data-structures/hash/hash-map.js +30 -0
- package/dist/mjs/data-structures/hash/hash-map.js.map +1 -1
- package/dist/mjs/data-structures/heap/heap.d.ts +26 -9
- package/dist/mjs/data-structures/heap/heap.js +37 -17
- package/dist/mjs/data-structures/heap/heap.js.map +1 -1
- package/dist/mjs/data-structures/linked-list/doubly-linked-list.d.ts +54 -9
- package/dist/mjs/data-structures/linked-list/doubly-linked-list.js +80 -19
- package/dist/mjs/data-structures/linked-list/doubly-linked-list.js.map +1 -1
- package/dist/mjs/data-structures/linked-list/singly-linked-list.d.ts +35 -2
- package/dist/mjs/data-structures/linked-list/singly-linked-list.js +55 -11
- package/dist/mjs/data-structures/linked-list/singly-linked-list.js.map +1 -1
- package/dist/mjs/data-structures/queue/deque.d.ts +37 -8
- package/dist/mjs/data-structures/queue/deque.js +73 -29
- package/dist/mjs/data-structures/queue/deque.js.map +1 -1
- package/dist/mjs/data-structures/queue/queue.d.ts +41 -1
- package/dist/mjs/data-structures/queue/queue.js +51 -9
- package/dist/mjs/data-structures/queue/queue.js.map +1 -1
- package/dist/mjs/data-structures/stack/stack.d.ts +27 -10
- package/dist/mjs/data-structures/stack/stack.js +39 -20
- package/dist/mjs/data-structures/stack/stack.js.map +1 -1
- package/dist/mjs/data-structures/trie/trie.d.ts +111 -6
- package/dist/mjs/data-structures/trie/trie.js +123 -14
- package/dist/mjs/data-structures/trie/trie.js.map +1 -1
- package/dist/mjs/index.d.ts +1 -1
- package/dist/mjs/index.js +1 -1
- package/dist/mjs/index.js.map +1 -1
- package/dist/mjs/types/data-structures/binary-tree/binary-tree.d.ts +1 -1
- package/dist/mjs/types/data-structures/binary-tree/bst.d.ts +3 -2
- package/dist/mjs/types/data-structures/binary-tree/rb-tree.d.ts +1 -1
- package/dist/mjs/types/utils/utils.d.ts +10 -6
- package/dist/mjs/utils/utils.js +4 -2
- package/dist/mjs/utils/utils.js.map +1 -1
- package/dist/umd/data-structure-typed.js +671 -246
- package/dist/umd/data-structure-typed.min.js +3 -3
- package/dist/umd/data-structure-typed.min.js.map +1 -1
- package/package.json +7 -7
- package/src/common/index.ts +25 -0
- package/src/data-structures/binary-tree/avl-tree-multi-map.ts +9 -11
- package/src/data-structures/binary-tree/avl-tree.ts +3 -2
- package/src/data-structures/binary-tree/binary-tree.ts +110 -66
- package/src/data-structures/binary-tree/bst.ts +232 -72
- package/src/data-structures/binary-tree/index.ts +1 -1
- package/src/data-structures/binary-tree/{rb-tree.ts → red-black-tree.ts} +56 -3
- package/src/data-structures/binary-tree/tree-multi-map.ts +6 -6
- package/src/data-structures/hash/hash-map.ts +30 -0
- package/src/data-structures/heap/heap.ts +72 -49
- package/src/data-structures/linked-list/doubly-linked-list.ts +173 -105
- package/src/data-structures/linked-list/singly-linked-list.ts +61 -11
- package/src/data-structures/queue/deque.ts +72 -28
- package/src/data-structures/queue/queue.ts +50 -7
- package/src/data-structures/stack/stack.ts +39 -20
- package/src/data-structures/trie/trie.ts +123 -13
- package/src/index.ts +1 -1
- package/src/types/data-structures/binary-tree/binary-tree.ts +1 -1
- package/src/types/data-structures/binary-tree/bst.ts +3 -2
- package/src/types/data-structures/binary-tree/rb-tree.ts +1 -1
- package/src/types/utils/utils.ts +16 -10
- package/src/utils/utils.ts +4 -2
- package/test/performance/data-structures/binary-tree/avl-tree.test.ts +3 -0
- package/test/performance/data-structures/binary-tree/rb-tree.test.ts +4 -1
- package/test/performance/reportor.ts +38 -33
- package/test/unit/data-structures/binary-tree/avl-tree-multi-map.test.ts +2 -2
- package/test/unit/data-structures/binary-tree/binary-tree.test.ts +47 -47
- package/test/unit/data-structures/binary-tree/bst.test.ts +114 -44
- package/test/unit/data-structures/binary-tree/overall.test.ts +14 -22
- package/test/unit/data-structures/binary-tree/{rb-tree.test.ts → red-black-tree.test.ts} +55 -1
- package/test/unit/data-structures/trie/trie.test.ts +151 -0
- package/test/unit/utils/utils.test.ts +6 -6
- package/dist/cjs/constants/index.d.ts +0 -4
- package/dist/cjs/constants/index.js +0 -9
- package/dist/cjs/constants/index.js.map +0 -1
- package/dist/cjs/data-structures/binary-tree/rb-tree.js.map +0 -1
- package/dist/mjs/constants/index.d.ts +0 -4
- package/dist/mjs/constants/index.js +0 -6
- package/dist/mjs/constants/index.js.map +0 -1
- package/dist/mjs/data-structures/binary-tree/rb-tree.js.map +0 -1
- package/src/constants/index.ts +0 -4
package/src/types/utils/utils.ts
CHANGED
|
@@ -7,17 +7,23 @@ export type SpecifyOptional<T, K extends keyof T> = Omit<T, K> & Partial<Pick<T,
|
|
|
7
7
|
|
|
8
8
|
export type Any = string | number | bigint | boolean | symbol | undefined | object;
|
|
9
9
|
|
|
10
|
+
export type Arithmetic = number | bigint;
|
|
11
|
+
|
|
10
12
|
export type ComparablePrimitive = number | bigint | string | boolean;
|
|
11
13
|
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
14
|
+
export interface BaseComparableObject {
|
|
15
|
+
[key: string]: unknown;
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
export interface ValueComparableObject extends BaseComparableObject {
|
|
19
|
+
valueOf: () => ComparablePrimitive | ValueComparableObject;
|
|
20
|
+
toString?: () => string;
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
export interface StringComparableObject extends BaseComparableObject {
|
|
24
|
+
toString: () => string;
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
export type ComparableObject = ValueComparableObject | StringComparableObject;
|
|
22
28
|
|
|
23
29
|
export type Comparable = ComparablePrimitive | Date | ComparableObject;
|
package/src/utils/utils.ts
CHANGED
|
@@ -226,7 +226,8 @@ export const roundFixed = (num: number, digit: number = 10) => {
|
|
|
226
226
|
*/
|
|
227
227
|
function isPrimitiveComparable(value: unknown): value is ComparablePrimitive {
|
|
228
228
|
const valueType = typeof value;
|
|
229
|
-
if (valueType === 'number') return
|
|
229
|
+
if (valueType === 'number') return true;
|
|
230
|
+
// if (valueType === 'number') return !Number.isNaN(value);
|
|
230
231
|
return valueType === 'bigint' || valueType === 'string' || valueType === 'boolean';
|
|
231
232
|
}
|
|
232
233
|
|
|
@@ -274,7 +275,8 @@ export function isComparable(value: unknown, isForceObjectComparable = false): v
|
|
|
274
275
|
if (isPrimitiveComparable(value)) return true;
|
|
275
276
|
|
|
276
277
|
if (typeof value !== 'object') return false;
|
|
277
|
-
if (value instanceof Date) return
|
|
278
|
+
if (value instanceof Date) return true;
|
|
279
|
+
// if (value instanceof Date) return !Number.isNaN(value.getTime());
|
|
278
280
|
if (isForceObjectComparable) return true;
|
|
279
281
|
const comparableValue = tryObjectToPrimitive(value);
|
|
280
282
|
if (comparableValue === null || comparableValue === undefined) return false;
|
|
@@ -19,6 +19,9 @@ suite
|
|
|
19
19
|
.add(`${HUNDRED_THOUSAND.toLocaleString()} get`, () => {
|
|
20
20
|
for (let i = 0; i < randomArray.length; i++) avlTree.get(randomArray[i]);
|
|
21
21
|
})
|
|
22
|
+
.add(`${HUNDRED_THOUSAND.toLocaleString()} getNode`, () => {
|
|
23
|
+
for (let i = 0; i < randomArray.length; i++) avlTree.getNode(randomArray[i]);
|
|
24
|
+
})
|
|
22
25
|
.add(`${HUNDRED_THOUSAND.toLocaleString()} iterator`, () => {
|
|
23
26
|
const entries = [...avlTree];
|
|
24
27
|
return entries.length === HUNDRED_THOUSAND;
|
|
@@ -23,9 +23,12 @@ suite
|
|
|
23
23
|
.add(`${HUNDRED_THOUSAND.toLocaleString()} get`, () => {
|
|
24
24
|
for (let i = 0; i < randomArray.length; i++) rbTree.get(randomArray[i]);
|
|
25
25
|
})
|
|
26
|
+
.add(`${HUNDRED_THOUSAND.toLocaleString()} getNode`, () => {
|
|
27
|
+
for (let i = 0; i < randomArray.length; i++) rbTree.getNode(randomArray[i]);
|
|
28
|
+
})
|
|
26
29
|
.add(`${HUNDRED_THOUSAND.toLocaleString()} node mode add randomly`, () => {
|
|
27
30
|
rbTreeNodeMode.clear();
|
|
28
|
-
for (let i = 0; i < randomArray.length; i++)
|
|
31
|
+
for (let i = 0; i < randomArray.length; i++) rbTreeNodeMode.add(randomArray[i]);
|
|
29
32
|
})
|
|
30
33
|
.add(`${HUNDRED_THOUSAND.toLocaleString()} node mode get`, () => {
|
|
31
34
|
for (let i = 0; i < randomArray.length; i++) rbTreeNodeMode.get(randomArray[i]);
|
|
@@ -8,6 +8,22 @@ import { PerformanceTest } from './types';
|
|
|
8
8
|
const args = process.argv.slice(2);
|
|
9
9
|
|
|
10
10
|
const { GREEN, BOLD, END, YELLOW, GRAY, CYAN, BG_YELLOW } = ConsoleColor;
|
|
11
|
+
const isOnlyOrdered = true;
|
|
12
|
+
const runOrder = [
|
|
13
|
+
'heap',
|
|
14
|
+
'avl-tree',
|
|
15
|
+
'rb-tree',
|
|
16
|
+
'doubly-linked-list',
|
|
17
|
+
'directed-graph',
|
|
18
|
+
'queue',
|
|
19
|
+
'deque',
|
|
20
|
+
'hash-map',
|
|
21
|
+
'trie',
|
|
22
|
+
'stack'
|
|
23
|
+
// 'singly-linked-list',
|
|
24
|
+
// 'priority-queue',
|
|
25
|
+
// 'binary-tree-overall'
|
|
26
|
+
];
|
|
11
27
|
|
|
12
28
|
const getRelativePath = (file: string) => {
|
|
13
29
|
return path.relative(__dirname, file);
|
|
@@ -80,7 +96,7 @@ const composeReport = () => {
|
|
|
80
96
|
#json-to-html {
|
|
81
97
|
padding: 0 10px 20px;
|
|
82
98
|
}
|
|
83
|
-
|
|
99
|
+
|
|
84
100
|
.json-to-html-label {
|
|
85
101
|
font-size: 2rem;
|
|
86
102
|
margin: 2rem 0 0 3px;
|
|
@@ -92,19 +108,19 @@ const composeReport = () => {
|
|
|
92
108
|
margin-top: 10px;
|
|
93
109
|
font-size: 16px;
|
|
94
110
|
}
|
|
95
|
-
|
|
111
|
+
|
|
96
112
|
.content table th,
|
|
97
113
|
.content table td {
|
|
98
114
|
padding: 8px 12px;
|
|
99
115
|
text-align: left;
|
|
100
116
|
border: 1px solid #ddd;
|
|
101
117
|
}
|
|
102
|
-
|
|
118
|
+
|
|
103
119
|
.content table th {
|
|
104
120
|
background-color: #f2f2f2;
|
|
105
121
|
font-weight: bold;
|
|
106
122
|
}
|
|
107
|
-
|
|
123
|
+
|
|
108
124
|
.content table tr:nth-child(odd) {
|
|
109
125
|
background-color: #ffffff;
|
|
110
126
|
}
|
|
@@ -188,46 +204,35 @@ function replaceMarkdownContent(startMarker: string, endMarker: string, newText:
|
|
|
188
204
|
});
|
|
189
205
|
}
|
|
190
206
|
|
|
191
|
-
const
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
'hash-map',
|
|
197
|
-
'trie',
|
|
198
|
-
'avl-tree',
|
|
199
|
-
'binary-tree-overall',
|
|
200
|
-
'directed-graph',
|
|
201
|
-
'doubly-linked-list',
|
|
202
|
-
'singly-linked-list',
|
|
203
|
-
'priority-queue',
|
|
204
|
-
'stack'
|
|
205
|
-
];
|
|
206
|
-
|
|
207
|
-
const sortedPerformanceTests = [...performanceTests].sort((a, b) => {
|
|
208
|
-
const indexA = order.indexOf(a.testName);
|
|
209
|
-
const indexB = order.indexOf(b.testName);
|
|
207
|
+
const sortedPerformanceTests = (
|
|
208
|
+
isOnlyOrdered ? [...performanceTests].filter(test => runOrder.includes(test.testName)) : [...performanceTests]
|
|
209
|
+
).sort((a, b) => {
|
|
210
|
+
const indexA = runOrder.indexOf(a.testName);
|
|
211
|
+
const indexB = runOrder.indexOf(b.testName);
|
|
210
212
|
|
|
211
|
-
// If both a and b are in the
|
|
213
|
+
// If both a and b are in the runOrder, sort them according to their indices in the runOrder.
|
|
212
214
|
if (indexA !== -1 && indexB !== -1) {
|
|
213
215
|
return indexA - indexB;
|
|
214
216
|
}
|
|
215
217
|
|
|
216
|
-
// If there is only 'a' in the
|
|
218
|
+
// If there is only 'a' in the runOrder, then place 'b' in front.
|
|
217
219
|
if (indexA !== -1) {
|
|
218
220
|
return 1;
|
|
219
221
|
}
|
|
220
222
|
|
|
221
|
-
// If only b is in the
|
|
223
|
+
// If only b is in the runOrder, then a should be placed before it.
|
|
222
224
|
if (indexB !== -1) {
|
|
223
225
|
return -1;
|
|
224
226
|
}
|
|
225
227
|
|
|
226
|
-
// If neither a nor b are in
|
|
228
|
+
// If neither a nor b are in runOrder, keep their original runOrder
|
|
227
229
|
return 0;
|
|
228
230
|
});
|
|
229
231
|
|
|
230
|
-
console.log(`${GREEN} Found tests${END}: ${
|
|
232
|
+
console.log(`${GREEN} Found tests (${performanceTests.length})${END}: ${performanceTests.map(test => test.testName)}`);
|
|
233
|
+
console.log(
|
|
234
|
+
`${GREEN} Running tests (${sortedPerformanceTests.length})${END}: ${sortedPerformanceTests.map(test => test.testName)}`
|
|
235
|
+
);
|
|
231
236
|
|
|
232
237
|
sortedPerformanceTests.forEach(item => {
|
|
233
238
|
const { suite, testName, file } = item;
|
|
@@ -245,22 +250,22 @@ sortedPerformanceTests.forEach(item => {
|
|
|
245
250
|
return {
|
|
246
251
|
'test name': benchmark.name,
|
|
247
252
|
'time taken (ms)': numberFix(benchmark.times.period * 1000, 2),
|
|
248
|
-
'executions per sec': numberFix(benchmark.hz, 2),
|
|
253
|
+
// 'executions per sec': numberFix(benchmark.hz, 2),
|
|
249
254
|
// 'executed times': numberFix(benchmark.count, 0),
|
|
250
|
-
|
|
255
|
+
'sample mean (secs)': numberFix(benchmark.stats.mean, 2),
|
|
251
256
|
'sample deviation': numberFix(benchmark.stats.deviation, 2)
|
|
252
257
|
};
|
|
253
258
|
});
|
|
254
259
|
|
|
255
260
|
report[testName].testName = testName;
|
|
256
|
-
const isDone = completedCount ===
|
|
261
|
+
const isDone = completedCount === sortedPerformanceTests.length;
|
|
257
262
|
runTime = Number(runTime.toFixed(2));
|
|
258
263
|
const isTimeWarn = runTime > 120;
|
|
259
264
|
console.log(
|
|
260
265
|
// `Files: ${GREEN}${testFileCount}${END} `,
|
|
261
266
|
// `Suites: ${GREEN}${performanceTests.length}${END} `,
|
|
262
|
-
`Suites Progress: ${isDone ? GREEN : YELLOW}${completedCount}${END}/${isDone ? GREEN : YELLOW}${
|
|
263
|
-
`Time: ${isTimeWarn ? YELLOW : GREEN}${runTime}s${END}`
|
|
267
|
+
`Suites Progress: ${isDone ? GREEN : YELLOW}${completedCount}${END}/${isDone ? GREEN : YELLOW}${sortedPerformanceTests.length}${END}`,
|
|
268
|
+
`Time Costs: ${isTimeWarn ? YELLOW : GREEN}${runTime}s${END}`
|
|
264
269
|
);
|
|
265
270
|
if (isDone) {
|
|
266
271
|
composeReport();
|
|
@@ -736,7 +736,7 @@ describe('AVLTree toEntryFn', () => {
|
|
|
736
736
|
{ obj: { id: 5 } }
|
|
737
737
|
])
|
|
738
738
|
).toThrowError(
|
|
739
|
-
`When comparing object types, a custom
|
|
739
|
+
`When comparing object types, a custom extractComparable must be defined in the constructor's options parameter.`
|
|
740
740
|
);
|
|
741
741
|
});
|
|
742
742
|
|
|
@@ -744,7 +744,7 @@ describe('AVLTree toEntryFn', () => {
|
|
|
744
744
|
const tree = new AVLTreeMultiMap<{ obj: { id: number } }, number>(
|
|
745
745
|
[{ obj: { id: 1 } }, { obj: { id: 2 } }, { obj: { id: 3 } }, { obj: { id: 4 } }, { obj: { id: 5 } }],
|
|
746
746
|
{
|
|
747
|
-
|
|
747
|
+
extractComparable: key => key.obj.id
|
|
748
748
|
}
|
|
749
749
|
);
|
|
750
750
|
|
|
@@ -103,9 +103,9 @@ describe('BinaryTree addMany', () => {
|
|
|
103
103
|
[undefined, 22, 44, 33]
|
|
104
104
|
);
|
|
105
105
|
expect(tree.get(2)).toBe(22);
|
|
106
|
-
expect(tree.get(tree.
|
|
107
|
-
expect(tree.get(tree.
|
|
108
|
-
expect(tree.get(tree.
|
|
106
|
+
expect(tree.get(tree.getNode(3))).toBe(33);
|
|
107
|
+
expect(tree.get(tree.getNode(4))).toBe(44);
|
|
108
|
+
expect(tree.get(tree.getNode(1))).toBe(1);
|
|
109
109
|
});
|
|
110
110
|
|
|
111
111
|
it('should addMany undefined and null', () => {
|
|
@@ -349,7 +349,7 @@ describe('BinaryTree', () => {
|
|
|
349
349
|
expect(tree.isBST(tree.getNode(4), 'ITERATIVE')).toBe(true);
|
|
350
350
|
expect(tree.getNodes(2, false, null)).toEqual([]);
|
|
351
351
|
expect(tree.getNodes(undefined)).toEqual([]);
|
|
352
|
-
expect(tree.getNodes(tree.
|
|
352
|
+
expect(tree.getNodes(tree.getNode(2), false, tree.root)).toEqual([tree.getNode(2)]);
|
|
353
353
|
});
|
|
354
354
|
|
|
355
355
|
describe('should isKey', () => {
|
|
@@ -362,9 +362,9 @@ describe('BinaryTree', () => {
|
|
|
362
362
|
expect(tree.isKey(-Infinity)).toBe(true);
|
|
363
363
|
});
|
|
364
364
|
|
|
365
|
-
it('NaN should not be a key', () => {
|
|
366
|
-
|
|
367
|
-
});
|
|
365
|
+
// it('NaN should not be a key', () => {
|
|
366
|
+
// expect(tree.isKey(NaN)).toBe(false);
|
|
367
|
+
// });
|
|
368
368
|
|
|
369
369
|
it('strings should be a key', () => {
|
|
370
370
|
expect(tree.isKey('hello')).toBe(true);
|
|
@@ -400,9 +400,9 @@ describe('BinaryTree', () => {
|
|
|
400
400
|
expect(tree.isKey(new Date('2024-01-01'))).toBe(true);
|
|
401
401
|
});
|
|
402
402
|
|
|
403
|
-
it('invalid Date objects should not be a key', () => {
|
|
404
|
-
|
|
405
|
-
});
|
|
403
|
+
// it('invalid Date objects should not be a key', () => {
|
|
404
|
+
// expect(tree.isKey(new Date('invalid'))).toBe(false);
|
|
405
|
+
// });
|
|
406
406
|
});
|
|
407
407
|
|
|
408
408
|
describe('arrays', () => {
|
|
@@ -733,41 +733,41 @@ describe('BinaryTree', () => {
|
|
|
733
733
|
]);
|
|
734
734
|
});
|
|
735
735
|
|
|
736
|
-
it('should keyValueNodeEntryRawToNodeAndValue', () => {
|
|
737
|
-
|
|
738
|
-
|
|
739
|
-
|
|
740
|
-
|
|
741
|
-
|
|
742
|
-
|
|
743
|
-
|
|
744
|
-
|
|
745
|
-
|
|
746
|
-
|
|
747
|
-
|
|
748
|
-
|
|
749
|
-
|
|
750
|
-
|
|
751
|
-
|
|
752
|
-
|
|
753
|
-
|
|
754
|
-
|
|
755
|
-
|
|
756
|
-
|
|
757
|
-
|
|
758
|
-
|
|
759
|
-
|
|
760
|
-
|
|
761
|
-
|
|
762
|
-
|
|
763
|
-
|
|
764
|
-
|
|
765
|
-
|
|
766
|
-
|
|
767
|
-
|
|
768
|
-
|
|
769
|
-
|
|
770
|
-
});
|
|
736
|
+
// it('should keyValueNodeEntryRawToNodeAndValue', () => {
|
|
737
|
+
// const tree = new BinaryTree<number>();
|
|
738
|
+
// const node0 = tree.keyValueNodeEntryRawToNodeAndValue(0);
|
|
739
|
+
// expect(node0).toEqual([
|
|
740
|
+
// {
|
|
741
|
+
// _left: undefined,
|
|
742
|
+
// _right: undefined,
|
|
743
|
+
// key: 0,
|
|
744
|
+
// parent: undefined,
|
|
745
|
+
// value: undefined
|
|
746
|
+
// },
|
|
747
|
+
// undefined
|
|
748
|
+
// ]);
|
|
749
|
+
//
|
|
750
|
+
// const nodeUndefined = tree.keyValueNodeEntryRawToNodeAndValue(undefined);
|
|
751
|
+
// expect(nodeUndefined).toEqual([undefined, undefined]);
|
|
752
|
+
//
|
|
753
|
+
// const nodeNull = tree.keyValueNodeEntryRawToNodeAndValue(null);
|
|
754
|
+
// expect(nodeNull).toEqual([null, undefined]);
|
|
755
|
+
//
|
|
756
|
+
// const [, nodeWithSeparateValue] = tree.keyValueNodeEntryRawToNodeAndValue(7, 77);
|
|
757
|
+
// expect(nodeWithSeparateValue).toBe(77);
|
|
758
|
+
//
|
|
759
|
+
// expect(tree.keyValueNodeEntryRawToNodeAndValue([undefined, 2])).toEqual([undefined, undefined]);
|
|
760
|
+
//
|
|
761
|
+
// expect(tree.keyValueNodeEntryRawToNodeAndValue(Symbol('test') as unknown as number)).toEqual([
|
|
762
|
+
// undefined,
|
|
763
|
+
// undefined
|
|
764
|
+
// ]);
|
|
765
|
+
//
|
|
766
|
+
// const bTree = new BinaryTree<number, number, { obj: { id: number } }>([], {
|
|
767
|
+
// toEntryFn: (ele: { obj: { id: number } }) => [Symbol('test') as unknown as number, ele.obj.id]
|
|
768
|
+
// });
|
|
769
|
+
// expect(bTree.keyValueNodeEntryRawToNodeAndValue({ obj: { id: 1 } })).toEqual([undefined, undefined]);
|
|
770
|
+
// });
|
|
771
771
|
|
|
772
772
|
it('should replace value', () => {
|
|
773
773
|
const tree = new BinaryTree<number, string>([4, 5, [1, '1'], 2, 3], { isMapMode: false });
|
|
@@ -1155,8 +1155,8 @@ describe('BinaryTree', () => {
|
|
|
1155
1155
|
tree.add([3, 'B']);
|
|
1156
1156
|
tree.add([7, 'C']);
|
|
1157
1157
|
|
|
1158
|
-
expect(tree.getPathToRoot(
|
|
1159
|
-
expect(tree.getPathToRoot(
|
|
1158
|
+
expect(tree.getPathToRoot(7)).toEqual([7, 5]);
|
|
1159
|
+
expect(tree.getPathToRoot(1)).toEqual([]);
|
|
1160
1160
|
});
|
|
1161
1161
|
|
|
1162
1162
|
it('should check if the tree is perfectly balanced', () => {
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { BinaryTreeNode, BST, BSTNode } from '../../../../src';
|
|
1
|
+
import { BinaryTreeNode, BST, BSTNode, Range } from '../../../../src';
|
|
2
2
|
import { isDebugTest, isTestStackOverflow, SYSTEM_MAX_CALL_STACK } from '../../../config';
|
|
3
3
|
|
|
4
4
|
const isDebug = isDebugTest;
|
|
@@ -58,7 +58,7 @@ describe('BST operations test', () => {
|
|
|
58
58
|
[10, 10],
|
|
59
59
|
[5, 5]
|
|
60
60
|
];
|
|
61
|
-
bst.addMany(idsAndValues,
|
|
61
|
+
bst.addMany(idsAndValues, [], false);
|
|
62
62
|
expect(bst.root).toBeInstanceOf(BSTNode);
|
|
63
63
|
|
|
64
64
|
if (bst.root) expect(bst.root.key).toBe(11);
|
|
@@ -450,26 +450,26 @@ describe('BST operations test', () => {
|
|
|
450
450
|
expect(bfsNodes[2].key).toBe(16);
|
|
451
451
|
});
|
|
452
452
|
|
|
453
|
-
it('should keyValueNodeEntryRawToNodeAndValue', () => {
|
|
454
|
-
|
|
455
|
-
|
|
456
|
-
|
|
457
|
-
|
|
458
|
-
|
|
459
|
-
|
|
460
|
-
|
|
461
|
-
|
|
462
|
-
|
|
463
|
-
|
|
464
|
-
|
|
465
|
-
|
|
466
|
-
|
|
467
|
-
|
|
468
|
-
|
|
469
|
-
|
|
470
|
-
|
|
471
|
-
|
|
472
|
-
});
|
|
453
|
+
// it('should keyValueNodeEntryRawToNodeAndValue', () => {
|
|
454
|
+
// const bst = new BST<number>();
|
|
455
|
+
// const node0 = bst.keyValueNodeEntryRawToNodeAndValue(0);
|
|
456
|
+
// expect(node0).toEqual([
|
|
457
|
+
// {
|
|
458
|
+
// _left: undefined,
|
|
459
|
+
// _right: undefined,
|
|
460
|
+
// key: 0,
|
|
461
|
+
// parent: undefined,
|
|
462
|
+
// value: undefined
|
|
463
|
+
// },
|
|
464
|
+
// undefined
|
|
465
|
+
// ]);
|
|
466
|
+
//
|
|
467
|
+
// const nodeUndefined = bst.keyValueNodeEntryRawToNodeAndValue(undefined);
|
|
468
|
+
// expect(nodeUndefined).toEqual([undefined, undefined]);
|
|
469
|
+
//
|
|
470
|
+
// const nodeNull = bst.keyValueNodeEntryRawToNodeAndValue(null);
|
|
471
|
+
// expect(nodeNull).toEqual([undefined, undefined]);
|
|
472
|
+
// });
|
|
473
473
|
|
|
474
474
|
it('should replace value', () => {
|
|
475
475
|
const tree = new BST<number, string>([4, 5, [1, '1'], 2, 3], { isMapMode: false });
|
|
@@ -489,6 +489,13 @@ describe('BST operations test', () => {
|
|
|
489
489
|
expect(treeMap.getNode(1)?.value).toBe(undefined);
|
|
490
490
|
expect(treeMap.get(1)).toBe('b');
|
|
491
491
|
});
|
|
492
|
+
|
|
493
|
+
it('should search in range', () => {
|
|
494
|
+
const bst = new BST<number>([10, 5, 15, 3, 7, 12, 18]);
|
|
495
|
+
expect(bst.rangeSearch([4, 12])).toEqual([10, 12, 5, 7]);
|
|
496
|
+
expect(() => bst.rangeSearch([12, 4])).toThrow('low must be less than or equal to high');
|
|
497
|
+
expect(bst.rangeSearch([12, 12])).toEqual([12]);
|
|
498
|
+
});
|
|
492
499
|
});
|
|
493
500
|
|
|
494
501
|
describe('BST operations test recursively', () => {
|
|
@@ -974,7 +981,7 @@ describe('BST operations test recursively', () => {
|
|
|
974
981
|
|
|
975
982
|
if (isTestStackOverflow) {
|
|
976
983
|
it('should getLeftMost', () => {
|
|
977
|
-
const bst = new BST<number>([], {
|
|
984
|
+
const bst = new BST<number>([], { extractComparable: key => key });
|
|
978
985
|
for (let i = 1; i <= SYSTEM_MAX_CALL_STACK; i++) bst.add(i);
|
|
979
986
|
|
|
980
987
|
expect(() => {
|
|
@@ -1009,7 +1016,7 @@ describe('BST isBST', function () {
|
|
|
1009
1016
|
|
|
1010
1017
|
it('isBST when variant is Max', () => {
|
|
1011
1018
|
const bst = new BST<number, number>([1, 2, 3, 9, 8, 5, 6, 7, 4], {
|
|
1012
|
-
|
|
1019
|
+
isReverse: true
|
|
1013
1020
|
});
|
|
1014
1021
|
bst.addMany([1, 2, 3, 9, 8, 5, 6, 7, 4]);
|
|
1015
1022
|
expect(bst.isBST()).toBe(true);
|
|
@@ -1340,26 +1347,26 @@ describe('BST operations not map mode test', () => {
|
|
|
1340
1347
|
});
|
|
1341
1348
|
});
|
|
1342
1349
|
|
|
1343
|
-
it('should keyValueNodeEntryRawToNodeAndValue', () => {
|
|
1344
|
-
|
|
1345
|
-
|
|
1346
|
-
|
|
1347
|
-
|
|
1348
|
-
|
|
1349
|
-
|
|
1350
|
-
|
|
1351
|
-
|
|
1352
|
-
|
|
1353
|
-
|
|
1354
|
-
|
|
1355
|
-
|
|
1356
|
-
|
|
1357
|
-
|
|
1358
|
-
|
|
1359
|
-
|
|
1360
|
-
|
|
1361
|
-
|
|
1362
|
-
});
|
|
1350
|
+
// it('should keyValueNodeEntryRawToNodeAndValue', () => {
|
|
1351
|
+
// const bst = new BST<number>([], { isMapMode: false });
|
|
1352
|
+
// const node0 = bst.keyValueNodeEntryRawToNodeAndValue(0);
|
|
1353
|
+
// expect(node0).toEqual([
|
|
1354
|
+
// {
|
|
1355
|
+
// _left: undefined,
|
|
1356
|
+
// _right: undefined,
|
|
1357
|
+
// key: 0,
|
|
1358
|
+
// parent: undefined,
|
|
1359
|
+
// value: undefined
|
|
1360
|
+
// },
|
|
1361
|
+
// undefined
|
|
1362
|
+
// ]);
|
|
1363
|
+
//
|
|
1364
|
+
// const nodeUndefined = bst.keyValueNodeEntryRawToNodeAndValue(undefined);
|
|
1365
|
+
// expect(nodeUndefined).toEqual([undefined, undefined]);
|
|
1366
|
+
//
|
|
1367
|
+
// const nodeNull = bst.keyValueNodeEntryRawToNodeAndValue(null);
|
|
1368
|
+
// expect(nodeNull).toEqual([undefined, undefined]);
|
|
1369
|
+
// });
|
|
1363
1370
|
});
|
|
1364
1371
|
|
|
1365
1372
|
describe('BST operations not map mode test recursively', () => {
|
|
@@ -1529,3 +1536,66 @@ describe('BST iterative methods not map mode test', () => {
|
|
|
1529
1536
|
expect(balanced.leaves(node => balanced.get(node?.key))).toEqual(['a', 'f', 'd', 'i']);
|
|
1530
1537
|
});
|
|
1531
1538
|
});
|
|
1539
|
+
|
|
1540
|
+
describe('classic use', () => {
|
|
1541
|
+
it('@example Merge 3 sorted datasets', () => {
|
|
1542
|
+
const dataset1 = new BST<number, string>([
|
|
1543
|
+
[1, 'A'],
|
|
1544
|
+
[7, 'G']
|
|
1545
|
+
]);
|
|
1546
|
+
const dataset2 = [
|
|
1547
|
+
[2, 'B'],
|
|
1548
|
+
[6, 'F']
|
|
1549
|
+
];
|
|
1550
|
+
const dataset3 = new BST<number, string>([
|
|
1551
|
+
[3, 'C'],
|
|
1552
|
+
[5, 'E'],
|
|
1553
|
+
[4, 'D']
|
|
1554
|
+
]);
|
|
1555
|
+
|
|
1556
|
+
// Merge datasets into a single BinarySearchTree
|
|
1557
|
+
const merged = new BST<number, string>(dataset1);
|
|
1558
|
+
merged.addMany(dataset2);
|
|
1559
|
+
merged.merge(dataset3);
|
|
1560
|
+
|
|
1561
|
+
// Verify merged dataset is in sorted order
|
|
1562
|
+
expect([...merged.values()]).toEqual(['A', 'B', 'C', 'D', 'E', 'F', 'G']);
|
|
1563
|
+
});
|
|
1564
|
+
|
|
1565
|
+
// Test case for finding elements in a given range
|
|
1566
|
+
it('@example Find elements in a range', () => {
|
|
1567
|
+
const bst = new BST<number>([10, 5, 15, 3, 7, 12, 18]);
|
|
1568
|
+
expect(bst.search(new Range(5, 10))).toEqual([10, 5, 7]);
|
|
1569
|
+
expect(bst.rangeSearch([4, 12], node => node.key.toString())).toEqual(['10', '12', '5', '7']);
|
|
1570
|
+
expect(bst.search(new Range(4, 12, true, false))).toEqual([10, 5, 7]);
|
|
1571
|
+
expect(bst.rangeSearch([15, 20])).toEqual([15, 18]);
|
|
1572
|
+
expect(bst.search(new Range(15, 20, false))).toEqual([18]);
|
|
1573
|
+
});
|
|
1574
|
+
|
|
1575
|
+
// Test case for Lowest Common Ancestor (LCA)
|
|
1576
|
+
it('@example Find lowest common ancestor', () => {
|
|
1577
|
+
const bst = new BST<number>([20, 10, 30, 5, 15, 25, 35, 3, 7, 12, 18]);
|
|
1578
|
+
|
|
1579
|
+
// LCA helper function
|
|
1580
|
+
const findLCA = (num1: number, num2: number): number | undefined => {
|
|
1581
|
+
const path1 = bst.getPathToRoot(num1);
|
|
1582
|
+
const path2 = bst.getPathToRoot(num2);
|
|
1583
|
+
// Find the first common ancestor
|
|
1584
|
+
return findFirstCommon(path1, path2);
|
|
1585
|
+
};
|
|
1586
|
+
|
|
1587
|
+
function findFirstCommon(arr1: number[], arr2: number[]): number | undefined {
|
|
1588
|
+
for (const num of arr1) {
|
|
1589
|
+
if (arr2.indexOf(num) !== -1) {
|
|
1590
|
+
return num;
|
|
1591
|
+
}
|
|
1592
|
+
}
|
|
1593
|
+
return undefined;
|
|
1594
|
+
}
|
|
1595
|
+
|
|
1596
|
+
// Assertions
|
|
1597
|
+
expect(findLCA(3, 10)).toBe(7);
|
|
1598
|
+
expect(findLCA(5, 35)).toBe(15);
|
|
1599
|
+
expect(findLCA(20, 30)).toBe(25);
|
|
1600
|
+
});
|
|
1601
|
+
});
|