data-structure-typed 1.41.7 → 1.41.9
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 +14 -11
- package/benchmark/report.html +14 -11
- package/benchmark/report.json +155 -204
- package/dist/cjs/src/data-structures/binary-tree/rb-tree.d.ts +5 -2
- package/dist/cjs/src/data-structures/binary-tree/rb-tree.js +15 -2
- package/dist/cjs/src/data-structures/binary-tree/rb-tree.js.map +1 -1
- package/dist/cjs/src/data-structures/graph/abstract-graph.d.ts +6 -2
- package/dist/cjs/src/data-structures/graph/abstract-graph.js +45 -35
- package/dist/cjs/src/data-structures/graph/abstract-graph.js.map +1 -1
- package/dist/mjs/src/data-structures/binary-tree/rb-tree.d.ts +5 -2
- package/dist/mjs/src/data-structures/binary-tree/rb-tree.js +15 -2
- package/dist/mjs/src/data-structures/graph/abstract-graph.d.ts +6 -2
- package/dist/mjs/src/data-structures/graph/abstract-graph.js +44 -35
- package/dist/umd/data-structure-typed.min.js +1 -1
- package/dist/umd/data-structure-typed.min.js.map +1 -1
- package/package.json +5 -5
- package/src/data-structures/binary-tree/binary-tree.ts +1 -1
- package/src/data-structures/binary-tree/bst.ts +1 -1
- package/src/data-structures/binary-tree/rb-tree.ts +18 -2
- package/src/data-structures/graph/abstract-graph.ts +50 -41
- package/test/performance/data-structures/binary-tree/avl-tree.test.ts +6 -6
- package/test/performance/data-structures/binary-tree/binary-tree.test.ts +7 -7
- package/test/performance/data-structures/binary-tree/bst.test.ts +6 -6
- package/test/performance/data-structures/binary-tree/rb-tree.test.ts +32 -0
- package/test/performance/data-structures/graph/directed-graph.test.ts +4 -4
- package/test/performance/data-structures/heap/heap.test.ts +7 -7
- package/test/performance/data-structures/linked-list/doubly-linked-list.test.ts +6 -6
- package/test/performance/data-structures/linked-list/singly-linked-list.test.ts +7 -7
- package/test/performance/data-structures/priority-queue/max-priority-queue.test.ts +1 -1
- package/test/performance/data-structures/queue/deque.test.ts +2 -2
- package/test/performance/data-structures/queue/queue.test.ts +2 -2
- package/test/performance/data-structures/trie/trie.test.ts +2 -2
- package/test/performance/reportor.ts +5 -6
- package/test/unit/data-structures/binary-tree/rb-tree.test.ts +103 -103
- package/test/unit/data-structures/graph/undirected-graph.test.ts +21 -13
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "data-structure-typed",
|
|
3
|
-
"version": "1.41.
|
|
3
|
+
"version": "1.41.9",
|
|
4
4
|
"description": "Data Structures of Javascript & TypeScript. Binary Tree, BST, Graph, Heap, Priority Queue, Linked List, Queue, Deque, Stack, AVL Tree, Tree Multiset, Trie, Directed Graph, Undirected Graph, Singly Linked List, Doubly Linked List, Max Heap, Max Priority Queue, Min Heap, Min Priority Queue.",
|
|
5
5
|
"main": "dist/cjs/src/index.js",
|
|
6
6
|
"module": "dist/mjs/src/index.js",
|
|
@@ -64,10 +64,10 @@
|
|
|
64
64
|
"@typescript-eslint/eslint-plugin": "^6.7.4",
|
|
65
65
|
"@typescript-eslint/parser": "^6.7.4",
|
|
66
66
|
"auto-changelog": "^2.4.0",
|
|
67
|
-
"avl-tree-typed": "^1.41.
|
|
67
|
+
"avl-tree-typed": "^1.41.8",
|
|
68
68
|
"benchmark": "^2.1.4",
|
|
69
|
-
"binary-tree-typed": "^1.41.
|
|
70
|
-
"bst-typed": "^1.41.
|
|
69
|
+
"binary-tree-typed": "^1.41.8",
|
|
70
|
+
"bst-typed": "^1.41.8",
|
|
71
71
|
"dependency-cruiser": "^14.1.0",
|
|
72
72
|
"eslint": "^8.50.0",
|
|
73
73
|
"eslint-config-prettier": "^9.0.0",
|
|
@@ -75,7 +75,7 @@
|
|
|
75
75
|
"eslint-import-resolver-typescript": "^3.6.1",
|
|
76
76
|
"eslint-plugin-import": "^2.28.1",
|
|
77
77
|
"fast-glob": "^3.3.1",
|
|
78
|
-
"heap-typed": "^1.41.
|
|
78
|
+
"heap-typed": "^1.41.8",
|
|
79
79
|
"istanbul-badges-readme": "^1.8.5",
|
|
80
80
|
"jest": "^29.7.0",
|
|
81
81
|
"prettier": "^3.0.3",
|
|
@@ -142,7 +142,7 @@ export class BinaryTree<V = any, N extends BinaryTreeNode<V, N> = BinaryTreeNode
|
|
|
142
142
|
}
|
|
143
143
|
|
|
144
144
|
protected defaultOneParamCallback = (node: N) => node.key;
|
|
145
|
-
|
|
145
|
+
|
|
146
146
|
/**
|
|
147
147
|
* Creates a new instance of BinaryTreeNode with the given key and value.
|
|
148
148
|
* @param {BTNKey} key - The key for the new node.
|
|
@@ -36,7 +36,7 @@ export class BST<V = any, N extends BSTNode<V, N> = BSTNode<V, BSTNodeNested<V>>
|
|
|
36
36
|
}
|
|
37
37
|
}
|
|
38
38
|
}
|
|
39
|
-
|
|
39
|
+
|
|
40
40
|
/**
|
|
41
41
|
* The function creates a new binary search tree node with the given key and value.
|
|
42
42
|
* @param {BTNKey} key - The key parameter is the key value that will be associated with
|
|
@@ -44,6 +44,12 @@ export class RedBlackTree {
|
|
|
44
44
|
return this._root;
|
|
45
45
|
}
|
|
46
46
|
|
|
47
|
+
protected _size: number = 0;
|
|
48
|
+
|
|
49
|
+
get size(): number {
|
|
50
|
+
return this._size;
|
|
51
|
+
}
|
|
52
|
+
|
|
47
53
|
/**
|
|
48
54
|
* The `insert` function inserts a new node with a given key into a red-black tree and fixes any
|
|
49
55
|
* violations of the red-black tree properties.
|
|
@@ -51,7 +57,7 @@ export class RedBlackTree {
|
|
|
51
57
|
* the RBTree.
|
|
52
58
|
* @returns The function does not explicitly return anything.
|
|
53
59
|
*/
|
|
54
|
-
|
|
60
|
+
add(key: number): void {
|
|
55
61
|
const node: RBTreeNode = new RBTreeNode(key, RBTNColor.RED);
|
|
56
62
|
node.left = NIL;
|
|
57
63
|
node.right = NIL;
|
|
@@ -79,20 +85,23 @@ export class RedBlackTree {
|
|
|
79
85
|
|
|
80
86
|
if (node.parent === null) {
|
|
81
87
|
node.color = RBTNColor.BLACK;
|
|
88
|
+
this._size++;
|
|
82
89
|
return;
|
|
83
90
|
}
|
|
84
91
|
|
|
85
92
|
if (node.parent.parent === null) {
|
|
93
|
+
this._size++;
|
|
86
94
|
return;
|
|
87
95
|
}
|
|
88
96
|
|
|
89
97
|
this._fixInsert(node);
|
|
98
|
+
this._size++;
|
|
90
99
|
}
|
|
91
100
|
|
|
92
101
|
/**
|
|
93
102
|
* The `delete` function in TypeScript is used to remove a node with a specific key from a red-black
|
|
94
103
|
* tree.
|
|
95
|
-
* @param {
|
|
104
|
+
* @param {number} key - The `node` parameter is of type `RBTreeNode` and represents the current
|
|
96
105
|
* node being processed in the delete operation.
|
|
97
106
|
* @returns The `delete` function does not return anything. It has a return type of `void`.
|
|
98
107
|
*/
|
|
@@ -113,6 +122,7 @@ export class RedBlackTree {
|
|
|
113
122
|
}
|
|
114
123
|
|
|
115
124
|
if (z === NIL) {
|
|
125
|
+
this._size--;
|
|
116
126
|
return;
|
|
117
127
|
}
|
|
118
128
|
|
|
@@ -144,6 +154,7 @@ export class RedBlackTree {
|
|
|
144
154
|
if (yOriginalColor === RBTNColor.BLACK) {
|
|
145
155
|
this._fixDelete(x);
|
|
146
156
|
}
|
|
157
|
+
this._size--;
|
|
147
158
|
};
|
|
148
159
|
helper(this.root);
|
|
149
160
|
}
|
|
@@ -241,6 +252,11 @@ export class RedBlackTree {
|
|
|
241
252
|
return y;
|
|
242
253
|
}
|
|
243
254
|
|
|
255
|
+
clear() {
|
|
256
|
+
this._root = NIL;
|
|
257
|
+
this._size = 0;
|
|
258
|
+
}
|
|
259
|
+
|
|
244
260
|
print(beginRoot: RBTreeNode = this.root) {
|
|
245
261
|
const display = (root: RBTreeNode | null): void => {
|
|
246
262
|
const [lines, , ,] = _displayAux(root);
|
|
@@ -1,11 +1,11 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* data-structure-typed
|
|
3
3
|
*
|
|
4
|
-
* @author
|
|
5
|
-
* @copyright Copyright (c) 2022
|
|
4
|
+
* @author Tyler Zeng
|
|
5
|
+
* @copyright Copyright (c) 2022 Tyler Zeng <zrwusa@gmail.com>
|
|
6
6
|
* @license MIT License
|
|
7
7
|
*/
|
|
8
|
-
import {
|
|
8
|
+
import {uuidV4} from '../../utils';
|
|
9
9
|
import {PriorityQueue} from '../priority-queue';
|
|
10
10
|
import type {DijkstraResult, VertexKey} from '../../types';
|
|
11
11
|
import {IGraph} from '../../interfaces';
|
|
@@ -223,39 +223,43 @@ export abstract class AbstractGraph<
|
|
|
223
223
|
* @param {VO | VertexKey} v1 - The parameter `v1` represents either a vertex object (`VO`) or a vertex ID (`VertexKey`).
|
|
224
224
|
* It is the starting vertex for finding paths.
|
|
225
225
|
* @param {VO | VertexKey} v2 - The parameter `v2` represents either a vertex object (`VO`) or a vertex ID (`VertexKey`).
|
|
226
|
+
* @param limit - The count of limitation of result array.
|
|
226
227
|
* @returns The function `getAllPathsBetween` returns an array of arrays of vertices (`VO[][]`).
|
|
227
228
|
*/
|
|
228
|
-
getAllPathsBetween(v1: VO | VertexKey, v2: VO | VertexKey): VO[][] {
|
|
229
|
+
getAllPathsBetween(v1: VO | VertexKey, v2: VO | VertexKey, limit = 1000): VO[][] {
|
|
229
230
|
const paths: VO[][] = [];
|
|
230
231
|
const vertex1 = this._getVertex(v1);
|
|
231
232
|
const vertex2 = this._getVertex(v2);
|
|
233
|
+
|
|
232
234
|
if (!(vertex1 && vertex2)) {
|
|
233
235
|
return [];
|
|
234
236
|
}
|
|
235
237
|
|
|
236
|
-
const
|
|
237
|
-
|
|
238
|
+
const stack: { vertex: VO, path: VO[] }[] = [];
|
|
239
|
+
stack.push({ vertex: vertex1, path: [vertex1] });
|
|
240
|
+
|
|
241
|
+
while (stack.length > 0) {
|
|
242
|
+
const { vertex, path } = stack.pop()!;
|
|
238
243
|
|
|
239
|
-
if (
|
|
240
|
-
paths.push(
|
|
244
|
+
if (vertex === vertex2) {
|
|
245
|
+
paths.push(path);
|
|
246
|
+
if (paths.length >= limit) return paths;
|
|
241
247
|
}
|
|
242
248
|
|
|
243
|
-
const neighbors = this.getNeighbors(
|
|
249
|
+
const neighbors = this.getNeighbors(vertex);
|
|
244
250
|
for (const neighbor of neighbors) {
|
|
245
|
-
if (!
|
|
246
|
-
path
|
|
247
|
-
|
|
248
|
-
path.pop();
|
|
251
|
+
if (!path.includes(neighbor)) {
|
|
252
|
+
const newPath = [...path, neighbor];
|
|
253
|
+
stack.push({ vertex: neighbor, path: newPath });
|
|
249
254
|
}
|
|
250
255
|
}
|
|
251
|
-
|
|
252
|
-
visiting.delete(cur);
|
|
253
|
-
};
|
|
254
|
-
|
|
255
|
-
dfs(vertex1, vertex2, new Set<VO>(), []);
|
|
256
|
+
}
|
|
256
257
|
return paths;
|
|
257
258
|
}
|
|
258
259
|
|
|
260
|
+
|
|
261
|
+
|
|
262
|
+
|
|
259
263
|
/**
|
|
260
264
|
* The function calculates the sum of weights along a given path.
|
|
261
265
|
* @param {VO[]} path - An array of vertices (VO) representing a path in a graph.
|
|
@@ -338,38 +342,43 @@ export abstract class AbstractGraph<
|
|
|
338
342
|
* @param {boolean} [isWeight] - A boolean flag indicating whether to consider the weight of edges in finding the
|
|
339
343
|
* minimum path. If set to true, the function will use Dijkstra's algorithm to find the minimum weighted path. If set
|
|
340
344
|
* to false, the function will use breadth-first search (BFS) to find the minimum path.
|
|
345
|
+
* @param isDFS - If set to true, it enforces the use of getAllPathsBetween to first obtain all possible paths,
|
|
346
|
+
* followed by iterative computation of the shortest path. This approach may result in exponential time complexity,
|
|
347
|
+
* so the default method is to use the Dijkstra algorithm to obtain the shortest weighted path.
|
|
341
348
|
* @returns The function `getMinPathBetween` returns an array of vertices (`VO[]`) representing the minimum path between
|
|
342
349
|
* two vertices (`v1` and `v2`). If there is no path between the vertices, it returns `null`.
|
|
343
350
|
*/
|
|
344
|
-
getMinPathBetween(v1: VO | VertexKey, v2: VO | VertexKey, isWeight?: boolean): VO[] | null {
|
|
351
|
+
getMinPathBetween(v1: VO | VertexKey, v2: VO | VertexKey, isWeight?: boolean, isDFS = false): VO[] | null {
|
|
345
352
|
if (isWeight === undefined) isWeight = false;
|
|
346
353
|
|
|
347
354
|
if (isWeight) {
|
|
348
|
-
|
|
349
|
-
|
|
350
|
-
|
|
351
|
-
|
|
352
|
-
|
|
353
|
-
const
|
|
354
|
-
|
|
355
|
-
min
|
|
356
|
-
|
|
355
|
+
if (isDFS) {
|
|
356
|
+
const allPaths = this.getAllPathsBetween(v1, v2, 10000);
|
|
357
|
+
let min = Infinity;
|
|
358
|
+
let minIndex = -1;
|
|
359
|
+
let index = 0;
|
|
360
|
+
for (const path of allPaths) {
|
|
361
|
+
const pathSumWeight = this.getPathSumWeight(path);
|
|
362
|
+
if (pathSumWeight < min) {
|
|
363
|
+
min = pathSumWeight;
|
|
364
|
+
minIndex = index;
|
|
365
|
+
}
|
|
366
|
+
index++;
|
|
357
367
|
}
|
|
358
|
-
|
|
368
|
+
return allPaths[minIndex] || null;
|
|
369
|
+
} else {
|
|
370
|
+
return this.dijkstra(v1, v2, true, true)?.minPath ?? [];
|
|
359
371
|
}
|
|
360
|
-
|
|
372
|
+
|
|
361
373
|
} else {
|
|
362
|
-
//
|
|
374
|
+
// DFS
|
|
363
375
|
let minPath: VO[] = [];
|
|
364
376
|
const vertex1 = this._getVertex(v1);
|
|
365
377
|
const vertex2 = this._getVertex(v2);
|
|
366
|
-
if (!(vertex1 && vertex2))
|
|
367
|
-
return [];
|
|
368
|
-
}
|
|
369
|
-
|
|
370
|
-
const dfs = (cur: VO, dest: VO, visiting: Map<VO, boolean>, path: VO[]) => {
|
|
371
|
-
visiting.set(cur, true);
|
|
378
|
+
if (!(vertex1 && vertex2)) return [];
|
|
372
379
|
|
|
380
|
+
const dfs = (cur: VO, dest: VO, visiting: Set<VO>, path: VO[]) => {
|
|
381
|
+
visiting.add(cur);
|
|
373
382
|
if (cur === dest) {
|
|
374
383
|
minPath = [vertex1, ...path];
|
|
375
384
|
return;
|
|
@@ -377,17 +386,17 @@ export abstract class AbstractGraph<
|
|
|
377
386
|
|
|
378
387
|
const neighbors = this.getNeighbors(cur);
|
|
379
388
|
for (const neighbor of neighbors) {
|
|
380
|
-
if (!visiting.
|
|
389
|
+
if (!visiting.has(neighbor)) {
|
|
381
390
|
path.push(neighbor);
|
|
382
391
|
dfs(neighbor, dest, visiting, path);
|
|
383
|
-
|
|
392
|
+
path.pop();
|
|
384
393
|
}
|
|
385
394
|
}
|
|
386
395
|
|
|
387
|
-
visiting.
|
|
396
|
+
visiting.delete(cur);
|
|
388
397
|
};
|
|
389
398
|
|
|
390
|
-
dfs(vertex1, vertex2, new
|
|
399
|
+
dfs(vertex1, vertex2, new Set<VO>(), []);
|
|
391
400
|
return minPath;
|
|
392
401
|
}
|
|
393
402
|
}
|
|
@@ -4,17 +4,17 @@ import {getRandomIntArray, magnitude} from '../../../utils';
|
|
|
4
4
|
|
|
5
5
|
const suite = new Benchmark.Suite();
|
|
6
6
|
const avl = new AVLTree<number>();
|
|
7
|
-
const {
|
|
8
|
-
const arr = getRandomIntArray(
|
|
7
|
+
const {TEN_THOUSAND} = magnitude;
|
|
8
|
+
const arr = getRandomIntArray(TEN_THOUSAND, 0, TEN_THOUSAND, true);
|
|
9
9
|
|
|
10
10
|
suite
|
|
11
|
-
.add(`${
|
|
11
|
+
.add(`${TEN_THOUSAND.toLocaleString()} add randomly`, () => {
|
|
12
12
|
avl.clear();
|
|
13
13
|
for (let i = 0; i < arr.length; i++) {
|
|
14
14
|
avl.add(arr[i]);
|
|
15
15
|
}
|
|
16
16
|
})
|
|
17
|
-
.add(`${
|
|
17
|
+
.add(`${TEN_THOUSAND.toLocaleString()} add & delete randomly`, () => {
|
|
18
18
|
avl.clear();
|
|
19
19
|
for (let i = 0; i < arr.length; i++) {
|
|
20
20
|
avl.add(arr[i]);
|
|
@@ -23,11 +23,11 @@ suite
|
|
|
23
23
|
avl.delete(arr[i]);
|
|
24
24
|
}
|
|
25
25
|
})
|
|
26
|
-
.add(`${
|
|
26
|
+
.add(`${TEN_THOUSAND.toLocaleString()} addMany`, () => {
|
|
27
27
|
avl.clear();
|
|
28
28
|
avl.addMany(arr);
|
|
29
29
|
})
|
|
30
|
-
.add(`${
|
|
30
|
+
.add(`${TEN_THOUSAND.toLocaleString()} get`, () => {
|
|
31
31
|
for (let i = 0; i < arr.length; i++) {
|
|
32
32
|
avl.get(arr[i]);
|
|
33
33
|
}
|
|
@@ -8,13 +8,13 @@ const {N_LOG_N} = magnitude;
|
|
|
8
8
|
const arr = getRandomIntArray(N_LOG_N, 0, N_LOG_N, true);
|
|
9
9
|
|
|
10
10
|
suite
|
|
11
|
-
.add(`${N_LOG_N} add randomly`, () => {
|
|
11
|
+
.add(`${N_LOG_N.toLocaleString()} add randomly`, () => {
|
|
12
12
|
biTree.clear();
|
|
13
13
|
for (let i = 0; i < arr.length; i++) {
|
|
14
14
|
biTree.add(arr[i]);
|
|
15
15
|
}
|
|
16
16
|
})
|
|
17
|
-
.add(`${N_LOG_N} add & delete randomly`, () => {
|
|
17
|
+
.add(`${N_LOG_N.toLocaleString()} add & delete randomly`, () => {
|
|
18
18
|
biTree.clear();
|
|
19
19
|
for (let i = 0; i < arr.length; i++) {
|
|
20
20
|
biTree.add(arr[i]);
|
|
@@ -23,22 +23,22 @@ suite
|
|
|
23
23
|
biTree.delete(arr[i]);
|
|
24
24
|
}
|
|
25
25
|
})
|
|
26
|
-
.add(`${N_LOG_N} addMany`, () => {
|
|
26
|
+
.add(`${N_LOG_N.toLocaleString()} addMany`, () => {
|
|
27
27
|
biTree.clear();
|
|
28
28
|
biTree.addMany(arr);
|
|
29
29
|
})
|
|
30
|
-
.add(`${N_LOG_N} get`, () => {
|
|
30
|
+
.add(`${N_LOG_N.toLocaleString()} get`, () => {
|
|
31
31
|
for (let i = 0; i < arr.length; i++) {
|
|
32
32
|
biTree.get(arr[i]);
|
|
33
33
|
}
|
|
34
34
|
})
|
|
35
|
-
.add(`${N_LOG_N} dfs`, () => {
|
|
35
|
+
.add(`${N_LOG_N.toLocaleString()} dfs`, () => {
|
|
36
36
|
for (let i = 0; i < N_LOG_N; i++) biTree.dfs();
|
|
37
37
|
})
|
|
38
|
-
.add(`${N_LOG_N} bfs`, () => {
|
|
38
|
+
.add(`${N_LOG_N.toLocaleString()} bfs`, () => {
|
|
39
39
|
for (let i = 0; i < N_LOG_N; i++) biTree.bfs();
|
|
40
40
|
})
|
|
41
|
-
.add(`${N_LOG_N} morris`, () => {
|
|
41
|
+
.add(`${N_LOG_N.toLocaleString()} morris`, () => {
|
|
42
42
|
for (let i = 0; i < N_LOG_N; i++) biTree.morris(n => n, 'pre');
|
|
43
43
|
});
|
|
44
44
|
|
|
@@ -4,17 +4,17 @@ import {getRandomIntArray, magnitude} from '../../../utils';
|
|
|
4
4
|
|
|
5
5
|
const suite = new Benchmark.Suite();
|
|
6
6
|
const bst = new BST<number>();
|
|
7
|
-
const {
|
|
8
|
-
const arr = getRandomIntArray(
|
|
7
|
+
const {TEN_THOUSAND} = magnitude;
|
|
8
|
+
const arr = getRandomIntArray(TEN_THOUSAND, 0, TEN_THOUSAND, true);
|
|
9
9
|
|
|
10
10
|
suite
|
|
11
|
-
.add(`${
|
|
11
|
+
.add(`${TEN_THOUSAND.toLocaleString()} add randomly`, () => {
|
|
12
12
|
bst.clear();
|
|
13
13
|
for (let i = 0; i < arr.length; i++) {
|
|
14
14
|
bst.add(arr[i]);
|
|
15
15
|
}
|
|
16
16
|
})
|
|
17
|
-
.add(`${
|
|
17
|
+
.add(`${TEN_THOUSAND.toLocaleString()} add & delete randomly`, () => {
|
|
18
18
|
bst.clear();
|
|
19
19
|
for (let i = 0; i < arr.length; i++) {
|
|
20
20
|
bst.add(arr[i]);
|
|
@@ -23,11 +23,11 @@ suite
|
|
|
23
23
|
bst.delete(arr[i]);
|
|
24
24
|
}
|
|
25
25
|
})
|
|
26
|
-
.add(`${
|
|
26
|
+
.add(`${TEN_THOUSAND.toLocaleString()} addMany`, () => {
|
|
27
27
|
bst.clear();
|
|
28
28
|
bst.addMany(arr);
|
|
29
29
|
})
|
|
30
|
-
.add(`${
|
|
30
|
+
.add(`${TEN_THOUSAND.toLocaleString()} get`, () => {
|
|
31
31
|
for (let i = 0; i < arr.length; i++) {
|
|
32
32
|
bst.get(arr[i]);
|
|
33
33
|
}
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
import {RedBlackTree} from '../../../../src';
|
|
2
|
+
import * as Benchmark from 'benchmark';
|
|
3
|
+
import {getRandomIntArray, magnitude} from '../../../utils';
|
|
4
|
+
|
|
5
|
+
const suite = new Benchmark.Suite();
|
|
6
|
+
const rbTree = new RedBlackTree();
|
|
7
|
+
const {HUNDRED_THOUSAND} = magnitude;
|
|
8
|
+
const arr = getRandomIntArray(HUNDRED_THOUSAND, 0, HUNDRED_THOUSAND, true);
|
|
9
|
+
|
|
10
|
+
suite
|
|
11
|
+
.add(`${HUNDRED_THOUSAND.toLocaleString()} add randomly`, () => {
|
|
12
|
+
rbTree.clear();
|
|
13
|
+
for (let i = 0; i < arr.length; i++) {
|
|
14
|
+
rbTree.add(arr[i]);
|
|
15
|
+
}
|
|
16
|
+
})
|
|
17
|
+
.add(`${HUNDRED_THOUSAND.toLocaleString()} add & 1000 delete randomly`, () => {
|
|
18
|
+
rbTree.clear();
|
|
19
|
+
for (let i = 0; i < arr.length; i++) {
|
|
20
|
+
rbTree.add(arr[i]);
|
|
21
|
+
}
|
|
22
|
+
for (let i = 0; i < 1000; i++) {
|
|
23
|
+
rbTree.delete(arr[i]);
|
|
24
|
+
}
|
|
25
|
+
})
|
|
26
|
+
.add(`${HUNDRED_THOUSAND.toLocaleString()} getNode`, () => {
|
|
27
|
+
for (let i = 0; i < arr.length; i++) {
|
|
28
|
+
rbTree.getNode(arr[i]);
|
|
29
|
+
}
|
|
30
|
+
});
|
|
31
|
+
|
|
32
|
+
export {suite};
|
|
@@ -8,24 +8,24 @@ const graph = new DirectedGraph<number, number>();
|
|
|
8
8
|
const vertexes = getRandomWords(THOUSAND);
|
|
9
9
|
|
|
10
10
|
suite
|
|
11
|
-
.add(`${THOUSAND} addVertex`, () => {
|
|
11
|
+
.add(`${THOUSAND.toLocaleString()} addVertex`, () => {
|
|
12
12
|
for (const v of vertexes) {
|
|
13
13
|
graph.addVertex(v);
|
|
14
14
|
}
|
|
15
15
|
})
|
|
16
|
-
.add(`${THOUSAND} addEdge`, () => {
|
|
16
|
+
.add(`${THOUSAND.toLocaleString()} addEdge`, () => {
|
|
17
17
|
for (let i = 0; i < THOUSAND; i++) {
|
|
18
18
|
const v1 = vertexes[getRandomIndex(vertexes)];
|
|
19
19
|
const v2 = vertexes[getRandomIndex(vertexes)];
|
|
20
20
|
graph.addEdge(v1, v2);
|
|
21
21
|
}
|
|
22
22
|
})
|
|
23
|
-
.add(`${THOUSAND} getVertex`, () => {
|
|
23
|
+
.add(`${THOUSAND.toLocaleString()} getVertex`, () => {
|
|
24
24
|
for (let i = 0; i < THOUSAND; i++) {
|
|
25
25
|
graph.getVertex(vertexes[getRandomIndex(vertexes)]);
|
|
26
26
|
}
|
|
27
27
|
})
|
|
28
|
-
.add(`${THOUSAND} getEdge`, () => {
|
|
28
|
+
.add(`${THOUSAND.toLocaleString()} getEdge`, () => {
|
|
29
29
|
for (let i = 0; i < THOUSAND; i++) {
|
|
30
30
|
graph.getEdge(vertexes[getRandomIndex(vertexes)], vertexes[getRandomIndex(vertexes)]);
|
|
31
31
|
}
|
|
@@ -3,26 +3,26 @@ import * as Benchmark from 'benchmark';
|
|
|
3
3
|
import {magnitude} from '../../../utils';
|
|
4
4
|
|
|
5
5
|
const suite = new Benchmark.Suite();
|
|
6
|
-
const {
|
|
6
|
+
const {TEN_THOUSAND} = magnitude;
|
|
7
7
|
|
|
8
8
|
suite
|
|
9
|
-
.add(`${
|
|
9
|
+
.add(`${TEN_THOUSAND.toLocaleString()} add & pop`, () => {
|
|
10
10
|
const heap = new Heap<number>({comparator: (a, b) => b - a});
|
|
11
11
|
|
|
12
|
-
for (let i = 0; i <
|
|
12
|
+
for (let i = 0; i < TEN_THOUSAND; i++) {
|
|
13
13
|
heap.add(i);
|
|
14
14
|
}
|
|
15
15
|
|
|
16
|
-
for (let i = 0; i <
|
|
16
|
+
for (let i = 0; i < TEN_THOUSAND; i++) {
|
|
17
17
|
heap.pop();
|
|
18
18
|
}
|
|
19
19
|
})
|
|
20
|
-
.add(`${
|
|
20
|
+
.add(`${TEN_THOUSAND.toLocaleString()} fib add & pop`, () => {
|
|
21
21
|
const fbHeap = new FibonacciHeap<number>();
|
|
22
|
-
for (let i = 1; i <=
|
|
22
|
+
for (let i = 1; i <= TEN_THOUSAND; i++) {
|
|
23
23
|
fbHeap.push(i);
|
|
24
24
|
}
|
|
25
|
-
for (let i = 1; i <=
|
|
25
|
+
for (let i = 1; i <= TEN_THOUSAND; i++) {
|
|
26
26
|
fbHeap.pop();
|
|
27
27
|
}
|
|
28
28
|
});
|
|
@@ -3,17 +3,17 @@ import * as Benchmark from 'benchmark';
|
|
|
3
3
|
import {magnitude} from '../../../utils';
|
|
4
4
|
|
|
5
5
|
const suite = new Benchmark.Suite();
|
|
6
|
-
const {LINEAR
|
|
6
|
+
const {LINEAR} = magnitude;
|
|
7
7
|
|
|
8
8
|
suite
|
|
9
|
-
.add(`${LINEAR} unshift`, () => {
|
|
9
|
+
.add(`${LINEAR.toLocaleString()} unshift`, () => {
|
|
10
10
|
const list = new DoublyLinkedList<number>();
|
|
11
11
|
|
|
12
12
|
for (let i = 0; i < LINEAR; i++) {
|
|
13
13
|
list.unshift(i);
|
|
14
14
|
}
|
|
15
15
|
})
|
|
16
|
-
.add(`${LINEAR} unshift & shift`, () => {
|
|
16
|
+
.add(`${LINEAR.toLocaleString()} unshift & shift`, () => {
|
|
17
17
|
const list = new DoublyLinkedList<number>();
|
|
18
18
|
|
|
19
19
|
for (let i = 0; i < LINEAR; i++) {
|
|
@@ -23,11 +23,11 @@ suite
|
|
|
23
23
|
list.shift();
|
|
24
24
|
}
|
|
25
25
|
})
|
|
26
|
-
.add(`${
|
|
26
|
+
.add(`${LINEAR.toLocaleString()} insertBefore`, () => {
|
|
27
27
|
const doublyList = new DoublyLinkedList<number>();
|
|
28
28
|
let midNode: DoublyLinkedListNode | null = null;
|
|
29
|
-
const midIndex = Math.floor(
|
|
30
|
-
for (let i = 0; i <
|
|
29
|
+
const midIndex = Math.floor(LINEAR / 2);
|
|
30
|
+
for (let i = 0; i < LINEAR; i++) {
|
|
31
31
|
doublyList.push(i);
|
|
32
32
|
if (i === midIndex) {
|
|
33
33
|
midNode = doublyList.getNode(i);
|
|
@@ -3,25 +3,25 @@ import * as Benchmark from 'benchmark';
|
|
|
3
3
|
import {magnitude} from '../../../utils';
|
|
4
4
|
|
|
5
5
|
const suite = new Benchmark.Suite();
|
|
6
|
-
const {
|
|
6
|
+
const {TEN_THOUSAND} = magnitude;
|
|
7
7
|
|
|
8
8
|
suite
|
|
9
|
-
.add(`${
|
|
9
|
+
.add(`${TEN_THOUSAND.toLocaleString()} push & pop`, () => {
|
|
10
10
|
const list = new SinglyLinkedList<number>();
|
|
11
11
|
|
|
12
|
-
for (let i = 0; i <
|
|
12
|
+
for (let i = 0; i < TEN_THOUSAND; i++) {
|
|
13
13
|
list.push(i);
|
|
14
14
|
}
|
|
15
15
|
|
|
16
|
-
for (let i = 0; i <
|
|
16
|
+
for (let i = 0; i < TEN_THOUSAND; i++) {
|
|
17
17
|
list.pop();
|
|
18
18
|
}
|
|
19
19
|
})
|
|
20
|
-
.add(`${
|
|
20
|
+
.add(`${TEN_THOUSAND.toLocaleString()} insertBefore`, () => {
|
|
21
21
|
const singlyList = new SinglyLinkedList<number>();
|
|
22
22
|
let midSinglyNode: SinglyLinkedListNode | null = null;
|
|
23
|
-
const midIndex = Math.floor(
|
|
24
|
-
for (let i = 0; i <
|
|
23
|
+
const midIndex = Math.floor(TEN_THOUSAND / 2);
|
|
24
|
+
for (let i = 0; i < TEN_THOUSAND; i++) {
|
|
25
25
|
singlyList.push(i);
|
|
26
26
|
if (i === midIndex) {
|
|
27
27
|
midSinglyNode = singlyList.getNode(i);
|
|
@@ -5,7 +5,7 @@ import {magnitude} from '../../../utils';
|
|
|
5
5
|
const suite = new Benchmark.Suite();
|
|
6
6
|
const {TEN_THOUSAND} = magnitude;
|
|
7
7
|
|
|
8
|
-
suite.add(`${TEN_THOUSAND} refill & poll`, () => {
|
|
8
|
+
suite.add(`${TEN_THOUSAND.toLocaleString()} refill & poll`, () => {
|
|
9
9
|
const nodes = Array.from(
|
|
10
10
|
new Set<number>(Array.from(new Array(TEN_THOUSAND), () => Math.floor(Math.random() * TEN_THOUSAND * 100)))
|
|
11
11
|
);
|
|
@@ -6,13 +6,13 @@ export const suite = new Benchmark.Suite();
|
|
|
6
6
|
const {LINEAR} = magnitude;
|
|
7
7
|
|
|
8
8
|
suite
|
|
9
|
-
.add(`${LINEAR} push`, () => {
|
|
9
|
+
.add(`${LINEAR.toLocaleString()} push`, () => {
|
|
10
10
|
const deque = new Deque<number>();
|
|
11
11
|
for (let i = 0; i < LINEAR; i++) {
|
|
12
12
|
deque.push(i);
|
|
13
13
|
}
|
|
14
14
|
})
|
|
15
|
-
.add(`${LINEAR} shift`, () => {
|
|
15
|
+
.add(`${LINEAR.toLocaleString()} shift`, () => {
|
|
16
16
|
const deque = new Deque<number>();
|
|
17
17
|
for (let i = 0; i < LINEAR; i++) {
|
|
18
18
|
deque.push(i);
|
|
@@ -6,14 +6,14 @@ const suite = new Benchmark.Suite();
|
|
|
6
6
|
const {LINEAR} = magnitude;
|
|
7
7
|
|
|
8
8
|
suite
|
|
9
|
-
.add(`${LINEAR} push`, () => {
|
|
9
|
+
.add(`${LINEAR.toLocaleString()} push`, () => {
|
|
10
10
|
const queue = new Queue<number>();
|
|
11
11
|
|
|
12
12
|
for (let i = 0; i < LINEAR; i++) {
|
|
13
13
|
queue.push(i);
|
|
14
14
|
}
|
|
15
15
|
})
|
|
16
|
-
.add(`${LINEAR} push & shift`, () => {
|
|
16
|
+
.add(`${LINEAR.toLocaleString()} push & shift`, () => {
|
|
17
17
|
const queue = new Queue<number>();
|
|
18
18
|
|
|
19
19
|
for (let i = 0; i < LINEAR; i++) {
|
|
@@ -8,12 +8,12 @@ const trie = new Trie();
|
|
|
8
8
|
const randomWords = getRandomWords(HUNDRED_THOUSAND, false);
|
|
9
9
|
|
|
10
10
|
suite
|
|
11
|
-
.add(`${HUNDRED_THOUSAND} push`, () => {
|
|
11
|
+
.add(`${HUNDRED_THOUSAND.toLocaleString()} push`, () => {
|
|
12
12
|
for (let i = 0; i < randomWords.length; i++) {
|
|
13
13
|
trie.add(randomWords[i]);
|
|
14
14
|
}
|
|
15
15
|
})
|
|
16
|
-
.add(`${HUNDRED_THOUSAND} getWords`, () => {
|
|
16
|
+
.add(`${HUNDRED_THOUSAND.toLocaleString()} getWords`, () => {
|
|
17
17
|
for (let i = 0; i < randomWords.length; i++) {
|
|
18
18
|
trie.getWords(randomWords[i]);
|
|
19
19
|
}
|
|
@@ -126,11 +126,10 @@ function replaceMarkdownContent(startMarker: string, endMarker: string, newText:
|
|
|
126
126
|
}
|
|
127
127
|
|
|
128
128
|
// Replace the old content with the new text
|
|
129
|
-
const updatedMarkdown =
|
|
130
|
-
data.slice(0, startIndex + startMarker.length) + '\n' + newText + data.slice(endIndex);
|
|
129
|
+
const updatedMarkdown = data.slice(0, startIndex + startMarker.length) + '\n' + newText + data.slice(endIndex);
|
|
131
130
|
|
|
132
131
|
// Try writing the modified content back to the file
|
|
133
|
-
fs.writeFile(filePath, updatedMarkdown, 'utf8',
|
|
132
|
+
fs.writeFile(filePath, updatedMarkdown, 'utf8', err => {
|
|
134
133
|
if (err) {
|
|
135
134
|
console.error(`Unable to write to ${filePath}:`, err);
|
|
136
135
|
} else {
|
|
@@ -145,7 +144,7 @@ performanceTests.forEach(item => {
|
|
|
145
144
|
const relativeFilePath = path.relative(__dirname, file);
|
|
146
145
|
const directory = path.dirname(relativeFilePath);
|
|
147
146
|
const fileName = path.basename(relativeFilePath);
|
|
148
|
-
console.log(`${BG_YELLOW}Running
|
|
147
|
+
console.log(`${BG_YELLOW} Running ${END} ${GRAY}${directory}/${END}${CYAN}${fileName}${END}`);
|
|
149
148
|
|
|
150
149
|
if (suite) {
|
|
151
150
|
let runTime = 0;
|
|
@@ -159,8 +158,8 @@ performanceTests.forEach(item => {
|
|
|
159
158
|
'test name': benchmark.name,
|
|
160
159
|
'time taken (ms)': numberFix(benchmark.times.period * 1000, 2),
|
|
161
160
|
'executions per sec': numberFix(benchmark.hz, 2),
|
|
162
|
-
'executed times': numberFix(benchmark.count, 0),
|
|
163
|
-
'sample mean (secs)': numberFix(benchmark.stats.mean, 2),
|
|
161
|
+
// 'executed times': numberFix(benchmark.count, 0),
|
|
162
|
+
// 'sample mean (secs)': numberFix(benchmark.stats.mean, 2),
|
|
164
163
|
'sample deviation': numberFix(benchmark.stats.deviation, 2)
|
|
165
164
|
};
|
|
166
165
|
});
|