min-heap-typed 1.50.1 → 1.50.3
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/base/iterable-base.d.ts +120 -9
- package/dist/data-structures/base/iterable-base.js +143 -7
- package/dist/data-structures/binary-tree/avl-tree.d.ts +72 -47
- package/dist/data-structures/binary-tree/avl-tree.js +101 -72
- package/dist/data-structures/binary-tree/binary-indexed-tree.d.ts +22 -0
- package/dist/data-structures/binary-tree/binary-indexed-tree.js +22 -0
- package/dist/data-structures/binary-tree/binary-tree.d.ts +244 -199
- package/dist/data-structures/binary-tree/binary-tree.js +484 -376
- package/dist/data-structures/binary-tree/bst.d.ts +92 -79
- package/dist/data-structures/binary-tree/bst.js +68 -76
- package/dist/data-structures/binary-tree/rb-tree.d.ts +127 -57
- package/dist/data-structures/binary-tree/rb-tree.js +152 -99
- package/dist/data-structures/binary-tree/segment-tree.d.ts +99 -6
- package/dist/data-structures/binary-tree/segment-tree.js +127 -10
- package/dist/data-structures/binary-tree/tree-multimap.d.ts +72 -58
- package/dist/data-structures/binary-tree/tree-multimap.js +102 -85
- package/dist/data-structures/graph/abstract-graph.d.ts +1 -78
- package/dist/data-structures/graph/abstract-graph.js +3 -189
- package/dist/data-structures/graph/directed-graph.d.ts +73 -0
- package/dist/data-structures/graph/directed-graph.js +131 -0
- package/dist/data-structures/graph/map-graph.d.ts +8 -0
- package/dist/data-structures/graph/map-graph.js +14 -0
- package/dist/data-structures/graph/undirected-graph.d.ts +76 -7
- package/dist/data-structures/graph/undirected-graph.js +151 -18
- package/dist/data-structures/hash/hash-map.d.ts +254 -28
- package/dist/data-structures/hash/hash-map.js +347 -78
- package/dist/data-structures/heap/heap.d.ts +95 -25
- package/dist/data-structures/heap/heap.js +95 -26
- package/dist/data-structures/linked-list/doubly-linked-list.d.ts +126 -63
- package/dist/data-structures/linked-list/doubly-linked-list.js +141 -77
- package/dist/data-structures/linked-list/singly-linked-list.d.ts +154 -106
- package/dist/data-structures/linked-list/singly-linked-list.js +164 -115
- package/dist/data-structures/linked-list/skip-linked-list.d.ts +63 -36
- package/dist/data-structures/linked-list/skip-linked-list.js +63 -36
- package/dist/data-structures/matrix/matrix.d.ts +35 -4
- package/dist/data-structures/matrix/matrix.js +50 -11
- package/dist/data-structures/priority-queue/max-priority-queue.d.ts +10 -0
- package/dist/data-structures/priority-queue/max-priority-queue.js +10 -0
- package/dist/data-structures/priority-queue/min-priority-queue.d.ts +11 -0
- package/dist/data-structures/priority-queue/min-priority-queue.js +11 -0
- package/dist/data-structures/priority-queue/priority-queue.d.ts +8 -0
- package/dist/data-structures/priority-queue/priority-queue.js +8 -0
- package/dist/data-structures/queue/deque.d.ts +139 -35
- package/dist/data-structures/queue/deque.js +200 -62
- package/dist/data-structures/queue/queue.d.ts +103 -49
- package/dist/data-structures/queue/queue.js +111 -49
- package/dist/data-structures/stack/stack.d.ts +51 -21
- package/dist/data-structures/stack/stack.js +58 -22
- package/dist/data-structures/tree/tree.d.ts +57 -3
- package/dist/data-structures/tree/tree.js +77 -11
- package/dist/data-structures/trie/trie.d.ts +135 -34
- package/dist/data-structures/trie/trie.js +153 -33
- package/dist/types/data-structures/binary-tree/binary-tree.d.ts +1 -1
- package/dist/types/data-structures/hash/hash-map.d.ts +4 -3
- package/dist/types/utils/utils.d.ts +1 -0
- package/package.json +2 -2
- package/src/data-structures/base/iterable-base.ts +184 -19
- package/src/data-structures/binary-tree/avl-tree.ts +134 -100
- package/src/data-structures/binary-tree/binary-indexed-tree.ts +22 -0
- package/src/data-structures/binary-tree/binary-tree.ts +674 -671
- package/src/data-structures/binary-tree/bst.ts +127 -136
- package/src/data-structures/binary-tree/rb-tree.ts +199 -166
- package/src/data-structures/binary-tree/segment-tree.ts +145 -11
- package/src/data-structures/binary-tree/tree-multimap.ts +138 -115
- package/src/data-structures/graph/abstract-graph.ts +4 -211
- package/src/data-structures/graph/directed-graph.ts +152 -0
- package/src/data-structures/graph/map-graph.ts +15 -0
- package/src/data-structures/graph/undirected-graph.ts +171 -19
- package/src/data-structures/hash/hash-map.ts +389 -96
- package/src/data-structures/heap/heap.ts +97 -26
- package/src/data-structures/linked-list/doubly-linked-list.ts +156 -83
- package/src/data-structures/linked-list/singly-linked-list.ts +174 -120
- package/src/data-structures/linked-list/skip-linked-list.ts +63 -37
- package/src/data-structures/matrix/matrix.ts +52 -12
- package/src/data-structures/priority-queue/max-priority-queue.ts +10 -0
- package/src/data-structures/priority-queue/min-priority-queue.ts +11 -0
- package/src/data-structures/priority-queue/priority-queue.ts +8 -0
- package/src/data-structures/queue/deque.ts +225 -70
- package/src/data-structures/queue/queue.ts +118 -49
- package/src/data-structures/stack/stack.ts +63 -23
- package/src/data-structures/tree/tree.ts +89 -15
- package/src/data-structures/trie/trie.ts +173 -38
- package/src/types/data-structures/binary-tree/binary-tree.ts +1 -1
- package/src/types/data-structures/hash/hash-map.ts +4 -3
- package/src/types/utils/utils.ts +2 -0
|
@@ -154,6 +154,105 @@ export abstract class IterableEntryBase<K = any, V = any> {
|
|
|
154
154
|
* Time Complexity: O(n)
|
|
155
155
|
* Space Complexity: O(1)
|
|
156
156
|
*/
|
|
157
|
+
|
|
158
|
+
/**
|
|
159
|
+
* Time Complexity: O(n)
|
|
160
|
+
* Space Complexity: O(1)
|
|
161
|
+
*
|
|
162
|
+
* The `find` function iterates over the entries of a collection and returns the first value for
|
|
163
|
+
* which the callback function returns true.
|
|
164
|
+
* @param callbackfn - The callback function that will be called for each entry in the collection. It
|
|
165
|
+
* takes three arguments: the value of the entry, the key of the entry, and the index of the entry in
|
|
166
|
+
* the collection. It should return a boolean value indicating whether the current entry matches the
|
|
167
|
+
* desired condition.
|
|
168
|
+
* @param {any} [thisArg] - The `thisArg` parameter is an optional argument that specifies the value
|
|
169
|
+
* to be used as `this` when executing the `callbackfn` function. If `thisArg` is provided, it will
|
|
170
|
+
* be passed as the `this` value to the `callbackfn` function. If `thisArg
|
|
171
|
+
* @returns The method `find` returns the value of the first element in the iterable that satisfies
|
|
172
|
+
* the provided callback function. If no element satisfies the callback function, `undefined` is
|
|
173
|
+
* returned.
|
|
174
|
+
*/
|
|
175
|
+
find(callbackfn: EntryCallback<K, V, [K, V]>, thisArg?: any): [K, V] | undefined {
|
|
176
|
+
let index = 0;
|
|
177
|
+
for (const item of this) {
|
|
178
|
+
const [key, value] = item;
|
|
179
|
+
if (callbackfn.call(thisArg, value, key, index++, this)) return item;
|
|
180
|
+
}
|
|
181
|
+
return;
|
|
182
|
+
}
|
|
183
|
+
|
|
184
|
+
/**
|
|
185
|
+
* Time Complexity: O(n)
|
|
186
|
+
* Space Complexity: O(1)
|
|
187
|
+
*/
|
|
188
|
+
|
|
189
|
+
/**
|
|
190
|
+
* Time Complexity: O(n)
|
|
191
|
+
* Space Complexity: O(1)
|
|
192
|
+
*
|
|
193
|
+
* The function checks if a given key exists in a collection.
|
|
194
|
+
* @param {K} key - The parameter "key" is of type K, which means it can be any type. It represents
|
|
195
|
+
* the key that we want to check for existence in the data structure.
|
|
196
|
+
* @returns a boolean value. It returns true if the key is found in the collection, and false
|
|
197
|
+
* otherwise.
|
|
198
|
+
*/
|
|
199
|
+
has(key: K): boolean {
|
|
200
|
+
for (const item of this) {
|
|
201
|
+
const [itemKey] = item;
|
|
202
|
+
if (itemKey === key) return true;
|
|
203
|
+
}
|
|
204
|
+
return false;
|
|
205
|
+
}
|
|
206
|
+
|
|
207
|
+
/**
|
|
208
|
+
* Time Complexity: O(n)
|
|
209
|
+
* Space Complexity: O(1)
|
|
210
|
+
*/
|
|
211
|
+
|
|
212
|
+
/**
|
|
213
|
+
* Time Complexity: O(n)
|
|
214
|
+
* Space Complexity: O(1)
|
|
215
|
+
*
|
|
216
|
+
* The function checks if a given value exists in a collection.
|
|
217
|
+
* @param {V} value - The parameter "value" is the value that we want to check if it exists in the
|
|
218
|
+
* collection.
|
|
219
|
+
* @returns a boolean value, either true or false.
|
|
220
|
+
*/
|
|
221
|
+
hasValue(value: V): boolean {
|
|
222
|
+
for (const [, elementValue] of this) {
|
|
223
|
+
if (elementValue === value) return true;
|
|
224
|
+
}
|
|
225
|
+
return false;
|
|
226
|
+
}
|
|
227
|
+
|
|
228
|
+
/**
|
|
229
|
+
* Time Complexity: O(n)
|
|
230
|
+
* Space Complexity: O(1)
|
|
231
|
+
*/
|
|
232
|
+
|
|
233
|
+
/**
|
|
234
|
+
* Time Complexity: O(n)
|
|
235
|
+
* Space Complexity: O(1)
|
|
236
|
+
*
|
|
237
|
+
* The `get` function retrieves the value associated with a given key from a collection.
|
|
238
|
+
* @param {K} key - K (the type of the key) - This parameter represents the key that is being
|
|
239
|
+
* searched for in the collection.
|
|
240
|
+
* @returns The `get` method returns the value associated with the specified key if it exists in the
|
|
241
|
+
* collection, otherwise it returns `undefined`.
|
|
242
|
+
*/
|
|
243
|
+
get(key: K): V | undefined {
|
|
244
|
+
for (const item of this) {
|
|
245
|
+
const [itemKey, value] = item;
|
|
246
|
+
if (itemKey === key) return value;
|
|
247
|
+
}
|
|
248
|
+
return;
|
|
249
|
+
}
|
|
250
|
+
|
|
251
|
+
/**
|
|
252
|
+
* Time Complexity: O(n)
|
|
253
|
+
* Space Complexity: O(1)
|
|
254
|
+
*/
|
|
255
|
+
|
|
157
256
|
/**
|
|
158
257
|
* Time Complexity: O(n)
|
|
159
258
|
* Space Complexity: O(1)
|
|
@@ -180,13 +279,6 @@ export abstract class IterableEntryBase<K = any, V = any> {
|
|
|
180
279
|
return accumulator;
|
|
181
280
|
}
|
|
182
281
|
|
|
183
|
-
hasValue(value: V): boolean {
|
|
184
|
-
for (const [, elementValue] of this) {
|
|
185
|
-
if (elementValue === value) return true;
|
|
186
|
-
}
|
|
187
|
-
return false;
|
|
188
|
-
}
|
|
189
|
-
|
|
190
282
|
/**
|
|
191
283
|
* Time Complexity: O(n)
|
|
192
284
|
* Space Complexity: O(n)
|
|
@@ -195,10 +287,20 @@ export abstract class IterableEntryBase<K = any, V = any> {
|
|
|
195
287
|
console.log([...this]);
|
|
196
288
|
}
|
|
197
289
|
|
|
290
|
+
abstract isEmpty(): boolean;
|
|
291
|
+
|
|
292
|
+
abstract clear(): void;
|
|
293
|
+
|
|
294
|
+
abstract clone(): any;
|
|
295
|
+
|
|
296
|
+
abstract map(...args: any[]): any;
|
|
297
|
+
|
|
298
|
+
abstract filter(...args: any[]): any;
|
|
299
|
+
|
|
198
300
|
protected abstract _getIterator(...args: any[]): IterableIterator<[K, V]>;
|
|
199
301
|
}
|
|
200
302
|
|
|
201
|
-
export abstract class IterableElementBase<
|
|
303
|
+
export abstract class IterableElementBase<E = any, C = any> {
|
|
202
304
|
/**
|
|
203
305
|
* Time Complexity: O(n)
|
|
204
306
|
* Space Complexity: O(1)
|
|
@@ -212,7 +314,7 @@ export abstract class IterableElementBase<V> {
|
|
|
212
314
|
* allows the function to accept any number of arguments as an array. In this case, the `args`
|
|
213
315
|
* parameter is used to pass any number of arguments to the `_getIterator` method.
|
|
214
316
|
*/
|
|
215
|
-
* [Symbol.iterator](...args: any[]): IterableIterator<
|
|
317
|
+
* [Symbol.iterator](...args: any[]): IterableIterator<E> {
|
|
216
318
|
yield* this._getIterator(...args);
|
|
217
319
|
}
|
|
218
320
|
|
|
@@ -226,7 +328,7 @@ export abstract class IterableElementBase<V> {
|
|
|
226
328
|
*
|
|
227
329
|
* The function returns an iterator that yields all the values in the object.
|
|
228
330
|
*/
|
|
229
|
-
* values(): IterableIterator<
|
|
331
|
+
* values(): IterableIterator<E> {
|
|
230
332
|
for (const item of this) {
|
|
231
333
|
yield item;
|
|
232
334
|
}
|
|
@@ -250,10 +352,10 @@ export abstract class IterableElementBase<V> {
|
|
|
250
352
|
* @returns The `every` method is returning a boolean value. It returns `true` if every element in
|
|
251
353
|
* the array satisfies the provided predicate function, and `false` otherwise.
|
|
252
354
|
*/
|
|
253
|
-
every(predicate: ElementCallback<
|
|
355
|
+
every(predicate: ElementCallback<E, boolean>, thisArg?: any): boolean {
|
|
254
356
|
let index = 0;
|
|
255
357
|
for (const item of this) {
|
|
256
|
-
if (!predicate.call(thisArg, item
|
|
358
|
+
if (!predicate.call(thisArg, item, index++, this)) {
|
|
257
359
|
return false;
|
|
258
360
|
}
|
|
259
361
|
}
|
|
@@ -278,10 +380,10 @@ export abstract class IterableElementBase<V> {
|
|
|
278
380
|
* @returns a boolean value. It returns true if the predicate function returns true for any element
|
|
279
381
|
* in the collection, and false otherwise.
|
|
280
382
|
*/
|
|
281
|
-
some(predicate: ElementCallback<
|
|
383
|
+
some(predicate: ElementCallback<E, boolean>, thisArg?: any): boolean {
|
|
282
384
|
let index = 0;
|
|
283
385
|
for (const item of this) {
|
|
284
|
-
if (predicate.call(thisArg, item
|
|
386
|
+
if (predicate.call(thisArg, item, index++, this)) {
|
|
285
387
|
return true;
|
|
286
388
|
}
|
|
287
389
|
}
|
|
@@ -292,6 +394,7 @@ export abstract class IterableElementBase<V> {
|
|
|
292
394
|
* Time Complexity: O(n)
|
|
293
395
|
* Space Complexity: O(1)
|
|
294
396
|
*/
|
|
397
|
+
|
|
295
398
|
/**
|
|
296
399
|
* Time Complexity: O(n)
|
|
297
400
|
* Space Complexity: O(1)
|
|
@@ -305,11 +408,63 @@ export abstract class IterableElementBase<V> {
|
|
|
305
408
|
* to be used as `this` when executing the `callbackfn` function. If `thisArg` is provided, it will
|
|
306
409
|
* be passed as the `this` value to the `callbackfn` function. If `thisArg
|
|
307
410
|
*/
|
|
308
|
-
forEach(callbackfn: ElementCallback<
|
|
411
|
+
forEach(callbackfn: ElementCallback<E, void>, thisArg?: any): void {
|
|
412
|
+
let index = 0;
|
|
413
|
+
for (const item of this) {
|
|
414
|
+
callbackfn.call(thisArg, item, index++, this);
|
|
415
|
+
}
|
|
416
|
+
}
|
|
417
|
+
|
|
418
|
+
/**
|
|
419
|
+
* Time Complexity: O(n)
|
|
420
|
+
* Space Complexity: O(1)
|
|
421
|
+
*/
|
|
422
|
+
|
|
423
|
+
/**
|
|
424
|
+
* Time Complexity: O(n)
|
|
425
|
+
* Space Complexity: O(1)
|
|
426
|
+
*
|
|
427
|
+
* The `find` function iterates over the elements of an array-like object and returns the first
|
|
428
|
+
* element that satisfies the provided callback function.
|
|
429
|
+
* @param callbackfn - The callbackfn parameter is a function that will be called for each element in
|
|
430
|
+
* the array. It takes three arguments: the current element being processed, the index of the current
|
|
431
|
+
* element, and the array itself. The function should return a boolean value indicating whether the
|
|
432
|
+
* current element matches the desired condition.
|
|
433
|
+
* @param {any} [thisArg] - The `thisArg` parameter is an optional argument that specifies the value
|
|
434
|
+
* to be used as `this` when executing the `callbackfn` function. If `thisArg` is provided, it will
|
|
435
|
+
* be passed as the `this` value to the `callbackfn` function. If `thisArg
|
|
436
|
+
* @returns The `find` method returns the first element in the array that satisfies the provided
|
|
437
|
+
* callback function. If no element satisfies the callback function, `undefined` is returned.
|
|
438
|
+
*/
|
|
439
|
+
find(callbackfn: ElementCallback<E, boolean>, thisArg?: any): E | undefined {
|
|
309
440
|
let index = 0;
|
|
310
441
|
for (const item of this) {
|
|
311
|
-
callbackfn.call(thisArg, item
|
|
442
|
+
if (callbackfn.call(thisArg, item, index++, this)) return item;
|
|
443
|
+
}
|
|
444
|
+
|
|
445
|
+
return;
|
|
446
|
+
}
|
|
447
|
+
|
|
448
|
+
/**
|
|
449
|
+
* Time Complexity: O(n)
|
|
450
|
+
* Space Complexity: O(1)
|
|
451
|
+
*/
|
|
452
|
+
|
|
453
|
+
/**
|
|
454
|
+
* Time Complexity: O(n)
|
|
455
|
+
* Space Complexity: O(1)
|
|
456
|
+
*
|
|
457
|
+
* The function checks if a given element exists in a collection.
|
|
458
|
+
* @param {E} element - The parameter "element" is of type E, which means it can be any type. It
|
|
459
|
+
* represents the element that we want to check for existence in the collection.
|
|
460
|
+
* @returns a boolean value. It returns true if the element is found in the collection, and false
|
|
461
|
+
* otherwise.
|
|
462
|
+
*/
|
|
463
|
+
has(element: E): boolean {
|
|
464
|
+
for (const ele of this) {
|
|
465
|
+
if (ele === element) return true;
|
|
312
466
|
}
|
|
467
|
+
return false;
|
|
313
468
|
}
|
|
314
469
|
|
|
315
470
|
/**
|
|
@@ -329,11 +484,11 @@ export abstract class IterableElementBase<V> {
|
|
|
329
484
|
* @returns The `reduce` method is returning the final value of the accumulator after iterating over
|
|
330
485
|
* all the elements in the array and applying the callback function to each element.
|
|
331
486
|
*/
|
|
332
|
-
reduce<U>(callbackfn: ReduceElementCallback<
|
|
487
|
+
reduce<U>(callbackfn: ReduceElementCallback<E, U>, initialValue: U): U {
|
|
333
488
|
let accumulator = initialValue;
|
|
334
489
|
let index = 0;
|
|
335
490
|
for (const item of this) {
|
|
336
|
-
accumulator = callbackfn(accumulator, item as
|
|
491
|
+
accumulator = callbackfn(accumulator, item as E, index++, this);
|
|
337
492
|
}
|
|
338
493
|
return accumulator;
|
|
339
494
|
}
|
|
@@ -346,5 +501,15 @@ export abstract class IterableElementBase<V> {
|
|
|
346
501
|
console.log([...this]);
|
|
347
502
|
}
|
|
348
503
|
|
|
349
|
-
|
|
504
|
+
abstract isEmpty(): boolean;
|
|
505
|
+
|
|
506
|
+
abstract clear(): void;
|
|
507
|
+
|
|
508
|
+
abstract clone(): C;
|
|
509
|
+
|
|
510
|
+
abstract map(...args: any[]): any;
|
|
511
|
+
|
|
512
|
+
abstract filter(...args: any[]): any;
|
|
513
|
+
|
|
514
|
+
protected abstract _getIterator(...args: any[]): IterableIterator<E>;
|
|
350
515
|
}
|
|
@@ -17,16 +17,41 @@ import type {
|
|
|
17
17
|
} from '../../types';
|
|
18
18
|
import { IBinaryTree } from '../../interfaces';
|
|
19
19
|
|
|
20
|
-
export class AVLTreeNode<
|
|
21
|
-
K,
|
|
22
|
-
V,
|
|
23
|
-
|
|
24
|
-
> {
|
|
25
|
-
|
|
26
|
-
|
|
20
|
+
export class AVLTreeNode<
|
|
21
|
+
K = any,
|
|
22
|
+
V = any,
|
|
23
|
+
NODE extends AVLTreeNode<K, V, NODE> = AVLTreeNodeNested<K, V>
|
|
24
|
+
> extends BSTNode<K, V, NODE> {
|
|
25
|
+
/**
|
|
26
|
+
* The constructor function initializes a new instance of a class with a key and an optional value,
|
|
27
|
+
* and sets the height property to 0.
|
|
28
|
+
* @param {K} key - The "key" parameter is of type K, which represents the type of the key for the
|
|
29
|
+
* constructor. It is used to initialize the key property of the object being created.
|
|
30
|
+
* @param {V} [value] - The "value" parameter is an optional parameter of type V. It represents the
|
|
31
|
+
* value associated with the key in the constructor.
|
|
32
|
+
*/
|
|
27
33
|
constructor(key: K, value?: V) {
|
|
28
34
|
super(key, value);
|
|
29
|
-
this.
|
|
35
|
+
this._height = 0;
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
protected _height: number;
|
|
39
|
+
|
|
40
|
+
/**
|
|
41
|
+
* The function returns the value of the height property.
|
|
42
|
+
* @returns The height of the object.
|
|
43
|
+
*/
|
|
44
|
+
get height(): number {
|
|
45
|
+
return this._height;
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
/**
|
|
49
|
+
* The above function sets the value of the height property.
|
|
50
|
+
* @param {number} value - The value parameter is a number that represents the new height value to be
|
|
51
|
+
* set.
|
|
52
|
+
*/
|
|
53
|
+
set height(value: number) {
|
|
54
|
+
this._height = value;
|
|
30
55
|
}
|
|
31
56
|
}
|
|
32
57
|
|
|
@@ -42,21 +67,21 @@ export class AVLTreeNode<K = any, V = any, N extends AVLTreeNode<K, V, N> = AVLT
|
|
|
42
67
|
export class AVLTree<
|
|
43
68
|
K = any,
|
|
44
69
|
V = any,
|
|
45
|
-
|
|
46
|
-
TREE extends AVLTree<K, V,
|
|
70
|
+
NODE extends AVLTreeNode<K, V, NODE> = AVLTreeNode<K, V, AVLTreeNodeNested<K, V>>,
|
|
71
|
+
TREE extends AVLTree<K, V, NODE, TREE> = AVLTree<K, V, NODE, AVLTreeNested<K, V, NODE>>
|
|
47
72
|
>
|
|
48
|
-
extends BST<K, V,
|
|
49
|
-
implements IBinaryTree<K, V,
|
|
73
|
+
extends BST<K, V, NODE, TREE>
|
|
74
|
+
implements IBinaryTree<K, V, NODE, TREE> {
|
|
50
75
|
/**
|
|
51
76
|
* The constructor function initializes an AVLTree object with optional keysOrNodesOrEntries and options.
|
|
52
|
-
* @param [keysOrNodesOrEntries] - The `keysOrNodesOrEntries` parameter is an optional iterable of `KeyOrNodeOrEntry<K, V,
|
|
77
|
+
* @param [keysOrNodesOrEntries] - The `keysOrNodesOrEntries` parameter is an optional iterable of `KeyOrNodeOrEntry<K, V, NODE>`
|
|
53
78
|
* objects. It represents a collection of nodes that will be added to the AVL tree during
|
|
54
79
|
* initialization.
|
|
55
80
|
* @param [options] - The `options` parameter is an optional object that allows you to customize the
|
|
56
81
|
* behavior of the AVL tree. It is of type `Partial<AVLTreeOptions>`, which means that you can
|
|
57
82
|
* provide only a subset of the properties defined in the `AVLTreeOptions` interface.
|
|
58
83
|
*/
|
|
59
|
-
constructor(keysOrNodesOrEntries: Iterable<KeyOrNodeOrEntry<K, V,
|
|
84
|
+
constructor(keysOrNodesOrEntries: Iterable<KeyOrNodeOrEntry<K, V, NODE>> = [], options?: AVLTreeOptions<K>) {
|
|
60
85
|
super([], options);
|
|
61
86
|
if (keysOrNodesOrEntries) super.addMany(keysOrNodesOrEntries);
|
|
62
87
|
}
|
|
@@ -67,11 +92,11 @@ export class AVLTree<
|
|
|
67
92
|
* the new node. It is used to determine the position of the node in the binary search tree.
|
|
68
93
|
* @param [value] - The parameter `value` is an optional value that can be assigned to the node. It is of
|
|
69
94
|
* type `V`, which means it can be any value that is assignable to the `value` property of the
|
|
70
|
-
* node type `
|
|
95
|
+
* node type `NODE`.
|
|
71
96
|
* @returns a new AVLTreeNode object with the specified key and value.
|
|
72
97
|
*/
|
|
73
|
-
override createNode(key: K, value?: V):
|
|
74
|
-
return new AVLTreeNode<K, V,
|
|
98
|
+
override createNode(key: K, value?: V): NODE {
|
|
99
|
+
return new AVLTreeNode<K, V, NODE>(key, value) as NODE;
|
|
75
100
|
}
|
|
76
101
|
|
|
77
102
|
/**
|
|
@@ -82,7 +107,7 @@ export class AVLTree<
|
|
|
82
107
|
* @returns a new AVLTree object.
|
|
83
108
|
*/
|
|
84
109
|
override createTree(options?: AVLTreeOptions<K>): TREE {
|
|
85
|
-
return new AVLTree<K, V,
|
|
110
|
+
return new AVLTree<K, V, NODE, TREE>([], {
|
|
86
111
|
iterationType: this.iterationType,
|
|
87
112
|
variant: this.variant,
|
|
88
113
|
...options
|
|
@@ -91,10 +116,10 @@ export class AVLTree<
|
|
|
91
116
|
|
|
92
117
|
/**
|
|
93
118
|
* The function checks if an keyOrNodeOrEntry is an instance of AVLTreeNode.
|
|
94
|
-
* @param keyOrNodeOrEntry - The `keyOrNodeOrEntry` parameter is of type `KeyOrNodeOrEntry<K, V,
|
|
119
|
+
* @param keyOrNodeOrEntry - The `keyOrNodeOrEntry` parameter is of type `KeyOrNodeOrEntry<K, V, NODE>`.
|
|
95
120
|
* @returns a boolean value indicating whether the keyOrNodeOrEntry is an instance of the AVLTreeNode class.
|
|
96
121
|
*/
|
|
97
|
-
override isNode(keyOrNodeOrEntry: KeyOrNodeOrEntry<K, V,
|
|
122
|
+
override isNode(keyOrNodeOrEntry: KeyOrNodeOrEntry<K, V, NODE>): keyOrNodeOrEntry is NODE {
|
|
98
123
|
return keyOrNodeOrEntry instanceof AVLTreeNode;
|
|
99
124
|
}
|
|
100
125
|
|
|
@@ -116,7 +141,7 @@ export class AVLTree<
|
|
|
116
141
|
* being added to the binary tree.
|
|
117
142
|
* @returns The method is returning either the inserted node or undefined.
|
|
118
143
|
*/
|
|
119
|
-
override add(keyOrNodeOrEntry: KeyOrNodeOrEntry<K, V,
|
|
144
|
+
override add(keyOrNodeOrEntry: KeyOrNodeOrEntry<K, V, NODE>, value?: V): boolean {
|
|
120
145
|
if (keyOrNodeOrEntry === null) return false;
|
|
121
146
|
const inserted = super.add(keyOrNodeOrEntry, value);
|
|
122
147
|
if (inserted) this._balancePath(keyOrNodeOrEntry);
|
|
@@ -140,13 +165,13 @@ export class AVLTree<
|
|
|
140
165
|
* @param {C} callback - The `callback` parameter is a function that will be called for each node
|
|
141
166
|
* that is deleted from the binary tree. It is an optional parameter and if not provided, it will
|
|
142
167
|
* default to the `_defaultOneParamCallback` function. The `callback` function should have a single
|
|
143
|
-
* parameter of type `
|
|
144
|
-
* @returns The method is returning an array of `BinaryTreeDeleteResult<
|
|
168
|
+
* parameter of type `NODE
|
|
169
|
+
* @returns The method is returning an array of `BinaryTreeDeleteResult<NODE>`.
|
|
145
170
|
*/
|
|
146
|
-
override delete<C extends BTNCallback<
|
|
171
|
+
override delete<C extends BTNCallback<NODE>>(
|
|
147
172
|
identifier: ReturnType<C>,
|
|
148
173
|
callback: C = this._defaultOneParamCallback as C
|
|
149
|
-
): BinaryTreeDeleteResult<
|
|
174
|
+
): BinaryTreeDeleteResult<NODE>[] {
|
|
150
175
|
if ((identifier as any) instanceof AVLTreeNode) callback = (node => node) as C;
|
|
151
176
|
const deletedResults = super.delete(identifier, callback);
|
|
152
177
|
for (const { needBalanced } of deletedResults) {
|
|
@@ -160,14 +185,17 @@ export class AVLTree<
|
|
|
160
185
|
/**
|
|
161
186
|
* The `_swapProperties` function swaps the key, value, and height properties between two nodes in a binary
|
|
162
187
|
* tree.
|
|
163
|
-
* @param {K |
|
|
164
|
-
* needs to be swapped with the destination node. It can be of type `K`, `
|
|
165
|
-
* @param {K |
|
|
188
|
+
* @param {K | NODE | undefined} srcNode - The `srcNode` parameter represents the source node that
|
|
189
|
+
* needs to be swapped with the destination node. It can be of type `K`, `NODE`, or `undefined`.
|
|
190
|
+
* @param {K | NODE | undefined} destNode - The `destNode` parameter represents the destination
|
|
166
191
|
* node where the values from the source node will be swapped to.
|
|
167
192
|
* @returns either the `destNode` object if both `srcNode` and `destNode` are defined, or `undefined`
|
|
168
193
|
* if either `srcNode` or `destNode` is undefined.
|
|
169
194
|
*/
|
|
170
|
-
protected override _swapProperties(
|
|
195
|
+
protected override _swapProperties(
|
|
196
|
+
srcNode: BSTNKeyOrNode<K, NODE>,
|
|
197
|
+
destNode: BSTNKeyOrNode<K, NODE>
|
|
198
|
+
): NODE | undefined {
|
|
171
199
|
srcNode = this.ensureNode(srcNode);
|
|
172
200
|
destNode = this.ensureNode(destNode);
|
|
173
201
|
|
|
@@ -195,7 +223,6 @@ export class AVLTree<
|
|
|
195
223
|
/**
|
|
196
224
|
* Time Complexity: O(1)
|
|
197
225
|
* Space Complexity: O(1)
|
|
198
|
-
* constant time, as it performs a fixed number of operations. constant space, as it only uses a constant amount of memory.
|
|
199
226
|
*/
|
|
200
227
|
|
|
201
228
|
/**
|
|
@@ -203,11 +230,11 @@ export class AVLTree<
|
|
|
203
230
|
* Space Complexity: O(1)
|
|
204
231
|
*
|
|
205
232
|
* The function calculates the balance factor of a node in a binary tree.
|
|
206
|
-
* @param {
|
|
233
|
+
* @param {NODE} node - The parameter "node" represents a node in a binary tree data structure.
|
|
207
234
|
* @returns the balance factor of a given node. The balance factor is calculated by subtracting the
|
|
208
235
|
* height of the left subtree from the height of the right subtree.
|
|
209
236
|
*/
|
|
210
|
-
protected _balanceFactor(node:
|
|
237
|
+
protected _balanceFactor(node: NODE): number {
|
|
211
238
|
if (!node.right)
|
|
212
239
|
// node has no right subtree
|
|
213
240
|
return -node.height;
|
|
@@ -220,7 +247,6 @@ export class AVLTree<
|
|
|
220
247
|
/**
|
|
221
248
|
* Time Complexity: O(1)
|
|
222
249
|
* Space Complexity: O(1)
|
|
223
|
-
* constant time, as it performs a fixed number of operations. constant space, as it only uses a constant amount of memory.
|
|
224
250
|
*/
|
|
225
251
|
|
|
226
252
|
/**
|
|
@@ -229,9 +255,9 @@ export class AVLTree<
|
|
|
229
255
|
*
|
|
230
256
|
* The function updates the height of a node in a binary tree based on the heights of its left and
|
|
231
257
|
* right children.
|
|
232
|
-
* @param {
|
|
258
|
+
* @param {NODE} node - The parameter "node" represents a node in a binary tree data structure.
|
|
233
259
|
*/
|
|
234
|
-
protected _updateHeight(node:
|
|
260
|
+
protected _updateHeight(node: NODE): void {
|
|
235
261
|
if (!node.left && !node.right) node.height = 0;
|
|
236
262
|
else if (!node.left) {
|
|
237
263
|
const rightHeight = node.right ? node.right.height : 0;
|
|
@@ -240,65 +266,9 @@ export class AVLTree<
|
|
|
240
266
|
else node.height = 1 + Math.max(node.right.height, node.left.height);
|
|
241
267
|
}
|
|
242
268
|
|
|
243
|
-
/**
|
|
244
|
-
* Time Complexity: O(log n)
|
|
245
|
-
* Space Complexity: O(1)
|
|
246
|
-
* logarithmic time, where "n" is the number of nodes in the tree. The method traverses the path from the inserted node to the root. constant space, as it doesn't use additional data structures that scale with input size.
|
|
247
|
-
*/
|
|
248
|
-
|
|
249
|
-
/**
|
|
250
|
-
* Time Complexity: O(log n)
|
|
251
|
-
* Space Complexity: O(1)
|
|
252
|
-
*
|
|
253
|
-
* The `_balancePath` function is used to update the heights of nodes and perform rotation operations
|
|
254
|
-
* to restore balance in an AVL tree after inserting a node.
|
|
255
|
-
* @param {N} node - The `node` parameter in the `_balancePath` function represents the node in the
|
|
256
|
-
* AVL tree that needs to be balanced.
|
|
257
|
-
*/
|
|
258
|
-
protected _balancePath(node: KeyOrNodeOrEntry<K, V, N>): void {
|
|
259
|
-
node = this.ensureNode(node);
|
|
260
|
-
const path = this.getPathToRoot(node, false); // first O(log n) + O(log n)
|
|
261
|
-
for (let i = 0; i < path.length; i++) {
|
|
262
|
-
// second O(log n)
|
|
263
|
-
const A = path[i];
|
|
264
|
-
// Update Heights: After inserting a node, backtrack from the insertion point to the root node, updating the height of each node along the way.
|
|
265
|
-
this._updateHeight(A); // first O(1)
|
|
266
|
-
// Check Balance: Simultaneously with height updates, check if each node violates the balance property of an AVL tree.
|
|
267
|
-
// Balance Restoration: If a balance issue is discovered after inserting a node, it requires balance restoration operations. Balance restoration includes four basic cases where rotation operations need to be performed to fix the balance:
|
|
268
|
-
switch (
|
|
269
|
-
this._balanceFactor(A) // second O(1)
|
|
270
|
-
) {
|
|
271
|
-
case -2:
|
|
272
|
-
if (A && A.left) {
|
|
273
|
-
if (this._balanceFactor(A.left) <= 0) {
|
|
274
|
-
// second O(1)
|
|
275
|
-
// Left Rotation (LL Rotation): When the inserted node is in the left subtree of the left subtree, causing an imbalance.
|
|
276
|
-
this._balanceLL(A);
|
|
277
|
-
} else {
|
|
278
|
-
// Left-Right Rotation (LR Rotation): When the inserted node is in the right subtree of the left subtree, causing an imbalance.
|
|
279
|
-
this._balanceLR(A);
|
|
280
|
-
}
|
|
281
|
-
}
|
|
282
|
-
break;
|
|
283
|
-
case +2:
|
|
284
|
-
if (A && A.right) {
|
|
285
|
-
if (this._balanceFactor(A.right) >= 0) {
|
|
286
|
-
// Right Rotation (RR Rotation): When the inserted node is in the right subtree of the right subtree, causing an imbalance.
|
|
287
|
-
this._balanceRR(A);
|
|
288
|
-
} else {
|
|
289
|
-
// Right-Left Rotation (RL Rotation): When the inserted node is in the left subtree of the right subtree, causing an imbalance.
|
|
290
|
-
this._balanceRL(A);
|
|
291
|
-
}
|
|
292
|
-
}
|
|
293
|
-
}
|
|
294
|
-
// TODO So far, no sure if this is necessary that Recursive Repair: Once rotation operations are executed, it may cause imbalance issues at higher levels of the tree. Therefore, you need to recursively check and repair imbalance problems upwards until you reach the root node.
|
|
295
|
-
}
|
|
296
|
-
}
|
|
297
|
-
|
|
298
269
|
/**
|
|
299
270
|
* Time Complexity: O(1)
|
|
300
271
|
* Space Complexity: O(1)
|
|
301
|
-
* constant time, as these methods perform a fixed number of operations. constant space, as they only use a constant amount of memory.
|
|
302
272
|
*/
|
|
303
273
|
|
|
304
274
|
/**
|
|
@@ -306,9 +276,9 @@ export class AVLTree<
|
|
|
306
276
|
* Space Complexity: O(1)
|
|
307
277
|
*
|
|
308
278
|
* The function `_balanceLL` performs a left-left rotation to balance a binary tree.
|
|
309
|
-
* @param {
|
|
279
|
+
* @param {NODE} A - A is a node in a binary tree.
|
|
310
280
|
*/
|
|
311
|
-
protected _balanceLL(A:
|
|
281
|
+
protected _balanceLL(A: NODE): void {
|
|
312
282
|
const parentOfA = A.parent;
|
|
313
283
|
const B = A.left;
|
|
314
284
|
A.parent = B;
|
|
@@ -344,9 +314,9 @@ export class AVLTree<
|
|
|
344
314
|
* Space Complexity: O(1)
|
|
345
315
|
*
|
|
346
316
|
* The `_balanceLR` function performs a left-right rotation to balance a binary tree.
|
|
347
|
-
* @param {
|
|
317
|
+
* @param {NODE} A - A is a node in a binary tree.
|
|
348
318
|
*/
|
|
349
|
-
protected _balanceLR(A:
|
|
319
|
+
protected _balanceLR(A: NODE): void {
|
|
350
320
|
const parentOfA = A.parent;
|
|
351
321
|
const B = A.left;
|
|
352
322
|
let C = undefined;
|
|
@@ -400,9 +370,9 @@ export class AVLTree<
|
|
|
400
370
|
* Space Complexity: O(1)
|
|
401
371
|
*
|
|
402
372
|
* The function `_balanceRR` performs a right-right rotation to balance a binary tree.
|
|
403
|
-
* @param {
|
|
373
|
+
* @param {NODE} A - A is a node in a binary tree.
|
|
404
374
|
*/
|
|
405
|
-
protected _balanceRR(A:
|
|
375
|
+
protected _balanceRR(A: NODE): void {
|
|
406
376
|
const parentOfA = A.parent;
|
|
407
377
|
const B = A.right;
|
|
408
378
|
A.parent = B;
|
|
@@ -443,9 +413,9 @@ export class AVLTree<
|
|
|
443
413
|
* Space Complexity: O(1)
|
|
444
414
|
*
|
|
445
415
|
* The function `_balanceRL` performs a right-left rotation to balance a binary tree.
|
|
446
|
-
* @param {
|
|
416
|
+
* @param {NODE} A - A is a node in a binary tree.
|
|
447
417
|
*/
|
|
448
|
-
protected _balanceRL(A:
|
|
418
|
+
protected _balanceRL(A: NODE): void {
|
|
449
419
|
const parentOfA = A.parent;
|
|
450
420
|
const B = A.right;
|
|
451
421
|
let C = undefined;
|
|
@@ -488,7 +458,71 @@ export class AVLTree<
|
|
|
488
458
|
C && this._updateHeight(C);
|
|
489
459
|
}
|
|
490
460
|
|
|
491
|
-
|
|
461
|
+
/**
|
|
462
|
+
* Time Complexity: O(log n)
|
|
463
|
+
* Space Complexity: O(1)
|
|
464
|
+
* logarithmic time, where "n" is the number of nodes in the tree. The method traverses the path from the inserted node to the root. constant space, as it doesn't use additional data structures that scale with input size.
|
|
465
|
+
*/
|
|
466
|
+
|
|
467
|
+
/**
|
|
468
|
+
* Time Complexity: O(log n)
|
|
469
|
+
* Space Complexity: O(1)
|
|
470
|
+
*
|
|
471
|
+
* The `_balancePath` function is used to update the heights of nodes and perform rotation operations
|
|
472
|
+
* to restore balance in an AVL tree after inserting a node.
|
|
473
|
+
* @param {NODE} node - The `node` parameter in the `_balancePath` function represents the node in the
|
|
474
|
+
* AVL tree that needs to be balanced.
|
|
475
|
+
*/
|
|
476
|
+
protected _balancePath(node: KeyOrNodeOrEntry<K, V, NODE>): void {
|
|
477
|
+
node = this.ensureNode(node);
|
|
478
|
+
const path = this.getPathToRoot(node, false); // first O(log n) + O(log n)
|
|
479
|
+
for (let i = 0; i < path.length; i++) {
|
|
480
|
+
// second O(log n)
|
|
481
|
+
const A = path[i];
|
|
482
|
+
// Update Heights: After inserting a node, backtrack from the insertion point to the root node, updating the height of each node along the way.
|
|
483
|
+
this._updateHeight(A); // first O(1)
|
|
484
|
+
// Check Balance: Simultaneously with height updates, check if each node violates the balance property of an AVL tree.
|
|
485
|
+
// Balance Restoration: If a balance issue is discovered after inserting a node, it requires balance restoration operations. Balance restoration includes four basic cases where rotation operations need to be performed to fix the balance:
|
|
486
|
+
switch (
|
|
487
|
+
this._balanceFactor(A) // second O(1)
|
|
488
|
+
) {
|
|
489
|
+
case -2:
|
|
490
|
+
if (A && A.left) {
|
|
491
|
+
if (this._balanceFactor(A.left) <= 0) {
|
|
492
|
+
// second O(1)
|
|
493
|
+
// Left Rotation (LL Rotation): When the inserted node is in the left subtree of the left subtree, causing an imbalance.
|
|
494
|
+
this._balanceLL(A);
|
|
495
|
+
} else {
|
|
496
|
+
// Left-Right Rotation (LR Rotation): When the inserted node is in the right subtree of the left subtree, causing an imbalance.
|
|
497
|
+
this._balanceLR(A);
|
|
498
|
+
}
|
|
499
|
+
}
|
|
500
|
+
break;
|
|
501
|
+
case +2:
|
|
502
|
+
if (A && A.right) {
|
|
503
|
+
if (this._balanceFactor(A.right) >= 0) {
|
|
504
|
+
// Right Rotation (RR Rotation): When the inserted node is in the right subtree of the right subtree, causing an imbalance.
|
|
505
|
+
this._balanceRR(A);
|
|
506
|
+
} else {
|
|
507
|
+
// Right-Left Rotation (RL Rotation): When the inserted node is in the left subtree of the right subtree, causing an imbalance.
|
|
508
|
+
this._balanceRL(A);
|
|
509
|
+
}
|
|
510
|
+
}
|
|
511
|
+
}
|
|
512
|
+
// TODO So far, no sure if this is necessary that Recursive Repair: Once rotation operations are executed, it may cause imbalance issues at higher levels of the tree. Therefore, you need to recursively check and repair imbalance problems upwards until you reach the root node.
|
|
513
|
+
}
|
|
514
|
+
}
|
|
515
|
+
|
|
516
|
+
/**
|
|
517
|
+
* The function replaces an old node with a new node while preserving the height of the old node.
|
|
518
|
+
* @param {NODE} oldNode - The `oldNode` parameter is the node that you want to replace with the
|
|
519
|
+
* `newNode`.
|
|
520
|
+
* @param {NODE} newNode - The `newNode` parameter is the new node that will replace the `oldNode` in
|
|
521
|
+
* the data structure.
|
|
522
|
+
* @returns the result of calling the `_replaceNode` method on the superclass, passing in the
|
|
523
|
+
* `oldNode` and `newNode` as arguments.
|
|
524
|
+
*/
|
|
525
|
+
protected _replaceNode(oldNode: NODE, newNode: NODE): NODE {
|
|
492
526
|
newNode.height = oldNode.height;
|
|
493
527
|
|
|
494
528
|
return super._replaceNode(oldNode, newNode);
|