min-heap-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.
@@ -26,6 +26,8 @@ export declare class RedBlackTree {
26
26
  constructor();
27
27
  protected _root: RBTreeNode;
28
28
  get root(): RBTreeNode;
29
+ protected _size: number;
30
+ get size(): number;
29
31
  /**
30
32
  * The `insert` function inserts a new node with a given key into a red-black tree and fixes any
31
33
  * violations of the red-black tree properties.
@@ -33,11 +35,11 @@ export declare class RedBlackTree {
33
35
  * the RBTree.
34
36
  * @returns The function does not explicitly return anything.
35
37
  */
36
- insert(key: number): void;
38
+ add(key: number): void;
37
39
  /**
38
40
  * The `delete` function in TypeScript is used to remove a node with a specific key from a red-black
39
41
  * tree.
40
- * @param {RBTreeNode} node - The `node` parameter is of type `RBTreeNode` and represents the current
42
+ * @param {number} key - The `node` parameter is of type `RBTreeNode` and represents the current
41
43
  * node being processed in the delete operation.
42
44
  * @returns The `delete` function does not return anything. It has a return type of `void`.
43
45
  */
@@ -80,6 +82,7 @@ export declare class RedBlackTree {
80
82
  * @returns the predecessor of the given RBTreeNode 'x'.
81
83
  */
82
84
  getPredecessor(x: RBTreeNode): RBTreeNode;
85
+ clear(): void;
83
86
  print(beginRoot?: RBTreeNode): void;
84
87
  /**
85
88
  * The function performs a left rotation on a red-black tree node.
@@ -30,11 +30,15 @@ exports.NIL = new RBTreeNode(0);
30
30
  */
31
31
  class RedBlackTree {
32
32
  constructor() {
33
+ this._size = 0;
33
34
  this._root = exports.NIL;
34
35
  }
35
36
  get root() {
36
37
  return this._root;
37
38
  }
39
+ get size() {
40
+ return this._size;
41
+ }
38
42
  /**
39
43
  * The `insert` function inserts a new node with a given key into a red-black tree and fixes any
40
44
  * violations of the red-black tree properties.
@@ -42,7 +46,7 @@ class RedBlackTree {
42
46
  * the RBTree.
43
47
  * @returns The function does not explicitly return anything.
44
48
  */
45
- insert(key) {
49
+ add(key) {
46
50
  const node = new RBTreeNode(key, types_1.RBTNColor.RED);
47
51
  node.left = exports.NIL;
48
52
  node.right = exports.NIL;
@@ -69,17 +73,20 @@ class RedBlackTree {
69
73
  }
70
74
  if (node.parent === null) {
71
75
  node.color = types_1.RBTNColor.BLACK;
76
+ this._size++;
72
77
  return;
73
78
  }
74
79
  if (node.parent.parent === null) {
80
+ this._size++;
75
81
  return;
76
82
  }
77
83
  this._fixInsert(node);
84
+ this._size++;
78
85
  }
79
86
  /**
80
87
  * The `delete` function in TypeScript is used to remove a node with a specific key from a red-black
81
88
  * tree.
82
- * @param {RBTreeNode} node - The `node` parameter is of type `RBTreeNode` and represents the current
89
+ * @param {number} key - The `node` parameter is of type `RBTreeNode` and represents the current
83
90
  * node being processed in the delete operation.
84
91
  * @returns The `delete` function does not return anything. It has a return type of `void`.
85
92
  */
@@ -99,6 +106,7 @@ class RedBlackTree {
99
106
  }
100
107
  }
101
108
  if (z === exports.NIL) {
109
+ this._size--;
102
110
  return;
103
111
  }
104
112
  y = z;
@@ -131,6 +139,7 @@ class RedBlackTree {
131
139
  if (yOriginalColor === types_1.RBTNColor.BLACK) {
132
140
  this._fixDelete(x);
133
141
  }
142
+ this._size--;
134
143
  };
135
144
  helper(this.root);
136
145
  }
@@ -219,6 +228,10 @@ class RedBlackTree {
219
228
  }
220
229
  return y;
221
230
  }
231
+ clear() {
232
+ this._root = exports.NIL;
233
+ this._size = 0;
234
+ }
222
235
  print(beginRoot = this.root) {
223
236
  const display = (root) => {
224
237
  const [lines, , ,] = _displayAux(root);
@@ -114,9 +114,10 @@ export declare abstract class AbstractGraph<V = any, E = any, VO extends Abstrac
114
114
  * @param {VO | VertexKey} v1 - The parameter `v1` represents either a vertex object (`VO`) or a vertex ID (`VertexKey`).
115
115
  * It is the starting vertex for finding paths.
116
116
  * @param {VO | VertexKey} v2 - The parameter `v2` represents either a vertex object (`VO`) or a vertex ID (`VertexKey`).
117
+ * @param limit - The count of limitation of result array.
117
118
  * @returns The function `getAllPathsBetween` returns an array of arrays of vertices (`VO[][]`).
118
119
  */
119
- getAllPathsBetween(v1: VO | VertexKey, v2: VO | VertexKey): VO[][];
120
+ getAllPathsBetween(v1: VO | VertexKey, v2: VO | VertexKey, limit?: number): VO[][];
120
121
  /**
121
122
  * The function calculates the sum of weights along a given path.
122
123
  * @param {VO[]} path - An array of vertices (VO) representing a path in a graph.
@@ -148,10 +149,13 @@ export declare abstract class AbstractGraph<V = any, E = any, VO extends Abstrac
148
149
  * @param {boolean} [isWeight] - A boolean flag indicating whether to consider the weight of edges in finding the
149
150
  * minimum path. If set to true, the function will use Dijkstra's algorithm to find the minimum weighted path. If set
150
151
  * to false, the function will use breadth-first search (BFS) to find the minimum path.
152
+ * @param isDFS - If set to true, it enforces the use of getAllPathsBetween to first obtain all possible paths,
153
+ * followed by iterative computation of the shortest path. This approach may result in exponential time complexity,
154
+ * so the default method is to use the Dijkstra algorithm to obtain the shortest weighted path.
151
155
  * @returns The function `getMinPathBetween` returns an array of vertices (`VO[]`) representing the minimum path between
152
156
  * two vertices (`v1` and `v2`). If there is no path between the vertices, it returns `null`.
153
157
  */
154
- getMinPathBetween(v1: VO | VertexKey, v2: VO | VertexKey, isWeight?: boolean): VO[] | null;
158
+ getMinPathBetween(v1: VO | VertexKey, v2: VO | VertexKey, isWeight?: boolean, isDFS?: boolean): VO[] | null;
155
159
  /**
156
160
  * Dijkstra algorithm time: O(VE) space: O(VO + EO)
157
161
  * /
@@ -4,8 +4,8 @@ exports.AbstractGraph = exports.AbstractEdge = exports.AbstractVertex = void 0;
4
4
  /**
5
5
  * data-structure-typed
6
6
  *
7
- * @author Kirk Qi
8
- * @copyright Copyright (c) 2022 Kirk Qi <qilinaus@gmail.com>
7
+ * @author Tyler Zeng
8
+ * @copyright Copyright (c) 2022 Tyler Zeng <zrwusa@gmail.com>
9
9
  * @license MIT License
10
10
  */
11
11
  const utils_1 = require("../../utils");
@@ -162,31 +162,33 @@ class AbstractGraph {
162
162
  * @param {VO | VertexKey} v1 - The parameter `v1` represents either a vertex object (`VO`) or a vertex ID (`VertexKey`).
163
163
  * It is the starting vertex for finding paths.
164
164
  * @param {VO | VertexKey} v2 - The parameter `v2` represents either a vertex object (`VO`) or a vertex ID (`VertexKey`).
165
+ * @param limit - The count of limitation of result array.
165
166
  * @returns The function `getAllPathsBetween` returns an array of arrays of vertices (`VO[][]`).
166
167
  */
167
- getAllPathsBetween(v1, v2) {
168
+ getAllPathsBetween(v1, v2, limit = 1000) {
168
169
  const paths = [];
169
170
  const vertex1 = this._getVertex(v1);
170
171
  const vertex2 = this._getVertex(v2);
171
172
  if (!(vertex1 && vertex2)) {
172
173
  return [];
173
174
  }
174
- const dfs = (cur, dest, visiting, path) => {
175
- visiting.add(cur);
176
- if (cur === dest) {
177
- paths.push([vertex1, ...path]);
175
+ const stack = [];
176
+ stack.push({ vertex: vertex1, path: [vertex1] });
177
+ while (stack.length > 0) {
178
+ const { vertex, path } = stack.pop();
179
+ if (vertex === vertex2) {
180
+ paths.push(path);
181
+ if (paths.length >= limit)
182
+ return paths;
178
183
  }
179
- const neighbors = this.getNeighbors(cur);
184
+ const neighbors = this.getNeighbors(vertex);
180
185
  for (const neighbor of neighbors) {
181
- if (!visiting.has(neighbor)) {
182
- path.push(neighbor);
183
- dfs(neighbor, dest, visiting, path);
184
- path.pop();
186
+ if (!path.includes(neighbor)) {
187
+ const newPath = [...path, neighbor];
188
+ stack.push({ vertex: neighbor, path: newPath });
185
189
  }
186
190
  }
187
- visiting.delete(cur);
188
- };
189
- dfs(vertex1, vertex2, new Set(), []);
191
+ }
190
192
  return paths;
191
193
  }
192
194
  /**
@@ -270,52 +272,60 @@ class AbstractGraph {
270
272
  * @param {boolean} [isWeight] - A boolean flag indicating whether to consider the weight of edges in finding the
271
273
  * minimum path. If set to true, the function will use Dijkstra's algorithm to find the minimum weighted path. If set
272
274
  * to false, the function will use breadth-first search (BFS) to find the minimum path.
275
+ * @param isDFS - If set to true, it enforces the use of getAllPathsBetween to first obtain all possible paths,
276
+ * followed by iterative computation of the shortest path. This approach may result in exponential time complexity,
277
+ * so the default method is to use the Dijkstra algorithm to obtain the shortest weighted path.
273
278
  * @returns The function `getMinPathBetween` returns an array of vertices (`VO[]`) representing the minimum path between
274
279
  * two vertices (`v1` and `v2`). If there is no path between the vertices, it returns `null`.
275
280
  */
276
- getMinPathBetween(v1, v2, isWeight) {
281
+ getMinPathBetween(v1, v2, isWeight, isDFS = false) {
282
+ var _a, _b;
277
283
  if (isWeight === undefined)
278
284
  isWeight = false;
279
285
  if (isWeight) {
280
- const allPaths = this.getAllPathsBetween(v1, v2);
281
- let min = Infinity;
282
- let minIndex = -1;
283
- let index = 0;
284
- for (const path of allPaths) {
285
- const pathSumWeight = this.getPathSumWeight(path);
286
- if (pathSumWeight < min) {
287
- min = pathSumWeight;
288
- minIndex = index;
286
+ if (isDFS) {
287
+ const allPaths = this.getAllPathsBetween(v1, v2, 10000);
288
+ let min = Infinity;
289
+ let minIndex = -1;
290
+ let index = 0;
291
+ for (const path of allPaths) {
292
+ const pathSumWeight = this.getPathSumWeight(path);
293
+ if (pathSumWeight < min) {
294
+ min = pathSumWeight;
295
+ minIndex = index;
296
+ }
297
+ index++;
289
298
  }
290
- index++;
299
+ return allPaths[minIndex] || null;
300
+ }
301
+ else {
302
+ return (_b = (_a = this.dijkstra(v1, v2, true, true)) === null || _a === void 0 ? void 0 : _a.minPath) !== null && _b !== void 0 ? _b : [];
291
303
  }
292
- return allPaths[minIndex] || null;
293
304
  }
294
305
  else {
295
- // BFS
306
+ // DFS
296
307
  let minPath = [];
297
308
  const vertex1 = this._getVertex(v1);
298
309
  const vertex2 = this._getVertex(v2);
299
- if (!(vertex1 && vertex2)) {
310
+ if (!(vertex1 && vertex2))
300
311
  return [];
301
- }
302
312
  const dfs = (cur, dest, visiting, path) => {
303
- visiting.set(cur, true);
313
+ visiting.add(cur);
304
314
  if (cur === dest) {
305
315
  minPath = [vertex1, ...path];
306
316
  return;
307
317
  }
308
318
  const neighbors = this.getNeighbors(cur);
309
319
  for (const neighbor of neighbors) {
310
- if (!visiting.get(neighbor)) {
320
+ if (!visiting.has(neighbor)) {
311
321
  path.push(neighbor);
312
322
  dfs(neighbor, dest, visiting, path);
313
- (0, utils_1.arrayRemove)(path, (vertex) => vertex === neighbor);
323
+ path.pop();
314
324
  }
315
325
  }
316
- visiting.set(cur, false);
326
+ visiting.delete(cur);
317
327
  };
318
- dfs(vertex1, vertex2, new Map(), []);
328
+ dfs(vertex1, vertex2, new Set(), []);
319
329
  return minPath;
320
330
  }
321
331
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "min-heap-typed",
3
- "version": "1.41.7",
3
+ "version": "1.41.9",
4
4
  "description": "Min Heap. Javascript & Typescript Data Structure.",
5
5
  "main": "dist/index.js",
6
6
  "scripts": {
@@ -132,6 +132,6 @@
132
132
  "typescript": "^4.9.5"
133
133
  },
134
134
  "dependencies": {
135
- "data-structure-typed": "^1.41.7"
135
+ "data-structure-typed": "^1.41.9"
136
136
  }
137
137
  }
@@ -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
- insert(key: number): void {
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 {RBTreeNode} node - The `node` parameter is of type `RBTreeNode` and represents the current
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 Kirk Qi
5
- * @copyright Copyright (c) 2022 Kirk Qi <qilinaus@gmail.com>
4
+ * @author Tyler Zeng
5
+ * @copyright Copyright (c) 2022 Tyler Zeng <zrwusa@gmail.com>
6
6
  * @license MIT License
7
7
  */
8
- import {arrayRemove, uuidV4} from '../../utils';
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 dfs = (cur: VO, dest: VO, visiting: Set<VO>, path: VO[]) => {
237
- visiting.add(cur);
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 (cur === dest) {
240
- paths.push([vertex1, ...path]);
244
+ if (vertex === vertex2) {
245
+ paths.push(path);
246
+ if (paths.length >= limit) return paths;
241
247
  }
242
248
 
243
- const neighbors = this.getNeighbors(cur);
249
+ const neighbors = this.getNeighbors(vertex);
244
250
  for (const neighbor of neighbors) {
245
- if (!visiting.has(neighbor)) {
246
- path.push(neighbor);
247
- dfs(neighbor, dest, visiting, path);
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
- const allPaths = this.getAllPathsBetween(v1, v2);
349
- let min = Infinity;
350
- let minIndex = -1;
351
- let index = 0;
352
- for (const path of allPaths) {
353
- const pathSumWeight = this.getPathSumWeight(path);
354
- if (pathSumWeight < min) {
355
- min = pathSumWeight;
356
- minIndex = index;
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
- index++;
368
+ return allPaths[minIndex] || null;
369
+ } else {
370
+ return this.dijkstra(v1, v2, true, true)?.minPath ?? [];
359
371
  }
360
- return allPaths[minIndex] || null;
372
+
361
373
  } else {
362
- // BFS
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.get(neighbor)) {
389
+ if (!visiting.has(neighbor)) {
381
390
  path.push(neighbor);
382
391
  dfs(neighbor, dest, visiting, path);
383
- arrayRemove(path, (vertex: VO) => vertex === neighbor);
392
+ path.pop();
384
393
  }
385
394
  }
386
395
 
387
- visiting.set(cur, false);
396
+ visiting.delete(cur);
388
397
  };
389
398
 
390
- dfs(vertex1, vertex2, new Map<VO, boolean>(), []);
399
+ dfs(vertex1, vertex2, new Set<VO>(), []);
391
400
  return minPath;
392
401
  }
393
402
  }