priority-queue-typed 1.47.6 → 1.47.7
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/data-structures/binary-tree/avl-tree.d.ts +40 -22
- package/dist/data-structures/binary-tree/avl-tree.js +45 -36
- package/dist/data-structures/binary-tree/binary-tree.d.ts +105 -113
- package/dist/data-structures/binary-tree/binary-tree.js +133 -119
- package/dist/data-structures/binary-tree/bst.d.ts +53 -44
- package/dist/data-structures/binary-tree/bst.js +137 -154
- package/dist/data-structures/binary-tree/rb-tree.d.ts +48 -15
- package/dist/data-structures/binary-tree/rb-tree.js +70 -33
- package/dist/data-structures/binary-tree/tree-multimap.d.ts +26 -37
- package/dist/data-structures/binary-tree/tree-multimap.js +58 -137
- package/dist/data-structures/hash/hash-map.d.ts +2 -6
- package/dist/data-structures/hash/hash-map.js +5 -8
- package/dist/data-structures/trie/trie.d.ts +3 -0
- package/dist/data-structures/trie/trie.js +19 -4
- package/dist/interfaces/binary-tree.d.ts +3 -3
- package/dist/types/common.d.ts +6 -1
- package/dist/types/data-structures/hash/hash-map.d.ts +1 -2
- package/package.json +2 -2
- package/src/data-structures/binary-tree/avl-tree.ts +59 -39
- package/src/data-structures/binary-tree/binary-tree.ts +192 -180
- package/src/data-structures/binary-tree/bst.ts +157 -154
- package/src/data-structures/binary-tree/rb-tree.ts +78 -37
- package/src/data-structures/binary-tree/tree-multimap.ts +67 -145
- package/src/data-structures/hash/hash-map.ts +8 -8
- package/src/data-structures/trie/trie.ts +23 -4
- package/src/interfaces/binary-tree.ts +3 -3
- package/src/types/common.ts +11 -1
- package/src/types/data-structures/hash/hash-map.ts +1 -2
|
@@ -5,8 +5,18 @@
|
|
|
5
5
|
* @copyright Copyright (c) 2022 Tyler Zeng <zrwusa@gmail.com>
|
|
6
6
|
* @license MIT License
|
|
7
7
|
*/
|
|
8
|
-
import type {
|
|
9
|
-
|
|
8
|
+
import type {
|
|
9
|
+
BSTNested,
|
|
10
|
+
BSTNodeKeyOrNode,
|
|
11
|
+
BSTNodeNested,
|
|
12
|
+
BSTOptions,
|
|
13
|
+
BTNCallback,
|
|
14
|
+
BTNKey,
|
|
15
|
+
BTNodeExemplar,
|
|
16
|
+
BTNodePureExemplar,
|
|
17
|
+
Comparator
|
|
18
|
+
} from '../../types';
|
|
19
|
+
import { CP, IterationType } from '../../types';
|
|
10
20
|
import { BinaryTree, BinaryTreeNode } from './binary-tree';
|
|
11
21
|
import { IBinaryTree } from '../../interfaces';
|
|
12
22
|
import { Queue } from '../queue';
|
|
@@ -62,16 +72,29 @@ export class BSTNode<V = any, N extends BSTNode<V, N> = BSTNodeNested<V>> extend
|
|
|
62
72
|
}
|
|
63
73
|
}
|
|
64
74
|
|
|
75
|
+
/**
|
|
76
|
+
* 1. Node Order: Each node's left child has a lesser value, and the right child has a greater value.
|
|
77
|
+
* 2. Unique Keys: No duplicate keys in a standard BST.
|
|
78
|
+
* 3. Efficient Search: Enables quick search, minimum, and maximum operations.
|
|
79
|
+
* 4. Inorder Traversal: Yields nodes in ascending order.
|
|
80
|
+
* 5. Logarithmic Operations: Ideal operations like insertion, deletion, and searching are O(log n) time-efficient.
|
|
81
|
+
* 6. Balance Variability: Can become unbalanced; special types maintain balance.
|
|
82
|
+
* 7. No Auto-Balancing: Standard BSTs don't automatically balance themselves.
|
|
83
|
+
*/
|
|
65
84
|
export class BST<V = any, N extends BSTNode<V, N> = BSTNode<V, BSTNodeNested<V>>, TREE extends BST<V, N, TREE> = BST<V, N, BSTNested<V, N>>>
|
|
66
85
|
extends BinaryTree<V, N, TREE>
|
|
67
86
|
implements IBinaryTree<V, N, TREE> {
|
|
68
87
|
|
|
88
|
+
|
|
69
89
|
/**
|
|
70
|
-
*
|
|
71
|
-
*
|
|
72
|
-
*
|
|
90
|
+
* This is the constructor function for a binary search tree class in TypeScript, which initializes
|
|
91
|
+
* the tree with optional elements and options.
|
|
92
|
+
* @param [elements] - An optional iterable of BTNodeExemplar objects that will be added to the
|
|
93
|
+
* binary search tree.
|
|
94
|
+
* @param [options] - The `options` parameter is an optional object that can contain additional
|
|
95
|
+
* configuration options for the binary search tree. It can have the following properties:
|
|
73
96
|
*/
|
|
74
|
-
constructor(elements?:
|
|
97
|
+
constructor(elements?: Iterable<BTNodeExemplar<V, N>>, options?: Partial<BSTOptions>) {
|
|
75
98
|
super([], options);
|
|
76
99
|
|
|
77
100
|
if (options) {
|
|
@@ -82,14 +105,12 @@ export class BST<V = any, N extends BSTNode<V, N> = BSTNode<V, BSTNodeNested<V>>
|
|
|
82
105
|
}
|
|
83
106
|
|
|
84
107
|
this._root = undefined;
|
|
85
|
-
|
|
108
|
+
|
|
109
|
+
if (elements) this.addMany(elements);
|
|
86
110
|
}
|
|
87
111
|
|
|
88
112
|
protected override _root?: N;
|
|
89
113
|
|
|
90
|
-
/**
|
|
91
|
-
* Get the root node of the binary tree.
|
|
92
|
-
*/
|
|
93
114
|
override get root(): N | undefined {
|
|
94
115
|
return this._root;
|
|
95
116
|
}
|
|
@@ -108,6 +129,13 @@ export class BST<V = any, N extends BSTNode<V, N> = BSTNode<V, BSTNodeNested<V>>
|
|
|
108
129
|
return new BSTNode<V, N>(key, value) as N;
|
|
109
130
|
}
|
|
110
131
|
|
|
132
|
+
/**
|
|
133
|
+
* The function creates a new binary search tree with the specified options.
|
|
134
|
+
* @param [options] - The `options` parameter is an optional object that allows you to customize the
|
|
135
|
+
* behavior of the `createTree` method. It accepts a partial `BSTOptions` object, which is a type
|
|
136
|
+
* that defines various options for creating a binary search tree.
|
|
137
|
+
* @returns a new instance of the BST class with the specified options.
|
|
138
|
+
*/
|
|
111
139
|
override createTree(options?: Partial<BSTOptions>): TREE {
|
|
112
140
|
return new BST<V, N, TREE>([], {
|
|
113
141
|
iterationType: this.iterationType,
|
|
@@ -115,162 +143,154 @@ export class BST<V = any, N extends BSTNode<V, N> = BSTNode<V, BSTNodeNested<V>>
|
|
|
115
143
|
}) as TREE;
|
|
116
144
|
}
|
|
117
145
|
|
|
146
|
+
/**
|
|
147
|
+
* Time Complexity: O(log n) - Average case for a balanced tree. In the worst case (unbalanced tree), it can be O(n).
|
|
148
|
+
* Space Complexity: O(1) - Constant space is used.
|
|
149
|
+
*/
|
|
150
|
+
|
|
118
151
|
/**
|
|
119
152
|
* Time Complexity: O(log n) - Average case for a balanced tree. In the worst case (unbalanced tree), it can be O(n).
|
|
120
153
|
* Space Complexity: O(1) - Constant space is used.
|
|
121
154
|
*
|
|
122
|
-
* The `add` function adds a new node to a binary search tree
|
|
123
|
-
*
|
|
124
|
-
* following
|
|
125
|
-
* @
|
|
126
|
-
*
|
|
127
|
-
* @returns The method `add` returns a node (`N`) that was inserted into the binary search tree. If
|
|
128
|
-
* no node was inserted, it returns `undefined`.
|
|
155
|
+
* The `add` function adds a new node to a binary search tree, either by key or by providing a node
|
|
156
|
+
* object.
|
|
157
|
+
* @param keyOrNodeOrEntry - The `keyOrNodeOrEntry` parameter can be one of the following:
|
|
158
|
+
* @returns The method returns either the newly added node (`newNode`) or `undefined` if the input
|
|
159
|
+
* (`keyOrNodeOrEntry`) is null, undefined, or does not match any of the expected types.
|
|
129
160
|
*/
|
|
130
|
-
override add(
|
|
131
|
-
if (
|
|
132
|
-
|
|
133
|
-
|
|
161
|
+
override add(keyOrNodeOrEntry: BTNodeExemplar<V, N>): N | undefined {
|
|
162
|
+
if (keyOrNodeOrEntry === null || keyOrNodeOrEntry === undefined) {
|
|
163
|
+
return undefined;
|
|
164
|
+
}
|
|
165
|
+
|
|
134
166
|
let newNode: N | undefined;
|
|
135
|
-
if (
|
|
136
|
-
newNode =
|
|
137
|
-
} else if (this.isNodeKey(
|
|
138
|
-
newNode = this.createNode(
|
|
167
|
+
if (keyOrNodeOrEntry instanceof BSTNode) {
|
|
168
|
+
newNode = keyOrNodeOrEntry;
|
|
169
|
+
} else if (this.isNodeKey(keyOrNodeOrEntry)) {
|
|
170
|
+
newNode = this.createNode(keyOrNodeOrEntry);
|
|
171
|
+
} else if (this.isEntry(keyOrNodeOrEntry)) {
|
|
172
|
+
const [key, value] = keyOrNodeOrEntry;
|
|
173
|
+
if (key === undefined || key === null) {
|
|
174
|
+
return;
|
|
175
|
+
} else {
|
|
176
|
+
newNode = this.createNode(key, value);
|
|
177
|
+
}
|
|
139
178
|
} else {
|
|
140
|
-
|
|
179
|
+
return;
|
|
141
180
|
}
|
|
181
|
+
|
|
142
182
|
if (this.root === undefined) {
|
|
143
183
|
this._setRoot(newNode);
|
|
144
|
-
this._size
|
|
145
|
-
|
|
146
|
-
}
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
if (newNode) {
|
|
177
|
-
newNode.parent = cur;
|
|
178
|
-
}
|
|
179
|
-
//Add to the right of the current node
|
|
180
|
-
cur.right = newNode;
|
|
181
|
-
this._size = this.size + 1;
|
|
182
|
-
traversing = false;
|
|
183
|
-
inserted = cur.right;
|
|
184
|
-
} else {
|
|
185
|
-
//Traverse the left of the current node
|
|
186
|
-
if (cur.right) cur = cur.right;
|
|
187
|
-
}
|
|
188
|
-
}
|
|
189
|
-
} else {
|
|
190
|
-
traversing = false;
|
|
184
|
+
this._size++;
|
|
185
|
+
return this.root;
|
|
186
|
+
}
|
|
187
|
+
|
|
188
|
+
let current = this.root;
|
|
189
|
+
while (current !== undefined) {
|
|
190
|
+
if (this._compare(current.key, newNode.key) === CP.eq) {
|
|
191
|
+
// if (current !== newNode) {
|
|
192
|
+
// The key value is the same but the reference is different, update the value of the existing node
|
|
193
|
+
this._replaceNode(current, newNode);
|
|
194
|
+
return newNode;
|
|
195
|
+
|
|
196
|
+
// } else {
|
|
197
|
+
// The key value is the same and the reference is the same, replace the entire node
|
|
198
|
+
// this._replaceNode(current, newNode);
|
|
199
|
+
|
|
200
|
+
// return;
|
|
201
|
+
// }
|
|
202
|
+
} else if (this._compare(current.key, newNode.key) === CP.gt) {
|
|
203
|
+
if (current.left === undefined) {
|
|
204
|
+
current.left = newNode;
|
|
205
|
+
newNode.parent = current;
|
|
206
|
+
this._size++;
|
|
207
|
+
return newNode;
|
|
208
|
+
}
|
|
209
|
+
current = current.left;
|
|
210
|
+
} else {
|
|
211
|
+
if (current.right === undefined) {
|
|
212
|
+
current.right = newNode;
|
|
213
|
+
newNode.parent = current;
|
|
214
|
+
this._size++;
|
|
215
|
+
return newNode;
|
|
191
216
|
}
|
|
217
|
+
current = current.right;
|
|
192
218
|
}
|
|
193
219
|
}
|
|
194
|
-
|
|
220
|
+
|
|
221
|
+
return undefined;
|
|
195
222
|
}
|
|
196
223
|
|
|
197
224
|
/**
|
|
198
|
-
* Time Complexity: O(log n) -
|
|
199
|
-
* Space Complexity: O(
|
|
225
|
+
* Time Complexity: O(k log n) - Adding each element individually in a balanced tree.
|
|
226
|
+
* Space Complexity: O(k) - Additional space is required for the sorted array.
|
|
200
227
|
*/
|
|
201
228
|
|
|
202
229
|
/**
|
|
203
|
-
* Time Complexity: O(
|
|
204
|
-
* Space Complexity: O(
|
|
230
|
+
* Time Complexity: O(k log n) - Adding each element individually in a balanced tree.
|
|
231
|
+
* Space Complexity: O(k) - Additional space is required for the sorted array.
|
|
205
232
|
*
|
|
206
|
-
* The `addMany` function
|
|
207
|
-
*
|
|
208
|
-
* @param
|
|
209
|
-
* binary
|
|
210
|
-
* node), or `undefined`.
|
|
211
|
-
* @param {(V | undefined)[]} [data] - An optional array of values to associate with the keys or
|
|
212
|
-
* nodes being added. If provided, the length of the `data` array must be the same as the length of
|
|
213
|
-
* the `keysOrNodes` array.
|
|
233
|
+
* The `addMany` function in TypeScript adds multiple nodes to a binary tree, either in a balanced or
|
|
234
|
+
* unbalanced manner, and returns an array of the inserted nodes.
|
|
235
|
+
* @param keysOrNodesOrEntries - An iterable containing keys, nodes, or entries to be added to the
|
|
236
|
+
* binary tree.
|
|
214
237
|
* @param [isBalanceAdd=true] - A boolean flag indicating whether the tree should be balanced after
|
|
215
|
-
* adding the nodes. The default value is
|
|
238
|
+
* adding the nodes. The default value is true.
|
|
216
239
|
* @param iterationType - The `iterationType` parameter is an optional parameter that specifies the
|
|
217
|
-
* type of iteration to use when adding multiple keys or nodes to the binary
|
|
218
|
-
*
|
|
219
|
-
*
|
|
220
|
-
* @returns The
|
|
240
|
+
* type of iteration to use when adding multiple keys or nodes to the binary tree. It has a default
|
|
241
|
+
* value of `this.iterationType`, which means it will use the iteration type specified by the binary
|
|
242
|
+
* tree instance.
|
|
243
|
+
* @returns The `addMany` function returns an array of `N` or `undefined` values.
|
|
221
244
|
*/
|
|
222
245
|
override addMany(
|
|
223
|
-
|
|
224
|
-
data?: (V | undefined)[],
|
|
246
|
+
keysOrNodesOrEntries: Iterable<BTNodeExemplar<V, N>>,
|
|
225
247
|
isBalanceAdd = true,
|
|
226
248
|
iterationType = this.iterationType
|
|
227
249
|
): (N | undefined)[] {
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
250
|
+
const inserted: (N | undefined)[] = []
|
|
251
|
+
if (!isBalanceAdd) {
|
|
252
|
+
for (const kve of keysOrNodesOrEntries) {
|
|
253
|
+
const nn = this.add(kve)
|
|
254
|
+
inserted.push(nn);
|
|
255
|
+
}
|
|
256
|
+
return inserted;
|
|
231
257
|
}
|
|
258
|
+
const realBTNExemplars: BTNodePureExemplar<V, N>[] = [];
|
|
232
259
|
|
|
233
|
-
|
|
234
|
-
|
|
260
|
+
const isRealBTNExemplar = (kve: BTNodeExemplar<V, N>): kve is BTNodePureExemplar<V, N> => {
|
|
261
|
+
if (kve === undefined || kve === null) return false;
|
|
262
|
+
return !(this.isEntry(kve) && (kve[0] === undefined || kve[0] === null));
|
|
235
263
|
}
|
|
236
264
|
|
|
237
|
-
const
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
);
|
|
265
|
+
for (const kve of keysOrNodesOrEntries) {
|
|
266
|
+
isRealBTNExemplar(kve) && realBTNExemplars.push(kve);
|
|
267
|
+
}
|
|
241
268
|
|
|
242
|
-
|
|
269
|
+
// TODO this addMany function is inefficient, it should be optimized
|
|
270
|
+
let sorted: BTNodePureExemplar<V, N>[] = [];
|
|
243
271
|
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
272
|
+
sorted = realBTNExemplars.sort((a, b) => {
|
|
273
|
+
let aR: number, bR: number;
|
|
274
|
+
if (this.isEntry(a)) aR = a[0]
|
|
275
|
+
else if (this.isRealNode(a)) aR = a.key
|
|
276
|
+
else aR = a;
|
|
248
277
|
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
};
|
|
278
|
+
if (this.isEntry(b)) bR = b[0]
|
|
279
|
+
else if (this.isRealNode(b)) bR = b.key
|
|
280
|
+
else bR = b;
|
|
253
281
|
|
|
254
|
-
|
|
255
|
-
|
|
282
|
+
return aR - bR;
|
|
283
|
+
})
|
|
256
284
|
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
} else if (_isBinaryTreeKeyOrNullTuple(combinedArr)) {
|
|
260
|
-
sorted = combinedArr.sort((a, b) => a[0] - b[0]);
|
|
261
|
-
} else {
|
|
262
|
-
throw new Error('Invalid input keysOrNodes');
|
|
263
|
-
}
|
|
264
|
-
sortedKeysOrNodes = sorted.map(([keyOrNode]) => keyOrNode);
|
|
265
|
-
sortedData = sorted.map(([, value]) => value);
|
|
266
|
-
const _dfs = (arr: (BTNKey | undefined | N)[], data?: (V | undefined)[]) => {
|
|
285
|
+
|
|
286
|
+
const _dfs = (arr: BTNodePureExemplar<V, N>[]) => {
|
|
267
287
|
if (arr.length === 0) return;
|
|
268
288
|
|
|
269
289
|
const mid = Math.floor((arr.length - 1) / 2);
|
|
270
|
-
const newNode = this.add(arr[mid]
|
|
290
|
+
const newNode = this.add(arr[mid]);
|
|
271
291
|
inserted.push(newNode);
|
|
272
|
-
_dfs(arr.slice(0, mid)
|
|
273
|
-
_dfs(arr.slice(mid + 1)
|
|
292
|
+
_dfs(arr.slice(0, mid));
|
|
293
|
+
_dfs(arr.slice(mid + 1));
|
|
274
294
|
};
|
|
275
295
|
const _iterate = () => {
|
|
276
296
|
const n = sorted.length;
|
|
@@ -281,7 +301,7 @@ export class BST<V = any, N extends BSTNode<V, N> = BSTNode<V, BSTNodeNested<V>>
|
|
|
281
301
|
const [l, r] = popped;
|
|
282
302
|
if (l <= r) {
|
|
283
303
|
const m = l + Math.floor((r - l) / 2);
|
|
284
|
-
const newNode = this.add(
|
|
304
|
+
const newNode = this.add(sorted[m]);
|
|
285
305
|
inserted.push(newNode);
|
|
286
306
|
stack.push([m + 1, r]);
|
|
287
307
|
stack.push([l, m - 1]);
|
|
@@ -290,7 +310,7 @@ export class BST<V = any, N extends BSTNode<V, N> = BSTNode<V, BSTNodeNested<V>>
|
|
|
290
310
|
}
|
|
291
311
|
};
|
|
292
312
|
if (iterationType === IterationType.RECURSIVE) {
|
|
293
|
-
_dfs(
|
|
313
|
+
_dfs(sorted);
|
|
294
314
|
} else {
|
|
295
315
|
_iterate();
|
|
296
316
|
}
|
|
@@ -318,7 +338,7 @@ export class BST<V = any, N extends BSTNode<V, N> = BSTNode<V, BSTNodeNested<V>>
|
|
|
318
338
|
* the key of the leftmost node if the comparison result is greater than, and the key of the
|
|
319
339
|
* rightmost node otherwise. If no node is found, it returns 0.
|
|
320
340
|
*/
|
|
321
|
-
lastKey(beginRoot:
|
|
341
|
+
lastKey(beginRoot: BSTNodeKeyOrNode<N> = this.root, iterationType = this.iterationType): BTNKey {
|
|
322
342
|
if (this._compare(0, 1) === CP.lt) return this.getRightMost(beginRoot, iterationType)?.key ?? 0;
|
|
323
343
|
else if (this._compare(0, 1) === CP.gt) return this.getLeftMost(beginRoot, iterationType)?.key ?? 0;
|
|
324
344
|
else return this.getRightMost(beginRoot, iterationType)?.key ?? 0;
|
|
@@ -374,7 +394,7 @@ export class BST<V = any, N extends BSTNode<V, N> = BSTNode<V, BSTNodeNested<V>>
|
|
|
374
394
|
*/
|
|
375
395
|
|
|
376
396
|
/**
|
|
377
|
-
* The function `
|
|
397
|
+
* The function `ensureNode` returns the node corresponding to the given key if it is a node key,
|
|
378
398
|
* otherwise it returns the key itself.
|
|
379
399
|
* @param {BTNKey | N | undefined} key - The `key` parameter can be of type `BTNKey`, `N`, or
|
|
380
400
|
* `undefined`.
|
|
@@ -382,7 +402,7 @@ export class BST<V = any, N extends BSTNode<V, N> = BSTNode<V, BSTNodeNested<V>>
|
|
|
382
402
|
* type of iteration to be performed. It has a default value of `IterationType.ITERATIVE`.
|
|
383
403
|
* @returns either a node object (N) or undefined.
|
|
384
404
|
*/
|
|
385
|
-
override
|
|
405
|
+
override ensureNode(key: BSTNodeKeyOrNode<N>, iterationType = IterationType.ITERATIVE): N | undefined {
|
|
386
406
|
return this.isNodeKey(key) ? this.getNodeByKey(key, iterationType) : key;
|
|
387
407
|
}
|
|
388
408
|
|
|
@@ -413,10 +433,10 @@ export class BST<V = any, N extends BSTNode<V, N> = BSTNode<V, BSTNodeNested<V>>
|
|
|
413
433
|
identifier: ReturnType<C> | undefined,
|
|
414
434
|
callback: C = this._defaultOneParamCallback as C,
|
|
415
435
|
onlyOne = false,
|
|
416
|
-
beginRoot:
|
|
436
|
+
beginRoot: BSTNodeKeyOrNode<N> = this.root,
|
|
417
437
|
iterationType = this.iterationType
|
|
418
438
|
): N[] {
|
|
419
|
-
beginRoot = this.
|
|
439
|
+
beginRoot = this.ensureNode(beginRoot);
|
|
420
440
|
if (!beginRoot) return [];
|
|
421
441
|
const ans: N[] = [];
|
|
422
442
|
|
|
@@ -494,10 +514,10 @@ export class BST<V = any, N extends BSTNode<V, N> = BSTNode<V, BSTNodeNested<V>>
|
|
|
494
514
|
lesserOrGreaterTraverse<C extends BTNCallback<N>>(
|
|
495
515
|
callback: C = this._defaultOneParamCallback as C,
|
|
496
516
|
lesserOrGreater: CP = CP.lt,
|
|
497
|
-
targetNode:
|
|
517
|
+
targetNode: BSTNodeKeyOrNode<N> = this.root,
|
|
498
518
|
iterationType = this.iterationType
|
|
499
519
|
): ReturnType<C>[] {
|
|
500
|
-
targetNode = this.
|
|
520
|
+
targetNode = this.ensureNode(targetNode);
|
|
501
521
|
const ans: ReturnType<BTNCallback<N>>[] = [];
|
|
502
522
|
if (!targetNode) return ans;
|
|
503
523
|
if (!this.root) return ans;
|
|
@@ -559,7 +579,7 @@ export class BST<V = any, N extends BSTNode<V, N> = BSTNode<V, BSTNodeNested<V>>
|
|
|
559
579
|
if (l > r) return;
|
|
560
580
|
const m = l + Math.floor((r - l) / 2);
|
|
561
581
|
const midNode = sorted[m];
|
|
562
|
-
this.add(midNode.key, midNode.value);
|
|
582
|
+
this.add([midNode.key, midNode.value]);
|
|
563
583
|
buildBalanceBST(l, m - 1);
|
|
564
584
|
buildBalanceBST(m + 1, r);
|
|
565
585
|
};
|
|
@@ -576,7 +596,7 @@ export class BST<V = any, N extends BSTNode<V, N> = BSTNode<V, BSTNodeNested<V>>
|
|
|
576
596
|
const m = l + Math.floor((r - l) / 2);
|
|
577
597
|
const midNode = sorted[m];
|
|
578
598
|
debugger;
|
|
579
|
-
this.add(midNode.key, midNode.value);
|
|
599
|
+
this.add([midNode.key, midNode.value]);
|
|
580
600
|
stack.push([m + 1, r]);
|
|
581
601
|
stack.push([l, m - 1]);
|
|
582
602
|
}
|
|
@@ -654,23 +674,6 @@ export class BST<V = any, N extends BSTNode<V, N> = BSTNode<V, BSTNodeNested<V>>
|
|
|
654
674
|
return balanced;
|
|
655
675
|
}
|
|
656
676
|
|
|
657
|
-
/**
|
|
658
|
-
* Time Complexity: O(n) - Visiting each node once.
|
|
659
|
-
* Space Complexity: O(log n) - Space for the recursive call stack in the worst case.
|
|
660
|
-
*/
|
|
661
|
-
|
|
662
|
-
init(elements: IterableEntriesOrKeys<V>): void {
|
|
663
|
-
if (elements) {
|
|
664
|
-
for (const entryOrKey of elements) {
|
|
665
|
-
if (Array.isArray(entryOrKey)) {
|
|
666
|
-
const [key, value] = entryOrKey;
|
|
667
|
-
this.add(key, value);
|
|
668
|
-
} else {
|
|
669
|
-
this.add(entryOrKey);
|
|
670
|
-
}
|
|
671
|
-
}
|
|
672
|
-
}
|
|
673
|
-
}
|
|
674
677
|
|
|
675
678
|
protected _setRoot(v: N | undefined) {
|
|
676
679
|
if (v) {
|
|
@@ -8,9 +8,10 @@
|
|
|
8
8
|
|
|
9
9
|
import {
|
|
10
10
|
BiTreeDeleteResult,
|
|
11
|
+
BSTNodeKeyOrNode,
|
|
11
12
|
BTNCallback,
|
|
12
13
|
BTNKey,
|
|
13
|
-
|
|
14
|
+
BTNodeExemplar,
|
|
14
15
|
IterationType,
|
|
15
16
|
RBTNColor,
|
|
16
17
|
RBTreeOptions,
|
|
@@ -45,17 +46,22 @@ export class RedBlackTree<V = any, N extends RedBlackTreeNode<V, N> = RedBlackTr
|
|
|
45
46
|
implements IBinaryTree<V, N, TREE> {
|
|
46
47
|
Sentinel: N = new RedBlackTreeNode<V>(NaN) as unknown as N;
|
|
47
48
|
|
|
48
|
-
|
|
49
49
|
/**
|
|
50
|
-
*
|
|
51
|
-
*
|
|
52
|
-
*
|
|
50
|
+
* This is the constructor function for a Red-Black Tree data structure in TypeScript, which
|
|
51
|
+
* initializes the tree with optional elements and options.
|
|
52
|
+
* @param [elements] - The `elements` parameter is an optional iterable of `BTNodeExemplar<V, N>`
|
|
53
|
+
* objects. It represents the initial elements that will be added to the RBTree during its
|
|
54
|
+
* construction. If this parameter is provided, the `addMany` method is called to add all the
|
|
55
|
+
* elements to the
|
|
56
|
+
* @param [options] - The `options` parameter is an optional object that allows you to customize the
|
|
57
|
+
* behavior of the RBTree. It is of type `Partial<RBTreeOptions>`, which means that you can provide
|
|
58
|
+
* only a subset of the properties defined in the `RBTreeOptions` interface.
|
|
53
59
|
*/
|
|
54
|
-
constructor(elements?:
|
|
60
|
+
constructor(elements?: Iterable<BTNodeExemplar<V, N>>, options?: Partial<RBTreeOptions>) {
|
|
55
61
|
super([], options);
|
|
56
62
|
|
|
57
63
|
this._root = this.Sentinel;
|
|
58
|
-
if (elements)
|
|
64
|
+
if (elements) super.addMany(elements);
|
|
59
65
|
}
|
|
60
66
|
|
|
61
67
|
protected _root: N;
|
|
@@ -70,10 +76,29 @@ export class RedBlackTree<V = any, N extends RedBlackTreeNode<V, N> = RedBlackTr
|
|
|
70
76
|
return this._size;
|
|
71
77
|
}
|
|
72
78
|
|
|
79
|
+
/**
|
|
80
|
+
* The function creates a new Red-Black Tree node with the specified key, value, and color.
|
|
81
|
+
* @param {BTNKey} key - The key parameter is the key value associated with the node. It is used to
|
|
82
|
+
* identify and compare nodes in the Red-Black Tree.
|
|
83
|
+
* @param {V} [value] - The `value` parameter is an optional parameter that represents the value
|
|
84
|
+
* associated with the node. It is of type `V`, which is a generic type that can be replaced with any
|
|
85
|
+
* specific type when using the `createNode` method.
|
|
86
|
+
* @param {RBTNColor} color - The "color" parameter is used to specify the color of the node in a
|
|
87
|
+
* Red-Black Tree. It can be either "RED" or "BLACK". By default, the color is set to "BLACK".
|
|
88
|
+
* @returns The method is returning a new instance of a RedBlackTreeNode with the specified key,
|
|
89
|
+
* value, and color.
|
|
90
|
+
*/
|
|
73
91
|
override createNode(key: BTNKey, value?: V, color: RBTNColor = RBTNColor.BLACK): N {
|
|
74
92
|
return new RedBlackTreeNode<V, N>(key, value, color) as N;
|
|
75
93
|
}
|
|
76
94
|
|
|
95
|
+
/**
|
|
96
|
+
* The function creates a Red-Black Tree with the specified options and returns it.
|
|
97
|
+
* @param {RBTreeOptions} [options] - The `options` parameter is an optional object that can be
|
|
98
|
+
* passed to the `createTree` function. It is used to customize the behavior of the `RedBlackTree`
|
|
99
|
+
* class.
|
|
100
|
+
* @returns a new instance of a RedBlackTree object.
|
|
101
|
+
*/
|
|
77
102
|
override createTree(options?: RBTreeOptions): TREE {
|
|
78
103
|
return new RedBlackTree<V, N, TREE>([], {
|
|
79
104
|
iterationType: this.iterationType,
|
|
@@ -84,24 +109,30 @@ export class RedBlackTree<V = any, N extends RedBlackTreeNode<V, N> = RedBlackTr
|
|
|
84
109
|
/**
|
|
85
110
|
* Time Complexity: O(log n) on average (where n is the number of nodes in the tree)
|
|
86
111
|
* Space Complexity: O(1)
|
|
87
|
-
*
|
|
88
|
-
* The `add` function adds a new node to a Red-Black Tree data structure.
|
|
89
|
-
* @param {BTNKey | N | null | undefined} keyOrNode - The `keyOrNode` parameter can be one of the
|
|
90
|
-
* following types:
|
|
91
|
-
* @param {V} [value] - The `value` parameter is an optional value that can be associated with the
|
|
92
|
-
* key in the node being added to the Red-Black Tree.
|
|
93
|
-
* @returns The method returns either a node (`N`) or `undefined`.
|
|
94
112
|
*/
|
|
95
|
-
|
|
113
|
+
|
|
114
|
+
|
|
115
|
+
/**
|
|
116
|
+
* The function adds a node to a Red-Black Tree data structure.
|
|
117
|
+
* @param keyOrNodeOrEntry - The `keyOrNodeOrEntry` parameter can be one of the following:
|
|
118
|
+
* @returns The method `add` returns either an instance of `N` (the node that was added) or
|
|
119
|
+
* `undefined`.
|
|
120
|
+
*/
|
|
121
|
+
override add(keyOrNodeOrEntry: BTNodeExemplar<V, N>): N | undefined {
|
|
96
122
|
let node: N;
|
|
97
|
-
if (this.isNodeKey(
|
|
98
|
-
node = this.createNode(
|
|
99
|
-
} else if (
|
|
100
|
-
node =
|
|
101
|
-
} else if (
|
|
102
|
-
return;
|
|
103
|
-
} else if (keyOrNode === undefined) {
|
|
123
|
+
if (this.isNodeKey(keyOrNodeOrEntry)) {
|
|
124
|
+
node = this.createNode(keyOrNodeOrEntry, undefined, RBTNColor.RED);
|
|
125
|
+
} else if (keyOrNodeOrEntry instanceof RedBlackTreeNode) {
|
|
126
|
+
node = keyOrNodeOrEntry;
|
|
127
|
+
} else if (keyOrNodeOrEntry === null || keyOrNodeOrEntry === undefined) {
|
|
104
128
|
return;
|
|
129
|
+
} else if (this.isEntry(keyOrNodeOrEntry)) {
|
|
130
|
+
const [key, value] = keyOrNodeOrEntry;
|
|
131
|
+
if (key === undefined || key === null) {
|
|
132
|
+
return;
|
|
133
|
+
} else {
|
|
134
|
+
node = this.createNode(key, value, RBTNColor.RED);
|
|
135
|
+
}
|
|
105
136
|
} else {
|
|
106
137
|
return;
|
|
107
138
|
}
|
|
@@ -120,6 +151,9 @@ export class RedBlackTree<V = any, N extends RedBlackTreeNode<V, N> = RedBlackTr
|
|
|
120
151
|
} else if (node.key > x.key) {
|
|
121
152
|
x = x?.right;
|
|
122
153
|
} else {
|
|
154
|
+
if (node !== x) {
|
|
155
|
+
this._replaceNode(x, node)
|
|
156
|
+
}
|
|
123
157
|
return;
|
|
124
158
|
}
|
|
125
159
|
}
|
|
@@ -261,6 +295,11 @@ export class RedBlackTree<V = any, N extends RedBlackTreeNode<V, N> = RedBlackTr
|
|
|
261
295
|
iterationType?: IterationType
|
|
262
296
|
): N | undefined;
|
|
263
297
|
|
|
298
|
+
/**
|
|
299
|
+
* Time Complexity: O(log n) on average (where n is the number of nodes in the tree)
|
|
300
|
+
* Space Complexity: O(1)
|
|
301
|
+
*/
|
|
302
|
+
|
|
264
303
|
/**
|
|
265
304
|
* Time Complexity: O(log n) on average (where n is the number of nodes in the tree)
|
|
266
305
|
* Space Complexity: O(1)
|
|
@@ -285,11 +324,11 @@ export class RedBlackTree<V = any, N extends RedBlackTreeNode<V, N> = RedBlackTr
|
|
|
285
324
|
getNode<C extends BTNCallback<N>>(
|
|
286
325
|
identifier: ReturnType<C> | undefined,
|
|
287
326
|
callback: C = this._defaultOneParamCallback as C,
|
|
288
|
-
beginRoot:
|
|
327
|
+
beginRoot: BSTNodeKeyOrNode<N> = this.root,
|
|
289
328
|
iterationType = this.iterationType
|
|
290
329
|
): N | null | undefined {
|
|
291
330
|
if ((identifier as any) instanceof BinaryTreeNode) callback = (node => node) as C;
|
|
292
|
-
beginRoot = this.
|
|
331
|
+
beginRoot = this.ensureNode(beginRoot);
|
|
293
332
|
return this.getNodes(identifier, callback, true, beginRoot, iterationType)[0] ?? undefined;
|
|
294
333
|
}
|
|
295
334
|
|
|
@@ -357,19 +396,6 @@ export class RedBlackTree<V = any, N extends RedBlackTreeNode<V, N> = RedBlackTr
|
|
|
357
396
|
this._size = 0;
|
|
358
397
|
}
|
|
359
398
|
|
|
360
|
-
init(elements: IterableEntriesOrKeys<V>): void {
|
|
361
|
-
if (elements) {
|
|
362
|
-
for (const entryOrKey of elements) {
|
|
363
|
-
if (Array.isArray(entryOrKey)) {
|
|
364
|
-
const [key, value] = entryOrKey;
|
|
365
|
-
this.add(key, value);
|
|
366
|
-
} else {
|
|
367
|
-
this.add(entryOrKey);
|
|
368
|
-
}
|
|
369
|
-
}
|
|
370
|
-
}
|
|
371
|
-
}
|
|
372
|
-
|
|
373
399
|
protected override _setRoot(v: N) {
|
|
374
400
|
if (v) {
|
|
375
401
|
v.parent = undefined;
|
|
@@ -596,4 +622,19 @@ export class RedBlackTree<V = any, N extends RedBlackTreeNode<V, N> = RedBlackTr
|
|
|
596
622
|
}
|
|
597
623
|
this.root.color = RBTNColor.BLACK;
|
|
598
624
|
}
|
|
625
|
+
|
|
626
|
+
/**
|
|
627
|
+
* The function replaces an old node with a new node while preserving the color of the old node.
|
|
628
|
+
* @param {N} oldNode - The `oldNode` parameter represents the node that needs to be replaced in a
|
|
629
|
+
* data structure. It is of type `N`, which is the type of the nodes in the data structure.
|
|
630
|
+
* @param {N} newNode - The `newNode` parameter is the node that will replace the `oldNode` in the
|
|
631
|
+
* data structure.
|
|
632
|
+
* @returns The method is returning the result of calling the `_replaceNode` method from the
|
|
633
|
+
* superclass, passing in the `oldNode` and `newNode` as arguments.
|
|
634
|
+
*/
|
|
635
|
+
protected _replaceNode(oldNode: N, newNode: N): N {
|
|
636
|
+
newNode.color = oldNode.color;
|
|
637
|
+
|
|
638
|
+
return super._replaceNode(oldNode, newNode)
|
|
639
|
+
}
|
|
599
640
|
}
|