undirected-graph-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/dist/common/index.d.ts +12 -0
- package/dist/common/index.js +28 -0
- package/dist/data-structures/binary-tree/avl-tree-multi-map.d.ts +1 -1
- package/dist/data-structures/binary-tree/avl-tree-multi-map.js +9 -12
- package/dist/data-structures/binary-tree/avl-tree.js +2 -2
- package/dist/data-structures/binary-tree/binary-tree.d.ts +55 -20
- package/dist/data-structures/binary-tree/binary-tree.js +102 -68
- package/dist/data-structures/binary-tree/bst.d.ts +131 -37
- package/dist/data-structures/binary-tree/bst.js +222 -69
- package/dist/data-structures/binary-tree/index.d.ts +1 -1
- package/dist/data-structures/binary-tree/index.js +1 -1
- package/dist/data-structures/binary-tree/{rb-tree.d.ts → red-black-tree.d.ts} +53 -0
- package/dist/data-structures/binary-tree/{rb-tree.js → red-black-tree.js} +56 -3
- package/dist/data-structures/binary-tree/tree-multi-map.d.ts +2 -2
- package/dist/data-structures/binary-tree/tree-multi-map.js +7 -7
- package/dist/data-structures/hash/hash-map.d.ts +30 -0
- package/dist/data-structures/hash/hash-map.js +30 -0
- package/dist/data-structures/heap/heap.d.ts +26 -9
- package/dist/data-structures/heap/heap.js +37 -17
- package/dist/data-structures/linked-list/doubly-linked-list.d.ts +54 -9
- package/dist/data-structures/linked-list/doubly-linked-list.js +80 -19
- package/dist/data-structures/linked-list/singly-linked-list.d.ts +35 -2
- package/dist/data-structures/linked-list/singly-linked-list.js +55 -11
- package/dist/data-structures/queue/deque.d.ts +37 -8
- package/dist/data-structures/queue/deque.js +73 -29
- package/dist/data-structures/queue/queue.d.ts +41 -1
- package/dist/data-structures/queue/queue.js +51 -9
- package/dist/data-structures/stack/stack.d.ts +27 -10
- package/dist/data-structures/stack/stack.js +39 -20
- package/dist/data-structures/trie/trie.d.ts +111 -6
- package/dist/data-structures/trie/trie.js +123 -14
- package/dist/index.d.ts +2 -1
- package/dist/index.js +2 -1
- package/dist/types/data-structures/binary-tree/binary-tree.d.ts +1 -1
- package/dist/types/data-structures/binary-tree/bst.d.ts +3 -2
- package/dist/types/data-structures/binary-tree/rb-tree.d.ts +1 -1
- package/dist/types/utils/utils.d.ts +10 -6
- package/dist/utils/utils.js +4 -2
- package/package.json +2 -2
- 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 +2 -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
|
@@ -4,6 +4,7 @@ exports.BST = exports.BSTNode = void 0;
|
|
|
4
4
|
const binary_tree_1 = require("./binary-tree");
|
|
5
5
|
const queue_1 = require("../queue");
|
|
6
6
|
const utils_1 = require("../../utils");
|
|
7
|
+
const common_1 = require("../../common");
|
|
7
8
|
class BSTNode extends binary_tree_1.BinaryTreeNode {
|
|
8
9
|
constructor(key, value) {
|
|
9
10
|
super(key, value);
|
|
@@ -58,6 +59,62 @@ exports.BSTNode = BSTNode;
|
|
|
58
59
|
* 5. Logarithmic Operations: Ideal operations like insertion, deletion, and searching are O(log n) time-efficient.
|
|
59
60
|
* 6. Balance Variability: Can become unbalanced; special types maintain balance.
|
|
60
61
|
* 7. No Auto-Balancing: Standard BSTs don't automatically balance themselves.
|
|
62
|
+
* @example
|
|
63
|
+
* // Merge 3 sorted datasets
|
|
64
|
+
* const dataset1 = new BST<number, string>([
|
|
65
|
+
* [1, 'A'],
|
|
66
|
+
* [7, 'G']
|
|
67
|
+
* ]);
|
|
68
|
+
* const dataset2 = [
|
|
69
|
+
* [2, 'B'],
|
|
70
|
+
* [6, 'F']
|
|
71
|
+
* ];
|
|
72
|
+
* const dataset3 = new BST<number, string>([
|
|
73
|
+
* [3, 'C'],
|
|
74
|
+
* [5, 'E'],
|
|
75
|
+
* [4, 'D']
|
|
76
|
+
* ]);
|
|
77
|
+
*
|
|
78
|
+
* // Merge datasets into a single BinarySearchTree
|
|
79
|
+
* const merged = new BST<number, string>(dataset1);
|
|
80
|
+
* merged.addMany(dataset2);
|
|
81
|
+
* merged.merge(dataset3);
|
|
82
|
+
*
|
|
83
|
+
* // Verify merged dataset is in sorted order
|
|
84
|
+
* console.log([...merged.values()]); // ['A', 'B', 'C', 'D', 'E', 'F', 'G']
|
|
85
|
+
* @example
|
|
86
|
+
* // Find elements in a range
|
|
87
|
+
* const bst = new BST<number>([10, 5, 15, 3, 7, 12, 18]);
|
|
88
|
+
* console.log(bst.search(new Range(5, 10))); // [10, 5, 7]
|
|
89
|
+
* console.log(bst.rangeSearch([4, 12], node => node.key.toString())); // ['10', '12', '5', '7']
|
|
90
|
+
* console.log(bst.search(new Range(4, 12, true, false))); // [10, 5, 7]
|
|
91
|
+
* console.log(bst.rangeSearch([15, 20])); // [15, 18]
|
|
92
|
+
* console.log(bst.search(new Range(15, 20, false))); // [18]
|
|
93
|
+
* @example
|
|
94
|
+
* // Find lowest common ancestor
|
|
95
|
+
* const bst = new BST<number>([20, 10, 30, 5, 15, 25, 35, 3, 7, 12, 18]);
|
|
96
|
+
*
|
|
97
|
+
* // LCA helper function
|
|
98
|
+
* const findLCA = (num1: number, num2: number): number | undefined => {
|
|
99
|
+
* const path1 = bst.getPathToRoot(num1);
|
|
100
|
+
* const path2 = bst.getPathToRoot(num2);
|
|
101
|
+
* // Find the first common ancestor
|
|
102
|
+
* return findFirstCommon(path1, path2);
|
|
103
|
+
* };
|
|
104
|
+
*
|
|
105
|
+
* function findFirstCommon(arr1: number[], arr2: number[]): number | undefined {
|
|
106
|
+
* for (const num of arr1) {
|
|
107
|
+
* if (arr2.indexOf(num) !== -1) {
|
|
108
|
+
* return num;
|
|
109
|
+
* }
|
|
110
|
+
* }
|
|
111
|
+
* return undefined;
|
|
112
|
+
* }
|
|
113
|
+
*
|
|
114
|
+
* // Assertions
|
|
115
|
+
* console.log(findLCA(3, 10)); // 7
|
|
116
|
+
* console.log(findLCA(5, 35)); // 15
|
|
117
|
+
* console.log(findLCA(20, 30)); // 25
|
|
61
118
|
*/
|
|
62
119
|
class BST extends binary_tree_1.BinaryTree {
|
|
63
120
|
/**
|
|
@@ -71,21 +128,33 @@ class BST extends binary_tree_1.BinaryTree {
|
|
|
71
128
|
constructor(keysNodesEntriesOrRaws = [], options) {
|
|
72
129
|
super([], options);
|
|
73
130
|
this._root = undefined;
|
|
74
|
-
this.
|
|
131
|
+
this._isReverse = false;
|
|
132
|
+
this._comparator = (a, b) => {
|
|
133
|
+
if ((0, utils_1.isComparable)(a) && (0, utils_1.isComparable)(b)) {
|
|
134
|
+
if (a > b)
|
|
135
|
+
return 1;
|
|
136
|
+
if (a < b)
|
|
137
|
+
return -1;
|
|
138
|
+
return 0;
|
|
139
|
+
}
|
|
140
|
+
if (this._extractComparable) {
|
|
141
|
+
if (this._extractComparable(a) > this._extractComparable(b))
|
|
142
|
+
return 1;
|
|
143
|
+
if (this._extractComparable(a) < this._extractComparable(b))
|
|
144
|
+
return -1;
|
|
145
|
+
return 0;
|
|
146
|
+
}
|
|
75
147
|
if (typeof a === 'object' || typeof b === 'object') {
|
|
76
|
-
throw TypeError(`When comparing object types, a custom
|
|
148
|
+
throw TypeError(`When comparing object types, a custom extractComparable must be defined in the constructor's options parameter.`);
|
|
77
149
|
}
|
|
78
|
-
if (a > b)
|
|
79
|
-
return 1;
|
|
80
|
-
if (a < b)
|
|
81
|
-
return -1;
|
|
82
150
|
return 0;
|
|
83
151
|
};
|
|
84
|
-
this._comparator = this._DEFAULT_COMPARATOR;
|
|
85
152
|
if (options) {
|
|
86
|
-
const {
|
|
87
|
-
if (
|
|
88
|
-
this.
|
|
153
|
+
const { extractComparable, isReverse } = options;
|
|
154
|
+
if (typeof extractComparable === 'function')
|
|
155
|
+
this._extractComparable = extractComparable;
|
|
156
|
+
if (isReverse !== undefined)
|
|
157
|
+
this._isReverse = isReverse;
|
|
89
158
|
}
|
|
90
159
|
if (keysNodesEntriesOrRaws)
|
|
91
160
|
this.addMany(keysNodesEntriesOrRaws);
|
|
@@ -97,6 +166,14 @@ class BST extends binary_tree_1.BinaryTree {
|
|
|
97
166
|
get root() {
|
|
98
167
|
return this._root;
|
|
99
168
|
}
|
|
169
|
+
/**
|
|
170
|
+
* The above function is a getter method in TypeScript that returns the value of the private property
|
|
171
|
+
* `_isReverse`.
|
|
172
|
+
* @returns The `isReverse` property of the object, which is a boolean value.
|
|
173
|
+
*/
|
|
174
|
+
get isReverse() {
|
|
175
|
+
return this._isReverse;
|
|
176
|
+
}
|
|
100
177
|
/**
|
|
101
178
|
* The function creates a new BSTNode with the given key and value and returns it.
|
|
102
179
|
* @param {K} key - The key parameter is of type K, which represents the type of the key for the node
|
|
@@ -116,7 +193,7 @@ class BST extends binary_tree_1.BinaryTree {
|
|
|
116
193
|
* @returns a new instance of the BST class with the provided options.
|
|
117
194
|
*/
|
|
118
195
|
createTree(options) {
|
|
119
|
-
return new BST([], Object.assign({ iterationType: this.iterationType, isMapMode: this._isMapMode,
|
|
196
|
+
return new BST([], Object.assign({ iterationType: this.iterationType, isMapMode: this._isMapMode, extractComparable: this._extractComparable, toEntryFn: this._toEntryFn, isReverse: this._isReverse }, options));
|
|
120
197
|
}
|
|
121
198
|
/**
|
|
122
199
|
* The function overrides a method and converts a key, value pair or entry or raw element to a node.
|
|
@@ -127,8 +204,8 @@ class BST extends binary_tree_1.BinaryTree {
|
|
|
127
204
|
* value associated with a key in a key-value pair.
|
|
128
205
|
* @returns either a NODE object or undefined.
|
|
129
206
|
*/
|
|
130
|
-
|
|
131
|
-
const [node, entryValue] = super.
|
|
207
|
+
_keyValueNodeEntryRawToNodeAndValue(keyNodeEntryOrRaw, value) {
|
|
208
|
+
const [node, entryValue] = super._keyValueNodeEntryRawToNodeAndValue(keyNodeEntryOrRaw, value);
|
|
132
209
|
if (node === null)
|
|
133
210
|
return [undefined, undefined];
|
|
134
211
|
return [node, value !== null && value !== void 0 ? value : entryValue];
|
|
@@ -167,11 +244,11 @@ class BST extends binary_tree_1.BinaryTree {
|
|
|
167
244
|
* @param {any} key - The `key` parameter is a value that will be checked to determine if it is of
|
|
168
245
|
* type `K`.
|
|
169
246
|
* @returns The `override isKey(key: any): key is K` function is returning a boolean value based on
|
|
170
|
-
* the result of the `isComparable` function with the condition `this.
|
|
247
|
+
* the result of the `isComparable` function with the condition `this._compare !==
|
|
171
248
|
* this._DEFAULT_COMPARATOR`.
|
|
172
249
|
*/
|
|
173
250
|
isKey(key) {
|
|
174
|
-
return (0, utils_1.isComparable)(key, this.
|
|
251
|
+
return (0, utils_1.isComparable)(key, this._extractComparable !== undefined);
|
|
175
252
|
}
|
|
176
253
|
/**
|
|
177
254
|
* Time Complexity: O(log n)
|
|
@@ -185,7 +262,7 @@ class BST extends binary_tree_1.BinaryTree {
|
|
|
185
262
|
* @returns a boolean value.
|
|
186
263
|
*/
|
|
187
264
|
add(keyNodeEntryOrRaw, value) {
|
|
188
|
-
const [newNode, newValue] = this.
|
|
265
|
+
const [newNode, newValue] = this._keyValueNodeEntryRawToNodeAndValue(keyNodeEntryOrRaw, value);
|
|
189
266
|
if (newNode === undefined)
|
|
190
267
|
return false;
|
|
191
268
|
if (this._root === undefined) {
|
|
@@ -197,13 +274,13 @@ class BST extends binary_tree_1.BinaryTree {
|
|
|
197
274
|
}
|
|
198
275
|
let current = this._root;
|
|
199
276
|
while (current !== undefined) {
|
|
200
|
-
if (this.
|
|
277
|
+
if (this._compare(current.key, newNode.key) === 0) {
|
|
201
278
|
this._replaceNode(current, newNode);
|
|
202
279
|
if (this._isMapMode)
|
|
203
280
|
this._setValue(current.key, newValue);
|
|
204
281
|
return true;
|
|
205
282
|
}
|
|
206
|
-
else if (this.
|
|
283
|
+
else if (this._compare(current.key, newNode.key) > 0) {
|
|
207
284
|
if (current.left === undefined) {
|
|
208
285
|
current.left = newNode;
|
|
209
286
|
if (this._isMapMode)
|
|
@@ -290,7 +367,7 @@ class BST extends binary_tree_1.BinaryTree {
|
|
|
290
367
|
keyB = b;
|
|
291
368
|
}
|
|
292
369
|
if (keyA !== undefined && keyA !== null && keyB !== undefined && keyB !== null) {
|
|
293
|
-
return this.
|
|
370
|
+
return this._compare(keyA, keyB);
|
|
294
371
|
}
|
|
295
372
|
return 0;
|
|
296
373
|
});
|
|
@@ -328,30 +405,47 @@ class BST extends binary_tree_1.BinaryTree {
|
|
|
328
405
|
}
|
|
329
406
|
return inserted;
|
|
330
407
|
}
|
|
408
|
+
/**
|
|
409
|
+
* Time Complexity: O(n)
|
|
410
|
+
* Space Complexity: O(1)
|
|
411
|
+
*
|
|
412
|
+
* The `merge` function overrides the base class method by adding elements from another
|
|
413
|
+
* binary search tree.
|
|
414
|
+
* @param anotherTree - `anotherTree` is an instance of a Binary Search Tree (BST) with key type `K`,
|
|
415
|
+
* value type `V`, return type `R`, node type `NODE`, and tree type `TREE`.
|
|
416
|
+
*/
|
|
417
|
+
merge(anotherTree) {
|
|
418
|
+
this.addMany(anotherTree, [], false);
|
|
419
|
+
}
|
|
331
420
|
/**
|
|
332
421
|
* Time Complexity: O(log n)
|
|
333
422
|
* Space Complexity: O(k + log n)
|
|
334
423
|
*
|
|
335
|
-
* The function `
|
|
336
|
-
*
|
|
337
|
-
* @param {BTNRep<K, V, NODE> | R | NodePredicate<NODE>} keyNodeEntryRawOrPredicate - The
|
|
338
|
-
* parameter in the `
|
|
339
|
-
*
|
|
340
|
-
*
|
|
341
|
-
*
|
|
342
|
-
*
|
|
343
|
-
*
|
|
344
|
-
*
|
|
345
|
-
*
|
|
346
|
-
*
|
|
347
|
-
*
|
|
348
|
-
*
|
|
349
|
-
*
|
|
350
|
-
*
|
|
351
|
-
*
|
|
352
|
-
*
|
|
424
|
+
* The function `search` in TypeScript overrides the search behavior in a binary tree structure based
|
|
425
|
+
* on specified criteria.
|
|
426
|
+
* @param {BTNRep<K, V, NODE> | R | NodePredicate<NODE>} keyNodeEntryRawOrPredicate - The
|
|
427
|
+
* `keyNodeEntryRawOrPredicate` parameter in the `override search` method can accept one of the
|
|
428
|
+
* following types:
|
|
429
|
+
* @param [onlyOne=false] - The `onlyOne` parameter is a boolean flag that determines whether the
|
|
430
|
+
* search should stop after finding the first matching node. If `onlyOne` is set to `true`, the
|
|
431
|
+
* search will return as soon as a matching node is found. If `onlyOne` is set to `false`, the
|
|
432
|
+
* @param {C} callback - The `callback` parameter in the `override search` function is a function
|
|
433
|
+
* that will be called on each node that matches the search criteria. It is of type `C`, which
|
|
434
|
+
* extends `NodeCallback<NODE>`. The callback function should accept a node of type `NODE` as its
|
|
435
|
+
* argument and
|
|
436
|
+
* @param {BTNRep<K, V, NODE> | R} startNode - The `startNode` parameter in the `override search`
|
|
437
|
+
* method represents the node from which the search operation will begin. It is the starting point
|
|
438
|
+
* for searching within the tree data structure. The method ensures that the `startNode` is a valid
|
|
439
|
+
* node before proceeding with the search operation. If the `
|
|
440
|
+
* @param {IterationType} iterationType - The `iterationType` parameter in the `override search`
|
|
441
|
+
* function determines the type of iteration to be used during the search operation. It can have two
|
|
442
|
+
* possible values:
|
|
443
|
+
* @returns The `override search` method returns an array of values that match the search criteria
|
|
444
|
+
* specified by the input parameters. The method performs a search operation on a binary tree
|
|
445
|
+
* structure based on the provided key, predicate, and other options. The search results are
|
|
446
|
+
* collected in an array and returned as the output of the method.
|
|
353
447
|
*/
|
|
354
|
-
|
|
448
|
+
search(keyNodeEntryRawOrPredicate, onlyOne = false, callback = this._DEFAULT_NODE_CALLBACK, startNode = this._root, iterationType = this.iterationType) {
|
|
355
449
|
if (keyNodeEntryRawOrPredicate === undefined)
|
|
356
450
|
return [];
|
|
357
451
|
if (keyNodeEntryRawOrPredicate === null)
|
|
@@ -359,28 +453,60 @@ class BST extends binary_tree_1.BinaryTree {
|
|
|
359
453
|
startNode = this.ensureNode(startNode);
|
|
360
454
|
if (!startNode)
|
|
361
455
|
return [];
|
|
362
|
-
|
|
456
|
+
let predicate;
|
|
457
|
+
const isRange = this.isRange(keyNodeEntryRawOrPredicate);
|
|
458
|
+
// Set predicate based on parameter type
|
|
459
|
+
if (isRange) {
|
|
460
|
+
predicate = node => keyNodeEntryRawOrPredicate.isInRange(node.key, this._comparator);
|
|
461
|
+
}
|
|
462
|
+
else {
|
|
463
|
+
predicate = this._ensurePredicate(keyNodeEntryRawOrPredicate);
|
|
464
|
+
}
|
|
465
|
+
const isToLeftByRange = (cur) => {
|
|
466
|
+
if (isRange) {
|
|
467
|
+
const range = keyNodeEntryRawOrPredicate;
|
|
468
|
+
const leftS = this.isReverse ? range.high : range.low;
|
|
469
|
+
const leftI = this.isReverse ? range.includeHigh : range.includeLow;
|
|
470
|
+
return (leftI && this._compare(cur.key, leftS) >= 0) || (!leftI && this._compare(cur.key, leftS) > 0);
|
|
471
|
+
}
|
|
472
|
+
return false;
|
|
473
|
+
};
|
|
474
|
+
const isToRightByRange = (cur) => {
|
|
475
|
+
if (isRange) {
|
|
476
|
+
const range = keyNodeEntryRawOrPredicate;
|
|
477
|
+
const rightS = this.isReverse ? range.low : range.high;
|
|
478
|
+
const rightI = this.isReverse ? range.includeLow : range.includeLow;
|
|
479
|
+
return (rightI && this._compare(cur.key, rightS) <= 0) || (!rightI && this._compare(cur.key, rightS) < 0);
|
|
480
|
+
}
|
|
481
|
+
return false;
|
|
482
|
+
};
|
|
363
483
|
const ans = [];
|
|
364
484
|
if (iterationType === 'RECURSIVE') {
|
|
365
485
|
const dfs = (cur) => {
|
|
366
|
-
if (
|
|
367
|
-
ans.push(cur);
|
|
486
|
+
if (predicate(cur)) {
|
|
487
|
+
ans.push(callback(cur));
|
|
368
488
|
if (onlyOne)
|
|
369
489
|
return;
|
|
370
490
|
}
|
|
371
491
|
if (!this.isRealNode(cur.left) && !this.isRealNode(cur.right))
|
|
372
492
|
return;
|
|
373
|
-
if (
|
|
374
|
-
|
|
493
|
+
if (isRange) {
|
|
494
|
+
if (this.isRealNode(cur.left) && isToLeftByRange(cur))
|
|
495
|
+
dfs(cur.left);
|
|
496
|
+
if (this.isRealNode(cur.right) && isToRightByRange(cur))
|
|
497
|
+
dfs(cur.right);
|
|
498
|
+
}
|
|
499
|
+
else if (!this._isPredicate(keyNodeEntryRawOrPredicate)) {
|
|
500
|
+
const benchmarkKey = this._extractKey(keyNodeEntryRawOrPredicate);
|
|
375
501
|
if (this.isRealNode(cur.left) &&
|
|
376
502
|
benchmarkKey !== null &&
|
|
377
503
|
benchmarkKey !== undefined &&
|
|
378
|
-
this.
|
|
504
|
+
this._compare(cur.key, benchmarkKey) > 0)
|
|
379
505
|
dfs(cur.left);
|
|
380
506
|
if (this.isRealNode(cur.right) &&
|
|
381
507
|
benchmarkKey !== null &&
|
|
382
508
|
benchmarkKey !== undefined &&
|
|
383
|
-
this.
|
|
509
|
+
this._compare(cur.key, benchmarkKey) < 0)
|
|
384
510
|
dfs(cur.right);
|
|
385
511
|
}
|
|
386
512
|
else {
|
|
@@ -396,22 +522,28 @@ class BST extends binary_tree_1.BinaryTree {
|
|
|
396
522
|
const stack = [startNode];
|
|
397
523
|
while (stack.length > 0) {
|
|
398
524
|
const cur = stack.pop();
|
|
399
|
-
if (
|
|
400
|
-
ans.push(cur);
|
|
525
|
+
if (predicate(cur)) {
|
|
526
|
+
ans.push(callback(cur));
|
|
401
527
|
if (onlyOne)
|
|
402
528
|
return ans;
|
|
403
529
|
}
|
|
404
|
-
if (
|
|
405
|
-
|
|
530
|
+
if (isRange) {
|
|
531
|
+
if (this.isRealNode(cur.left) && isToLeftByRange(cur))
|
|
532
|
+
stack.push(cur.left);
|
|
533
|
+
if (this.isRealNode(cur.right) && isToRightByRange(cur))
|
|
534
|
+
stack.push(cur.right);
|
|
535
|
+
}
|
|
536
|
+
else if (!this._isPredicate(keyNodeEntryRawOrPredicate)) {
|
|
537
|
+
const benchmarkKey = this._extractKey(keyNodeEntryRawOrPredicate);
|
|
406
538
|
if (this.isRealNode(cur.right) &&
|
|
407
539
|
benchmarkKey !== null &&
|
|
408
540
|
benchmarkKey !== undefined &&
|
|
409
|
-
this.
|
|
541
|
+
this._compare(cur.key, benchmarkKey) < 0)
|
|
410
542
|
stack.push(cur.right);
|
|
411
543
|
if (this.isRealNode(cur.left) &&
|
|
412
544
|
benchmarkKey !== null &&
|
|
413
545
|
benchmarkKey !== undefined &&
|
|
414
|
-
this.
|
|
546
|
+
this._compare(cur.key, benchmarkKey) > 0)
|
|
415
547
|
stack.push(cur.left);
|
|
416
548
|
}
|
|
417
549
|
else {
|
|
@@ -424,6 +556,31 @@ class BST extends binary_tree_1.BinaryTree {
|
|
|
424
556
|
}
|
|
425
557
|
return ans;
|
|
426
558
|
}
|
|
559
|
+
/**
|
|
560
|
+
* Time Complexity: O(log n)
|
|
561
|
+
* Space Complexity: O(n)
|
|
562
|
+
*
|
|
563
|
+
* The `rangeSearch` function searches for nodes within a specified range in a binary search tree.
|
|
564
|
+
* @param {Range<K> | [K, K]} range - The `range` parameter in the `rangeSearch` function can be
|
|
565
|
+
* either a `Range` object or an array of two elements representing the range boundaries.
|
|
566
|
+
* @param {C} callback - The `callback` parameter in the `rangeSearch` function is a callback
|
|
567
|
+
* function that is used to process each node that is found within the specified range during the
|
|
568
|
+
* search operation. It is of type `NodeCallback<NODE>`, where `NODE` is the type of nodes in the
|
|
569
|
+
* data structure.
|
|
570
|
+
* @param {BTNRep<K, V, NODE> | R} startNode - The `startNode` parameter in the `rangeSearch`
|
|
571
|
+
* function represents the node from which the search for nodes within the specified range will
|
|
572
|
+
* begin. It is the starting point for the range search operation.
|
|
573
|
+
* @param {IterationType} iterationType - The `iterationType` parameter in the `rangeSearch` function
|
|
574
|
+
* is used to specify the type of iteration to be performed during the search operation. It has a
|
|
575
|
+
* default value of `this.iterationType`, which suggests that it is likely a property of the class or
|
|
576
|
+
* object that the `rangeSearch`
|
|
577
|
+
* @returns The `rangeSearch` function is returning the result of calling the `search` method with
|
|
578
|
+
* the specified parameters.
|
|
579
|
+
*/
|
|
580
|
+
rangeSearch(range, callback = this._DEFAULT_NODE_CALLBACK, startNode = this._root, iterationType = this.iterationType) {
|
|
581
|
+
const searchRange = range instanceof common_1.Range ? range : new common_1.Range(range[0], range[1]);
|
|
582
|
+
return this.search(searchRange, false, callback, startNode, iterationType);
|
|
583
|
+
}
|
|
427
584
|
/**
|
|
428
585
|
* Time Complexity: O(log n)
|
|
429
586
|
* Space Complexity: O(1)
|
|
@@ -448,22 +605,6 @@ class BST extends binary_tree_1.BinaryTree {
|
|
|
448
605
|
var _a;
|
|
449
606
|
return (_a = this.getNodes(keyNodeEntryRawOrPredicate, true, startNode, iterationType)[0]) !== null && _a !== void 0 ? _a : undefined;
|
|
450
607
|
}
|
|
451
|
-
/**
|
|
452
|
-
* Time Complexity: O(log n)
|
|
453
|
-
* Space Complexity: O(1)
|
|
454
|
-
*
|
|
455
|
-
* The function `getNodeByKey` returns a node with a specific key from a tree data structure.
|
|
456
|
-
* @param {K} key - The key parameter is the value used to search for a specific node in the tree. It
|
|
457
|
-
* is typically a unique identifier or a value that can be used to determine the position of the node
|
|
458
|
-
* in the tree structure.
|
|
459
|
-
* @param {IterationType} [iterationType=ITERATIVE] - The `iterationType` parameter is an optional
|
|
460
|
-
* parameter that specifies the type of iteration to be used when searching for a node in the tree.
|
|
461
|
-
* It has a default value of `'ITERATIVE'`.
|
|
462
|
-
* @returns The method is returning a NODE object or undefined.
|
|
463
|
-
*/
|
|
464
|
-
getNodeByKey(key, iterationType = this.iterationType) {
|
|
465
|
-
return this.getNode(key, this._root, iterationType);
|
|
466
|
-
}
|
|
467
608
|
/**
|
|
468
609
|
* Time complexity: O(n)
|
|
469
610
|
* Space complexity: O(n)
|
|
@@ -559,9 +700,10 @@ class BST extends binary_tree_1.BinaryTree {
|
|
|
559
700
|
const targetKey = targetNodeEnsured.key;
|
|
560
701
|
if (iterationType === 'RECURSIVE') {
|
|
561
702
|
const dfs = (cur) => {
|
|
562
|
-
const compared = this.
|
|
703
|
+
const compared = this._compare(cur.key, targetKey);
|
|
563
704
|
if (Math.sign(compared) === lesserOrGreater)
|
|
564
705
|
ans.push(callback(cur));
|
|
706
|
+
// TODO here can be optimized to O(log n)
|
|
565
707
|
if (this.isRealNode(cur.left))
|
|
566
708
|
dfs(cur.left);
|
|
567
709
|
if (this.isRealNode(cur.right))
|
|
@@ -575,7 +717,7 @@ class BST extends binary_tree_1.BinaryTree {
|
|
|
575
717
|
while (queue.size > 0) {
|
|
576
718
|
const cur = queue.shift();
|
|
577
719
|
if (this.isRealNode(cur)) {
|
|
578
|
-
const compared = this.
|
|
720
|
+
const compared = this._compare(cur.key, targetKey);
|
|
579
721
|
if (Math.sign(compared) === lesserOrGreater)
|
|
580
722
|
ans.push(callback(cur));
|
|
581
723
|
if (this.isRealNode(cur.left))
|
|
@@ -705,6 +847,14 @@ class BST extends binary_tree_1.BinaryTree {
|
|
|
705
847
|
get comparator() {
|
|
706
848
|
return this._comparator;
|
|
707
849
|
}
|
|
850
|
+
/**
|
|
851
|
+
* This function returns the value of the `_extractComparable` property.
|
|
852
|
+
* @returns The method `extractComparable()` is being returned, which is a getter method for the
|
|
853
|
+
* `_extractComparable` property.
|
|
854
|
+
*/
|
|
855
|
+
get extractComparable() {
|
|
856
|
+
return this._extractComparable;
|
|
857
|
+
}
|
|
708
858
|
/**
|
|
709
859
|
* The function sets the root of a tree-like structure and updates the parent property of the new
|
|
710
860
|
* root.
|
|
@@ -716,5 +866,8 @@ class BST extends binary_tree_1.BinaryTree {
|
|
|
716
866
|
}
|
|
717
867
|
this._root = v;
|
|
718
868
|
}
|
|
869
|
+
_compare(a, b) {
|
|
870
|
+
return this._isReverse ? -this._comparator(a, b) : this._comparator(a, b);
|
|
871
|
+
}
|
|
719
872
|
}
|
|
720
873
|
exports.BST = BST;
|
|
@@ -19,6 +19,6 @@ __exportStar(require("./bst"), exports);
|
|
|
19
19
|
__exportStar(require("./binary-indexed-tree"), exports);
|
|
20
20
|
__exportStar(require("./segment-tree"), exports);
|
|
21
21
|
__exportStar(require("./avl-tree"), exports);
|
|
22
|
-
__exportStar(require("./
|
|
22
|
+
__exportStar(require("./red-black-tree"), exports);
|
|
23
23
|
__exportStar(require("./avl-tree-multi-map"), exports);
|
|
24
24
|
__exportStar(require("./tree-multi-map"), exports);
|
|
@@ -26,6 +26,59 @@ export declare class RedBlackTreeNode<K = any, V = any, NODE extends RedBlackTre
|
|
|
26
26
|
*/
|
|
27
27
|
set color(value: RBTNColor);
|
|
28
28
|
}
|
|
29
|
+
/**
|
|
30
|
+
* 1. Efficient self-balancing, but not completely balanced. Compared with AVLTree, the addition and deletion efficiency is high but the query efficiency is slightly lower.
|
|
31
|
+
* 2. It is BST itself. Compared with Heap which is not completely ordered, RedBlackTree is completely ordered.
|
|
32
|
+
* @example
|
|
33
|
+
* // Find elements in a range
|
|
34
|
+
* const bst = new RedBlackTree<number>([10, 5, 15, 3, 7, 12, 18]);
|
|
35
|
+
* console.log(bst.search(new Range(5, 10))); // [5, 10, 7]
|
|
36
|
+
* console.log(bst.search(new Range(4, 12))); // [5, 10, 12, 7]
|
|
37
|
+
* console.log(bst.search(new Range(15, 20))); // [15, 18]
|
|
38
|
+
* @example
|
|
39
|
+
* // using Red-Black Tree as a price-based index for stock data
|
|
40
|
+
* // Define the structure of individual stock records
|
|
41
|
+
* interface StockRecord {
|
|
42
|
+
* price: number; // Stock price (key for indexing)
|
|
43
|
+
* symbol: string; // Stock ticker symbol
|
|
44
|
+
* volume: number; // Trade volume
|
|
45
|
+
* }
|
|
46
|
+
*
|
|
47
|
+
* // Simulate stock market data as it might come from an external feed
|
|
48
|
+
* const marketStockData: StockRecord[] = [
|
|
49
|
+
* { price: 142.5, symbol: 'AAPL', volume: 1000000 },
|
|
50
|
+
* { price: 335.2, symbol: 'MSFT', volume: 800000 },
|
|
51
|
+
* { price: 3285.04, symbol: 'AMZN', volume: 500000 },
|
|
52
|
+
* { price: 267.98, symbol: 'META', volume: 750000 },
|
|
53
|
+
* { price: 234.57, symbol: 'GOOGL', volume: 900000 }
|
|
54
|
+
* ];
|
|
55
|
+
*
|
|
56
|
+
* // Extend the stock record type to include metadata for database usage
|
|
57
|
+
* type StockTableRecord = StockRecord & { lastUpdated: Date };
|
|
58
|
+
*
|
|
59
|
+
* // Create a Red-Black Tree to index stock records by price
|
|
60
|
+
* // Simulates a database index with stock price as the key for quick lookups
|
|
61
|
+
* const priceIndex = new RedBlackTree<number, StockTableRecord, StockRecord>(marketStockData, {
|
|
62
|
+
* toEntryFn: stockRecord => [
|
|
63
|
+
* stockRecord.price, // Use stock price as the key
|
|
64
|
+
* {
|
|
65
|
+
* ...stockRecord,
|
|
66
|
+
* lastUpdated: new Date() // Add a timestamp for when the record was indexed
|
|
67
|
+
* }
|
|
68
|
+
* ]
|
|
69
|
+
* });
|
|
70
|
+
*
|
|
71
|
+
* // Query the stock with the highest price
|
|
72
|
+
* const highestPricedStock = priceIndex.getRightMost();
|
|
73
|
+
* console.log(priceIndex.get(highestPricedStock)?.symbol); // 'AMZN' // Amazon has the highest price
|
|
74
|
+
*
|
|
75
|
+
* // Query stocks within a specific price range (200 to 400)
|
|
76
|
+
* const stocksInRange = priceIndex.rangeSearch(
|
|
77
|
+
* [200, 400], // Price range
|
|
78
|
+
* node => priceIndex.get(node)?.symbol // Extract stock symbols for the result
|
|
79
|
+
* );
|
|
80
|
+
* console.log(stocksInRange); // ['GOOGL', 'MSFT', 'META']
|
|
81
|
+
*/
|
|
29
82
|
export declare class RedBlackTree<K = any, V = any, R = object, NODE extends RedBlackTreeNode<K, V, NODE> = RedBlackTreeNode<K, V, RedBlackTreeNodeNested<K, V>>, TREE extends RedBlackTree<K, V, R, NODE, TREE> = RedBlackTree<K, V, R, NODE, RedBlackTreeNested<K, V, R, NODE>>> extends BST<K, V, R, NODE, TREE> implements IBinaryTree<K, V, R, NODE, TREE> {
|
|
30
83
|
/**
|
|
31
84
|
* This is the constructor function for a Red-Black Tree data structure in TypeScript.
|
|
@@ -34,6 +34,59 @@ class RedBlackTreeNode extends bst_1.BSTNode {
|
|
|
34
34
|
}
|
|
35
35
|
}
|
|
36
36
|
exports.RedBlackTreeNode = RedBlackTreeNode;
|
|
37
|
+
/**
|
|
38
|
+
* 1. Efficient self-balancing, but not completely balanced. Compared with AVLTree, the addition and deletion efficiency is high but the query efficiency is slightly lower.
|
|
39
|
+
* 2. It is BST itself. Compared with Heap which is not completely ordered, RedBlackTree is completely ordered.
|
|
40
|
+
* @example
|
|
41
|
+
* // Find elements in a range
|
|
42
|
+
* const bst = new RedBlackTree<number>([10, 5, 15, 3, 7, 12, 18]);
|
|
43
|
+
* console.log(bst.search(new Range(5, 10))); // [5, 10, 7]
|
|
44
|
+
* console.log(bst.search(new Range(4, 12))); // [5, 10, 12, 7]
|
|
45
|
+
* console.log(bst.search(new Range(15, 20))); // [15, 18]
|
|
46
|
+
* @example
|
|
47
|
+
* // using Red-Black Tree as a price-based index for stock data
|
|
48
|
+
* // Define the structure of individual stock records
|
|
49
|
+
* interface StockRecord {
|
|
50
|
+
* price: number; // Stock price (key for indexing)
|
|
51
|
+
* symbol: string; // Stock ticker symbol
|
|
52
|
+
* volume: number; // Trade volume
|
|
53
|
+
* }
|
|
54
|
+
*
|
|
55
|
+
* // Simulate stock market data as it might come from an external feed
|
|
56
|
+
* const marketStockData: StockRecord[] = [
|
|
57
|
+
* { price: 142.5, symbol: 'AAPL', volume: 1000000 },
|
|
58
|
+
* { price: 335.2, symbol: 'MSFT', volume: 800000 },
|
|
59
|
+
* { price: 3285.04, symbol: 'AMZN', volume: 500000 },
|
|
60
|
+
* { price: 267.98, symbol: 'META', volume: 750000 },
|
|
61
|
+
* { price: 234.57, symbol: 'GOOGL', volume: 900000 }
|
|
62
|
+
* ];
|
|
63
|
+
*
|
|
64
|
+
* // Extend the stock record type to include metadata for database usage
|
|
65
|
+
* type StockTableRecord = StockRecord & { lastUpdated: Date };
|
|
66
|
+
*
|
|
67
|
+
* // Create a Red-Black Tree to index stock records by price
|
|
68
|
+
* // Simulates a database index with stock price as the key for quick lookups
|
|
69
|
+
* const priceIndex = new RedBlackTree<number, StockTableRecord, StockRecord>(marketStockData, {
|
|
70
|
+
* toEntryFn: stockRecord => [
|
|
71
|
+
* stockRecord.price, // Use stock price as the key
|
|
72
|
+
* {
|
|
73
|
+
* ...stockRecord,
|
|
74
|
+
* lastUpdated: new Date() // Add a timestamp for when the record was indexed
|
|
75
|
+
* }
|
|
76
|
+
* ]
|
|
77
|
+
* });
|
|
78
|
+
*
|
|
79
|
+
* // Query the stock with the highest price
|
|
80
|
+
* const highestPricedStock = priceIndex.getRightMost();
|
|
81
|
+
* console.log(priceIndex.get(highestPricedStock)?.symbol); // 'AMZN' // Amazon has the highest price
|
|
82
|
+
*
|
|
83
|
+
* // Query stocks within a specific price range (200 to 400)
|
|
84
|
+
* const stocksInRange = priceIndex.rangeSearch(
|
|
85
|
+
* [200, 400], // Price range
|
|
86
|
+
* node => priceIndex.get(node)?.symbol // Extract stock symbols for the result
|
|
87
|
+
* );
|
|
88
|
+
* console.log(stocksInRange); // ['GOOGL', 'MSFT', 'META']
|
|
89
|
+
*/
|
|
37
90
|
class RedBlackTree extends bst_1.BST {
|
|
38
91
|
/**
|
|
39
92
|
* This is the constructor function for a Red-Black Tree data structure in TypeScript.
|
|
@@ -83,7 +136,7 @@ class RedBlackTree extends bst_1.BST {
|
|
|
83
136
|
* @returns a new instance of a RedBlackTree object.
|
|
84
137
|
*/
|
|
85
138
|
createTree(options) {
|
|
86
|
-
return new RedBlackTree([], Object.assign({ iterationType: this.iterationType, isMapMode: this._isMapMode,
|
|
139
|
+
return new RedBlackTree([], Object.assign({ iterationType: this.iterationType, isMapMode: this._isMapMode, extractComparable: this._extractComparable, toEntryFn: this._toEntryFn }, options));
|
|
87
140
|
}
|
|
88
141
|
/**
|
|
89
142
|
* Time Complexity: O(1)
|
|
@@ -160,7 +213,7 @@ class RedBlackTree extends bst_1.BST {
|
|
|
160
213
|
* returns true. If the node cannot be added or updated, the method returns false.
|
|
161
214
|
*/
|
|
162
215
|
add(keyNodeEntryOrRaw, value) {
|
|
163
|
-
const [newNode, newValue] = this.
|
|
216
|
+
const [newNode, newValue] = this._keyValueNodeEntryRawToNodeAndValue(keyNodeEntryOrRaw, value);
|
|
164
217
|
if (!this.isRealNode(newNode))
|
|
165
218
|
return false;
|
|
166
219
|
const insertStatus = this._insert(newNode);
|
|
@@ -303,7 +356,7 @@ class RedBlackTree extends bst_1.BST {
|
|
|
303
356
|
let parent = undefined;
|
|
304
357
|
while (this.isRealNode(current)) {
|
|
305
358
|
parent = current;
|
|
306
|
-
const compared = this.
|
|
359
|
+
const compared = this._compare(node.key, current.key);
|
|
307
360
|
if (compared < 0) {
|
|
308
361
|
current = (_a = current.left) !== null && _a !== void 0 ? _a : this.NIL;
|
|
309
362
|
}
|
|
@@ -7,7 +7,7 @@
|
|
|
7
7
|
*/
|
|
8
8
|
import type { BinaryTreeDeleteResult, BSTNOptKeyOrNode, BTNRep, IterationType, RBTNColor, TreeMultiMapNested, TreeMultiMapNodeNested, TreeMultiMapOptions } from '../../types';
|
|
9
9
|
import { IBinaryTree } from '../../interfaces';
|
|
10
|
-
import { RedBlackTree, RedBlackTreeNode } from './
|
|
10
|
+
import { RedBlackTree, RedBlackTreeNode } from './red-black-tree';
|
|
11
11
|
export declare class TreeMultiMapNode<K = any, V = any, NODE extends TreeMultiMapNode<K, V, NODE> = TreeMultiMapNodeNested<K, V>> extends RedBlackTreeNode<K, V, NODE> {
|
|
12
12
|
/**
|
|
13
13
|
* The constructor function initializes a Red-Black Tree node with a key, value, count, and color.
|
|
@@ -96,7 +96,7 @@ export declare class TreeMultiMap<K = any, V = any, R = object, NODE extends Tre
|
|
|
96
96
|
* times the key-value pair should be added to the data structure. If not provided, it defaults to 1.
|
|
97
97
|
* @returns either a NODE object or undefined.
|
|
98
98
|
*/
|
|
99
|
-
|
|
99
|
+
protected _keyValueNodeEntryRawToNodeAndValue(keyNodeEntryOrRaw: BTNRep<K, V, NODE> | R, value?: V, count?: number): [NODE | undefined, V | undefined];
|
|
100
100
|
/**
|
|
101
101
|
* The function checks if the input is an instance of the TreeMultiMapNode class.
|
|
102
102
|
* @param {BTNRep<K, V, NODE> | R} keyNodeEntryOrRaw - The parameter
|