avl-tree-typed 2.0.5 → 2.1.0
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.js +1 -1
- package/dist/constants/index.js +1 -1
- package/dist/data-structures/base/iterable-element-base.d.ts +186 -83
- package/dist/data-structures/base/iterable-element-base.js +149 -107
- package/dist/data-structures/base/iterable-entry-base.d.ts +95 -119
- package/dist/data-structures/base/iterable-entry-base.js +59 -116
- package/dist/data-structures/base/linear-base.d.ts +250 -192
- package/dist/data-structures/base/linear-base.js +137 -274
- package/dist/data-structures/binary-tree/avl-tree-counter.d.ts +126 -158
- package/dist/data-structures/binary-tree/avl-tree-counter.js +171 -205
- package/dist/data-structures/binary-tree/avl-tree-multi-map.d.ts +100 -69
- package/dist/data-structures/binary-tree/avl-tree-multi-map.js +135 -87
- package/dist/data-structures/binary-tree/avl-tree.d.ts +138 -149
- package/dist/data-structures/binary-tree/avl-tree.js +208 -195
- package/dist/data-structures/binary-tree/binary-tree.d.ts +476 -632
- package/dist/data-structures/binary-tree/binary-tree.js +598 -869
- package/dist/data-structures/binary-tree/bst.d.ts +258 -306
- package/dist/data-structures/binary-tree/bst.js +505 -481
- package/dist/data-structures/binary-tree/red-black-tree.d.ts +107 -179
- package/dist/data-structures/binary-tree/red-black-tree.js +114 -209
- package/dist/data-structures/binary-tree/tree-counter.d.ts +132 -154
- package/dist/data-structures/binary-tree/tree-counter.js +172 -203
- package/dist/data-structures/binary-tree/tree-multi-map.d.ts +72 -69
- package/dist/data-structures/binary-tree/tree-multi-map.js +105 -85
- package/dist/data-structures/graph/abstract-graph.d.ts +238 -233
- package/dist/data-structures/graph/abstract-graph.js +267 -237
- package/dist/data-structures/graph/directed-graph.d.ts +108 -224
- package/dist/data-structures/graph/directed-graph.js +146 -233
- package/dist/data-structures/graph/map-graph.d.ts +49 -55
- package/dist/data-structures/graph/map-graph.js +56 -59
- package/dist/data-structures/graph/undirected-graph.d.ts +103 -146
- package/dist/data-structures/graph/undirected-graph.js +129 -149
- package/dist/data-structures/hash/hash-map.d.ts +164 -338
- package/dist/data-structures/hash/hash-map.js +270 -457
- package/dist/data-structures/heap/heap.d.ts +214 -289
- package/dist/data-structures/heap/heap.js +340 -349
- package/dist/data-structures/heap/max-heap.d.ts +11 -47
- package/dist/data-structures/heap/max-heap.js +11 -66
- package/dist/data-structures/heap/min-heap.d.ts +12 -47
- package/dist/data-structures/heap/min-heap.js +11 -66
- package/dist/data-structures/linked-list/doubly-linked-list.d.ts +231 -347
- package/dist/data-structures/linked-list/doubly-linked-list.js +368 -494
- package/dist/data-structures/linked-list/singly-linked-list.d.ts +261 -310
- package/dist/data-structures/linked-list/singly-linked-list.js +447 -466
- package/dist/data-structures/linked-list/skip-linked-list.d.ts +0 -107
- package/dist/data-structures/linked-list/skip-linked-list.js +0 -100
- package/dist/data-structures/priority-queue/max-priority-queue.d.ts +12 -56
- package/dist/data-structures/priority-queue/max-priority-queue.js +11 -78
- package/dist/data-structures/priority-queue/min-priority-queue.d.ts +11 -57
- package/dist/data-structures/priority-queue/min-priority-queue.js +10 -79
- package/dist/data-structures/priority-queue/priority-queue.d.ts +2 -61
- package/dist/data-structures/priority-queue/priority-queue.js +8 -83
- package/dist/data-structures/queue/deque.d.ts +227 -254
- package/dist/data-structures/queue/deque.js +309 -348
- package/dist/data-structures/queue/queue.d.ts +180 -201
- package/dist/data-structures/queue/queue.js +265 -248
- package/dist/data-structures/stack/stack.d.ts +124 -102
- package/dist/data-structures/stack/stack.js +181 -125
- package/dist/data-structures/trie/trie.d.ts +164 -165
- package/dist/data-structures/trie/trie.js +189 -172
- package/dist/interfaces/binary-tree.d.ts +56 -6
- package/dist/interfaces/graph.d.ts +16 -0
- package/dist/types/data-structures/base/base.d.ts +1 -1
- package/dist/types/data-structures/graph/abstract-graph.d.ts +4 -0
- package/dist/types/utils/utils.d.ts +1 -0
- package/dist/utils/number.js +1 -2
- package/dist/utils/utils.d.ts +1 -1
- package/dist/utils/utils.js +9 -8
- package/package.json +15 -15
- package/src/data-structures/base/iterable-element-base.ts +238 -115
- package/src/data-structures/base/iterable-entry-base.ts +96 -120
- package/src/data-structures/base/linear-base.ts +271 -277
- package/src/data-structures/binary-tree/avl-tree-counter.ts +198 -216
- package/src/data-structures/binary-tree/avl-tree-multi-map.ts +192 -101
- package/src/data-structures/binary-tree/avl-tree.ts +239 -206
- package/src/data-structures/binary-tree/binary-tree.ts +664 -893
- package/src/data-structures/binary-tree/bst.ts +568 -570
- package/src/data-structures/binary-tree/red-black-tree.ts +161 -222
- package/src/data-structures/binary-tree/tree-counter.ts +199 -218
- package/src/data-structures/binary-tree/tree-multi-map.ts +131 -97
- package/src/data-structures/graph/abstract-graph.ts +339 -264
- package/src/data-structures/graph/directed-graph.ts +146 -236
- package/src/data-structures/graph/map-graph.ts +63 -60
- package/src/data-structures/graph/undirected-graph.ts +129 -152
- package/src/data-structures/hash/hash-map.ts +274 -496
- package/src/data-structures/heap/heap.ts +389 -402
- package/src/data-structures/heap/max-heap.ts +12 -76
- package/src/data-structures/heap/min-heap.ts +13 -76
- package/src/data-structures/linked-list/doubly-linked-list.ts +426 -530
- package/src/data-structures/linked-list/singly-linked-list.ts +495 -517
- package/src/data-structures/linked-list/skip-linked-list.ts +1 -108
- package/src/data-structures/priority-queue/max-priority-queue.ts +12 -87
- package/src/data-structures/priority-queue/min-priority-queue.ts +11 -88
- package/src/data-structures/priority-queue/priority-queue.ts +3 -92
- package/src/data-structures/queue/deque.ts +381 -357
- package/src/data-structures/queue/queue.ts +310 -264
- package/src/data-structures/stack/stack.ts +217 -131
- package/src/data-structures/trie/trie.ts +240 -175
- package/src/interfaces/binary-tree.ts +240 -6
- package/src/interfaces/graph.ts +37 -0
- package/src/types/data-structures/base/base.ts +5 -5
- package/src/types/data-structures/graph/abstract-graph.ts +5 -0
- package/src/types/utils/utils.ts +2 -0
- package/src/utils/utils.ts +9 -14
|
@@ -1,7 +1,8 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* data-structure-typed
|
|
3
|
-
*
|
|
4
|
-
* @
|
|
3
|
+
*
|
|
4
|
+
* @author Pablo Zeng
|
|
5
|
+
* @copyright Copyright (c) 2022 Pablo Zeng <zrwusa@gmail.com>
|
|
5
6
|
* @license MIT License
|
|
6
7
|
*/
|
|
7
8
|
|
|
@@ -9,6 +10,10 @@ import type { Comparator, DFSOrderPattern, ElementCallback, HeapOptions } from '
|
|
|
9
10
|
import { IterableElementBase } from '../base';
|
|
10
11
|
|
|
11
12
|
/**
|
|
13
|
+
* Binary heap with pluggable comparator; supports fast insertion and removal of the top element.
|
|
14
|
+
* @remarks Time O(1), Space O(1)
|
|
15
|
+
* @template E
|
|
16
|
+
* @template R
|
|
12
17
|
* 1. Complete Binary Tree: Heaps are typically complete binary trees, meaning every level is fully filled except possibly for the last level, which has nodes as far left as possible.
|
|
13
18
|
* 2. Heap Properties: Each node in a heap follows a specific order property, which varies depending on the type of heap:
|
|
14
19
|
* Max Heap: The value of each parent node is greater than or equal to the value of its children.
|
|
@@ -185,21 +190,18 @@ import { IterableElementBase } from '../base';
|
|
|
185
190
|
* ]);
|
|
186
191
|
* console.log(scheduleTasks(tasks, 2)); // expectedMap
|
|
187
192
|
*/
|
|
188
|
-
export class Heap<E =
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
*
|
|
193
|
-
*
|
|
194
|
-
*
|
|
195
|
-
* @param [options] -
|
|
196
|
-
*
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
* order of elements in the heap.
|
|
201
|
-
*/
|
|
202
|
-
constructor(elements: Iterable<E> | Iterable<R> = [], options?: HeapOptions<E, R>) {
|
|
193
|
+
export class Heap<E = unknown, R = never> extends IterableElementBase<E, R> {
|
|
194
|
+
protected _equals: (a: E, b: E) => boolean = Object.is;
|
|
195
|
+
|
|
196
|
+
/**
|
|
197
|
+
* Create a Heap and optionally bulk-insert elements.
|
|
198
|
+
* @remarks Time O(N), Space O(N)
|
|
199
|
+
* @param [elements] - Iterable of elements (or raw values if toElementFn is set).
|
|
200
|
+
* @param [options] - Options such as comparator and toElementFn.
|
|
201
|
+
* @returns New Heap instance.
|
|
202
|
+
*/
|
|
203
|
+
|
|
204
|
+
constructor(elements: Iterable<E | R> = [], options?: HeapOptions<E, R>) {
|
|
203
205
|
super(options);
|
|
204
206
|
|
|
205
207
|
if (options) {
|
|
@@ -207,91 +209,113 @@ export class Heap<E = any, R = any> extends IterableElementBase<E, R> {
|
|
|
207
209
|
if (comparator) this._comparator = comparator;
|
|
208
210
|
}
|
|
209
211
|
|
|
210
|
-
this.addMany(elements);
|
|
212
|
+
this.addMany(elements as Iterable<E | R>);
|
|
211
213
|
}
|
|
212
214
|
|
|
213
215
|
protected _elements: E[] = [];
|
|
214
216
|
|
|
215
217
|
/**
|
|
216
|
-
*
|
|
217
|
-
* @
|
|
218
|
+
* Get the backing array of the heap.
|
|
219
|
+
* @remarks Time O(1), Space O(1)
|
|
220
|
+
* @returns Internal elements array.
|
|
218
221
|
*/
|
|
222
|
+
|
|
219
223
|
get elements(): E[] {
|
|
220
224
|
return this._elements;
|
|
221
225
|
}
|
|
222
226
|
|
|
223
227
|
/**
|
|
224
|
-
* Get the
|
|
228
|
+
* Get the number of elements.
|
|
229
|
+
* @remarks Time O(1), Space O(1)
|
|
230
|
+
* @returns Heap size.
|
|
225
231
|
*/
|
|
232
|
+
|
|
226
233
|
get size(): number {
|
|
227
234
|
return this.elements.length;
|
|
228
235
|
}
|
|
229
236
|
|
|
230
237
|
/**
|
|
231
|
-
* Get the last
|
|
232
|
-
* @
|
|
238
|
+
* Get the last leaf element.
|
|
239
|
+
* @remarks Time O(1), Space O(1)
|
|
240
|
+
* @returns Last element or undefined.
|
|
233
241
|
*/
|
|
242
|
+
|
|
234
243
|
get leaf(): E | undefined {
|
|
235
244
|
return this.elements[this.size - 1] ?? undefined;
|
|
236
245
|
}
|
|
237
246
|
|
|
238
247
|
/**
|
|
239
|
-
*
|
|
240
|
-
* @
|
|
241
|
-
* @
|
|
242
|
-
* @
|
|
248
|
+
* Create a heap of the same class from an iterable.
|
|
249
|
+
* @remarks Time O(N), Space O(N)
|
|
250
|
+
* @template T
|
|
251
|
+
* @template R
|
|
252
|
+
* @template S
|
|
253
|
+
* @param [elements] - Iterable of elements or raw records.
|
|
254
|
+
* @param [options] - Heap options including comparator.
|
|
255
|
+
* @returns A new heap instance of this class.
|
|
256
|
+
*/
|
|
257
|
+
|
|
258
|
+
static from<T, R = never, S extends Heap<T, R> = Heap<T, R>>(
|
|
259
|
+
this: new (elements?: Iterable<T | R>, options?: HeapOptions<T, R>) => S,
|
|
260
|
+
elements?: Iterable<T | R>,
|
|
261
|
+
options?: HeapOptions<T, R>
|
|
262
|
+
): S {
|
|
263
|
+
return new this(elements, options);
|
|
264
|
+
}
|
|
265
|
+
|
|
266
|
+
/**
|
|
267
|
+
* Build a Heap from an iterable in linear time given a comparator.
|
|
268
|
+
* @remarks Time O(N), Space O(N)
|
|
269
|
+
* @template EE
|
|
270
|
+
* @template RR
|
|
271
|
+
* @param elements - Iterable of elements.
|
|
272
|
+
* @param options - Heap options including comparator.
|
|
273
|
+
* @returns A new Heap built from elements.
|
|
243
274
|
*/
|
|
244
|
-
|
|
245
|
-
|
|
275
|
+
|
|
276
|
+
static heapify<EE = unknown, RR = never>(elements: Iterable<EE>, options: HeapOptions<EE, RR>): Heap<EE, RR> {
|
|
277
|
+
return new Heap<EE, RR>(elements, options);
|
|
246
278
|
}
|
|
247
279
|
|
|
248
280
|
/**
|
|
249
|
-
*
|
|
250
|
-
*
|
|
251
|
-
*
|
|
252
|
-
*
|
|
253
|
-
* @param {E} element - The `element` parameter represents the element that you want to add to the
|
|
254
|
-
* data structure.
|
|
255
|
-
* @returns The `add` method is returning a boolean value, which is the result of calling the
|
|
256
|
-
* `_bubbleUp` method with the index `this.elements.length - 1` as an argument.
|
|
281
|
+
* Insert an element.
|
|
282
|
+
* @remarks Time O(1) amortized, Space O(1)
|
|
283
|
+
* @param element - Element to insert.
|
|
284
|
+
* @returns True.
|
|
257
285
|
*/
|
|
286
|
+
|
|
258
287
|
add(element: E): boolean {
|
|
259
|
-
this._elements.push(element
|
|
288
|
+
this._elements.push(element);
|
|
260
289
|
return this._bubbleUp(this.elements.length - 1);
|
|
261
290
|
}
|
|
262
291
|
|
|
263
292
|
/**
|
|
264
|
-
*
|
|
265
|
-
*
|
|
266
|
-
*
|
|
267
|
-
*
|
|
268
|
-
* boolean values indicating success or failure.
|
|
269
|
-
* @param {Iterable<E> | Iterable<R>} elements - The `elements` parameter in the `addMany` method is
|
|
270
|
-
* an iterable containing elements of type `E` or `R`. The method iterates over each element in the
|
|
271
|
-
* iterable and adds them to the data structure. If a transformation function `_toElementFn` is
|
|
272
|
-
* provided, it transforms the element
|
|
273
|
-
* @returns The `addMany` method returns an array of boolean values indicating whether each element
|
|
274
|
-
* in the input iterable was successfully added to the data structure.
|
|
293
|
+
* Insert many elements from an iterable.
|
|
294
|
+
* @remarks Time O(N log N), Space O(1)
|
|
295
|
+
* @param elements - Iterable of elements or raw values.
|
|
296
|
+
* @returns Array of per-element success flags.
|
|
275
297
|
*/
|
|
276
|
-
|
|
277
|
-
|
|
298
|
+
|
|
299
|
+
addMany(elements: Iterable<E | R>): boolean[] {
|
|
300
|
+
const flags: boolean[] = [];
|
|
278
301
|
for (const el of elements) {
|
|
279
|
-
if (this.
|
|
280
|
-
|
|
281
|
-
|
|
302
|
+
if (this.toElementFn) {
|
|
303
|
+
const ok = this.add(this.toElementFn(el as R));
|
|
304
|
+
flags.push(ok);
|
|
305
|
+
} else {
|
|
306
|
+
const ok = this.add(el as E);
|
|
307
|
+
flags.push(ok);
|
|
282
308
|
}
|
|
283
|
-
ans.push(this.add(el as E));
|
|
284
309
|
}
|
|
285
|
-
return
|
|
310
|
+
return flags;
|
|
286
311
|
}
|
|
287
312
|
|
|
288
313
|
/**
|
|
289
|
-
*
|
|
290
|
-
*
|
|
291
|
-
*
|
|
292
|
-
* Remove and return the top element (the smallest or largest element) from the heap.
|
|
293
|
-
* @returns The top element or undefined if the heap is empty.
|
|
314
|
+
* Remove and return the top element.
|
|
315
|
+
* @remarks Time O(log N), Space O(1)
|
|
316
|
+
* @returns Top element or undefined.
|
|
294
317
|
*/
|
|
318
|
+
|
|
295
319
|
poll(): E | undefined {
|
|
296
320
|
if (this.elements.length === 0) return;
|
|
297
321
|
const value = this.elements[0];
|
|
@@ -304,68 +328,74 @@ export class Heap<E = any, R = any> extends IterableElementBase<E, R> {
|
|
|
304
328
|
}
|
|
305
329
|
|
|
306
330
|
/**
|
|
307
|
-
*
|
|
308
|
-
*
|
|
309
|
-
*
|
|
310
|
-
* Peek at the top element of the heap without removing it.
|
|
311
|
-
* @returns The top element or undefined if the heap is empty.
|
|
331
|
+
* Get the current top element without removing it.
|
|
332
|
+
* @remarks Time O(1), Space O(1)
|
|
333
|
+
* @returns Top element or undefined.
|
|
312
334
|
*/
|
|
335
|
+
|
|
313
336
|
peek(): E | undefined {
|
|
314
337
|
return this.elements[0];
|
|
315
338
|
}
|
|
316
339
|
|
|
317
340
|
/**
|
|
318
|
-
* Check
|
|
319
|
-
* @
|
|
341
|
+
* Check whether the heap is empty.
|
|
342
|
+
* @remarks Time O(1), Space O(1)
|
|
343
|
+
* @returns True if size is 0.
|
|
320
344
|
*/
|
|
345
|
+
|
|
321
346
|
isEmpty(): boolean {
|
|
322
347
|
return this.size === 0;
|
|
323
348
|
}
|
|
324
349
|
|
|
325
350
|
/**
|
|
326
|
-
*
|
|
351
|
+
* Remove all elements.
|
|
352
|
+
* @remarks Time O(1), Space O(1)
|
|
353
|
+
* @returns void
|
|
327
354
|
*/
|
|
355
|
+
|
|
328
356
|
clear(): void {
|
|
329
357
|
this._elements = [];
|
|
330
358
|
}
|
|
331
359
|
|
|
332
360
|
/**
|
|
333
|
-
*
|
|
334
|
-
*
|
|
335
|
-
*
|
|
336
|
-
*
|
|
337
|
-
* @param elements
|
|
361
|
+
* Replace the backing array and rebuild the heap.
|
|
362
|
+
* @remarks Time O(N), Space O(N)
|
|
363
|
+
* @param elements - Iterable used to refill the heap.
|
|
364
|
+
* @returns Array of per-node results from fixing steps.
|
|
338
365
|
*/
|
|
339
|
-
|
|
340
|
-
|
|
366
|
+
|
|
367
|
+
refill(elements: Iterable<E>): boolean[] {
|
|
368
|
+
this._elements = Array.from(elements);
|
|
341
369
|
return this.fix();
|
|
342
370
|
}
|
|
343
371
|
|
|
344
372
|
/**
|
|
345
|
-
*
|
|
346
|
-
*
|
|
347
|
-
*
|
|
348
|
-
*
|
|
349
|
-
* @param element - the element to check.
|
|
350
|
-
* @returns Returns true if the specified element is contained; otherwise, returns false.
|
|
373
|
+
* Check if an equal element exists in the heap.
|
|
374
|
+
* @remarks Time O(N), Space O(1)
|
|
375
|
+
* @param element - Element to search for.
|
|
376
|
+
* @returns True if found.
|
|
351
377
|
*/
|
|
378
|
+
|
|
352
379
|
override has(element: E): boolean {
|
|
353
|
-
|
|
380
|
+
for (const el of this.elements) if (this._equals(el, element)) return true;
|
|
381
|
+
return false;
|
|
354
382
|
}
|
|
355
383
|
|
|
356
384
|
/**
|
|
357
|
-
*
|
|
358
|
-
*
|
|
359
|
-
*
|
|
360
|
-
*
|
|
361
|
-
* and structure of the remaining elements.
|
|
362
|
-
* @param {E} element - The `element` parameter represents the element that you want to delete from
|
|
363
|
-
* the array `this.elements`.
|
|
364
|
-
* @returns The `delete` function is returning a boolean value. It returns `true` if the element was
|
|
365
|
-
* successfully deleted from the array, and `false` if the element was not found in the array.
|
|
385
|
+
* Delete one occurrence of an element.
|
|
386
|
+
* @remarks Time O(N), Space O(1)
|
|
387
|
+
* @param element - Element to delete.
|
|
388
|
+
* @returns True if an element was removed.
|
|
366
389
|
*/
|
|
390
|
+
|
|
367
391
|
delete(element: E): boolean {
|
|
368
|
-
|
|
392
|
+
let index = -1;
|
|
393
|
+
for (let i = 0; i < this.elements.length; i++) {
|
|
394
|
+
if (this._equals(this.elements[i], element)) {
|
|
395
|
+
index = i;
|
|
396
|
+
break;
|
|
397
|
+
}
|
|
398
|
+
}
|
|
369
399
|
if (index < 0) return false;
|
|
370
400
|
if (index === 0) {
|
|
371
401
|
this.poll();
|
|
@@ -380,17 +410,54 @@ export class Heap<E = any, R = any> extends IterableElementBase<E, R> {
|
|
|
380
410
|
}
|
|
381
411
|
|
|
382
412
|
/**
|
|
383
|
-
*
|
|
384
|
-
*
|
|
385
|
-
*
|
|
386
|
-
*
|
|
387
|
-
|
|
388
|
-
|
|
413
|
+
* Delete the first element that matches a predicate.
|
|
414
|
+
* @remarks Time O(N), Space O(1)
|
|
415
|
+
* @param predicate - Function (element, index, heap) → boolean.
|
|
416
|
+
* @returns True if an element was removed.
|
|
417
|
+
*/
|
|
418
|
+
|
|
419
|
+
deleteBy(predicate: (element: E, index: number, heap: this) => boolean): boolean {
|
|
420
|
+
let idx = -1;
|
|
421
|
+
for (let i = 0; i < this.elements.length; i++) {
|
|
422
|
+
if (predicate(this.elements[i], i, this)) {
|
|
423
|
+
idx = i;
|
|
424
|
+
break;
|
|
425
|
+
}
|
|
426
|
+
}
|
|
427
|
+
if (idx < 0) return false;
|
|
428
|
+
if (idx === 0) {
|
|
429
|
+
this.poll();
|
|
430
|
+
} else if (idx === this.elements.length - 1) {
|
|
431
|
+
this.elements.pop();
|
|
432
|
+
} else {
|
|
433
|
+
this.elements.splice(idx, 1, this.elements.pop()!);
|
|
434
|
+
this._bubbleUp(idx);
|
|
435
|
+
this._sinkDown(idx, this.elements.length >> 1);
|
|
436
|
+
}
|
|
437
|
+
return true;
|
|
438
|
+
}
|
|
439
|
+
|
|
440
|
+
/**
|
|
441
|
+
* Set the equality comparator used by has/delete operations.
|
|
442
|
+
* @remarks Time O(1), Space O(1)
|
|
443
|
+
* @param equals - Equality predicate (a, b) → boolean.
|
|
444
|
+
* @returns This heap.
|
|
445
|
+
*/
|
|
446
|
+
|
|
447
|
+
setEquality(equals: (a: E, b: E) => boolean): this {
|
|
448
|
+
this._equals = equals;
|
|
449
|
+
return this;
|
|
450
|
+
}
|
|
451
|
+
|
|
452
|
+
/**
|
|
453
|
+
* Traverse the binary heap as a complete binary tree and collect elements.
|
|
454
|
+
* @remarks Time O(N), Space O(H)
|
|
455
|
+
* @param [order] - Traversal order: 'PRE' | 'IN' | 'POST'.
|
|
456
|
+
* @returns Array of visited elements.
|
|
389
457
|
*/
|
|
458
|
+
|
|
390
459
|
dfs(order: DFSOrderPattern = 'PRE'): E[] {
|
|
391
460
|
const result: E[] = [];
|
|
392
|
-
|
|
393
|
-
// Auxiliary recursive function, traverses the binary heap according to the traversal order
|
|
394
461
|
const _dfs = (index: number) => {
|
|
395
462
|
const left = 2 * index + 1,
|
|
396
463
|
right = left + 1;
|
|
@@ -410,153 +477,147 @@ export class Heap<E = any, R = any> extends IterableElementBase<E, R> {
|
|
|
410
477
|
}
|
|
411
478
|
}
|
|
412
479
|
};
|
|
413
|
-
|
|
414
|
-
_dfs(0); // Traverse starting from the root node
|
|
415
|
-
|
|
480
|
+
_dfs(0);
|
|
416
481
|
return result;
|
|
417
482
|
}
|
|
418
483
|
|
|
419
484
|
/**
|
|
420
|
-
*
|
|
421
|
-
*
|
|
422
|
-
*
|
|
423
|
-
* Clone the heap, creating a new heap with the same elements.
|
|
424
|
-
* @returns A new Heap instance containing the same elements.
|
|
485
|
+
* Restore heap order bottom-up (heapify in-place).
|
|
486
|
+
* @remarks Time O(N), Space O(1)
|
|
487
|
+
* @returns Array of per-node results from fixing steps.
|
|
425
488
|
*/
|
|
426
|
-
|
|
427
|
-
|
|
489
|
+
|
|
490
|
+
fix(): boolean[] {
|
|
491
|
+
const results: boolean[] = [];
|
|
492
|
+
for (let i = Math.floor(this.size / 2) - 1; i >= 0; i--) {
|
|
493
|
+
results.push(this._sinkDown(i, this.elements.length >> 1));
|
|
494
|
+
}
|
|
495
|
+
return results;
|
|
428
496
|
}
|
|
429
497
|
|
|
430
498
|
/**
|
|
431
|
-
*
|
|
432
|
-
*
|
|
433
|
-
*
|
|
434
|
-
* Sort the elements in the heap and return them as an array.
|
|
435
|
-
* @returns An array containing the elements sorted in ascending order.
|
|
499
|
+
* Return all elements in ascending order by repeatedly polling.
|
|
500
|
+
* @remarks Time O(N log N), Space O(N)
|
|
501
|
+
* @returns Sorted array of elements.
|
|
436
502
|
*/
|
|
503
|
+
|
|
437
504
|
sort(): E[] {
|
|
438
|
-
const
|
|
439
|
-
const cloned =
|
|
440
|
-
|
|
505
|
+
const visited: E[] = [];
|
|
506
|
+
const cloned = this._createInstance();
|
|
507
|
+
for (const x of this.elements) cloned.add(x);
|
|
508
|
+
while (!cloned.isEmpty()) {
|
|
441
509
|
const top = cloned.poll();
|
|
442
|
-
if (top !== undefined)
|
|
510
|
+
if (top !== undefined) visited.push(top);
|
|
443
511
|
}
|
|
444
|
-
return
|
|
512
|
+
return visited;
|
|
445
513
|
}
|
|
446
514
|
|
|
447
515
|
/**
|
|
448
|
-
*
|
|
449
|
-
*
|
|
450
|
-
*
|
|
451
|
-
* Fix the entire heap to maintain heap properties.
|
|
516
|
+
* Deep clone this heap.
|
|
517
|
+
* @remarks Time O(N), Space O(N)
|
|
518
|
+
* @returns A new heap with the same elements.
|
|
452
519
|
*/
|
|
453
|
-
|
|
454
|
-
|
|
455
|
-
|
|
456
|
-
|
|
520
|
+
|
|
521
|
+
clone(): this {
|
|
522
|
+
const next = this._createInstance();
|
|
523
|
+
for (const x of this.elements) next.add(x);
|
|
524
|
+
return next;
|
|
457
525
|
}
|
|
458
526
|
|
|
459
527
|
/**
|
|
460
|
-
*
|
|
461
|
-
*
|
|
462
|
-
*
|
|
463
|
-
*
|
|
464
|
-
*
|
|
465
|
-
|
|
466
|
-
|
|
467
|
-
|
|
468
|
-
|
|
469
|
-
|
|
470
|
-
|
|
471
|
-
|
|
472
|
-
|
|
473
|
-
|
|
474
|
-
|
|
475
|
-
filter(callback: ElementCallback<E, R, boolean>, thisArg?: any): Heap<E, R> {
|
|
476
|
-
const filteredList = new Heap<E, R>([], { toElementFn: this.toElementFn, comparator: this.comparator });
|
|
477
|
-
let index = 0;
|
|
478
|
-
for (const current of this) {
|
|
479
|
-
if (callback.call(thisArg, current, index, this)) {
|
|
480
|
-
filteredList.add(current);
|
|
528
|
+
* Filter elements into a new heap of the same class.
|
|
529
|
+
* @remarks Time O(N log N), Space O(N)
|
|
530
|
+
* @param callback - Predicate (element, index, heap) → boolean to keep element.
|
|
531
|
+
* @param [thisArg] - Value for `this` inside the callback.
|
|
532
|
+
* @returns A new heap with the kept elements.
|
|
533
|
+
*/
|
|
534
|
+
|
|
535
|
+
filter(callback: ElementCallback<E, R, boolean>, thisArg?: unknown): this {
|
|
536
|
+
const out = this._createInstance();
|
|
537
|
+
let i = 0;
|
|
538
|
+
for (const x of this) {
|
|
539
|
+
if (thisArg === undefined ? callback(x, i++, this) : callback.call(thisArg, x, i++, this)) {
|
|
540
|
+
out.add(x);
|
|
541
|
+
} else {
|
|
542
|
+
i++;
|
|
481
543
|
}
|
|
482
|
-
index++;
|
|
483
544
|
}
|
|
484
|
-
return
|
|
485
|
-
}
|
|
486
|
-
|
|
487
|
-
/**
|
|
488
|
-
*
|
|
489
|
-
*
|
|
490
|
-
*
|
|
491
|
-
*
|
|
492
|
-
*
|
|
493
|
-
* @param
|
|
494
|
-
*
|
|
495
|
-
*
|
|
496
|
-
* @param comparator - The `comparator` parameter is a function that defines the order of the
|
|
497
|
-
* elements in the heap. It takes two elements `a` and `b` as arguments and returns a negative number
|
|
498
|
-
* if `a` should be placed before `b`, a positive number if `a` should be placed after
|
|
499
|
-
* @param [toElementFn] - The `toElementFn` parameter is an optional function that converts the raw
|
|
500
|
-
* element `RR` to the desired type `T`. It takes a single argument `rawElement` of type `RR` and
|
|
501
|
-
* returns a value of type `T`. This function is used to transform the elements of the original
|
|
502
|
-
* @param {any} [thisArg] - The `thisArg` parameter is an optional argument that allows you to
|
|
503
|
-
* specify the value of `this` within the callback function. It is used to set the context or scope
|
|
504
|
-
* in which the callback function will be executed. If `thisArg` is provided, it will be used as the
|
|
505
|
-
* value of
|
|
506
|
-
* @returns a new instance of the `Heap` class with the mapped elements.
|
|
545
|
+
return out;
|
|
546
|
+
}
|
|
547
|
+
|
|
548
|
+
/**
|
|
549
|
+
* Map elements into a new heap of possibly different element type.
|
|
550
|
+
* @remarks Time O(N log N), Space O(N)
|
|
551
|
+
* @template EM
|
|
552
|
+
* @template RM
|
|
553
|
+
* @param callback - Mapping function (element, index, heap) → newElement.
|
|
554
|
+
* @param options - Options for the output heap, including comparator for EM.
|
|
555
|
+
* @param [thisArg] - Value for `this` inside the callback.
|
|
556
|
+
* @returns A new heap with mapped elements.
|
|
507
557
|
*/
|
|
558
|
+
|
|
508
559
|
map<EM, RM>(
|
|
509
560
|
callback: ElementCallback<E, R, EM>,
|
|
510
|
-
comparator: Comparator<EM
|
|
511
|
-
|
|
512
|
-
thisArg?: any
|
|
561
|
+
options: HeapOptions<EM, RM> & { comparator: Comparator<EM> },
|
|
562
|
+
thisArg?: unknown
|
|
513
563
|
): Heap<EM, RM> {
|
|
514
|
-
const
|
|
515
|
-
|
|
516
|
-
|
|
517
|
-
|
|
518
|
-
|
|
564
|
+
const { comparator, toElementFn, ...rest } = options ?? {};
|
|
565
|
+
if (!comparator) throw new TypeError('Heap.map requires options.comparator for EM');
|
|
566
|
+
const out = this._createLike<EM, RM>([], { ...rest, comparator, toElementFn });
|
|
567
|
+
let i = 0;
|
|
568
|
+
for (const x of this) {
|
|
569
|
+
const v = thisArg === undefined ? callback(x, i++, this) : callback.call(thisArg, x, i++, this);
|
|
570
|
+
out.add(v);
|
|
519
571
|
}
|
|
520
|
-
return
|
|
572
|
+
return out;
|
|
573
|
+
}
|
|
574
|
+
|
|
575
|
+
/**
|
|
576
|
+
* Map elements into a new heap of the same element type.
|
|
577
|
+
* @remarks Time O(N log N), Space O(N)
|
|
578
|
+
* @param callback - Mapping function (element, index, heap) → element.
|
|
579
|
+
* @param [thisArg] - Value for `this` inside the callback.
|
|
580
|
+
* @returns A new heap with mapped elements.
|
|
581
|
+
*/
|
|
582
|
+
|
|
583
|
+
mapSame(callback: ElementCallback<E, R, E>, thisArg?: unknown): this {
|
|
584
|
+
const out = this._createInstance();
|
|
585
|
+
let i = 0;
|
|
586
|
+
for (const x of this) {
|
|
587
|
+
const v = thisArg === undefined ? callback(x, i++, this) : callback.call(thisArg, x, i++, this);
|
|
588
|
+
out.add(v);
|
|
589
|
+
}
|
|
590
|
+
return out;
|
|
521
591
|
}
|
|
522
592
|
|
|
523
593
|
protected _DEFAULT_COMPARATOR = (a: E, b: E): number => {
|
|
524
594
|
if (typeof a === 'object' || typeof b === 'object') {
|
|
525
|
-
throw TypeError(
|
|
526
|
-
`When comparing object types, a custom comparator must be defined in the constructor's options parameter.`
|
|
527
|
-
);
|
|
595
|
+
throw TypeError('When comparing object types, define a custom comparator in options.');
|
|
528
596
|
}
|
|
529
|
-
if (a > b) return 1;
|
|
530
|
-
if (a < b) return -1;
|
|
597
|
+
if ((a as unknown as number) > (b as unknown as number)) return 1;
|
|
598
|
+
if ((a as unknown as number) < (b as unknown as number)) return -1;
|
|
531
599
|
return 0;
|
|
532
600
|
};
|
|
533
601
|
|
|
534
|
-
protected _comparator: Comparator<E> = this._DEFAULT_COMPARATOR;
|
|
535
|
-
|
|
602
|
+
protected _comparator: Comparator<E> = this._DEFAULT_COMPARATOR; /**
|
|
603
|
+
* Get the comparator used to order elements.
|
|
604
|
+
* @remarks Time O(1), Space O(1)
|
|
605
|
+
* @returns Comparator function.
|
|
606
|
+
*/
|
|
536
607
|
/**
|
|
537
|
-
*
|
|
538
|
-
* @
|
|
608
|
+
* Get the comparator used to order elements.
|
|
609
|
+
* @remarks Time O(1), Space O(1)
|
|
610
|
+
* @returns Comparator function.
|
|
539
611
|
*/
|
|
612
|
+
|
|
540
613
|
get comparator() {
|
|
541
614
|
return this._comparator;
|
|
542
615
|
}
|
|
543
616
|
|
|
544
|
-
/**
|
|
545
|
-
* The function `_getIterator` returns an iterable iterator for the elements in the class.
|
|
546
|
-
*/
|
|
547
617
|
protected *_getIterator(): IterableIterator<E> {
|
|
548
|
-
for (const element of this.elements)
|
|
549
|
-
yield element;
|
|
550
|
-
}
|
|
618
|
+
for (const element of this.elements) yield element;
|
|
551
619
|
}
|
|
552
620
|
|
|
553
|
-
/**
|
|
554
|
-
* Time Complexity: O(log n)
|
|
555
|
-
* Space Complexity: O(1)
|
|
556
|
-
*
|
|
557
|
-
* Float operation to maintain heap properties after adding an element.
|
|
558
|
-
* @param index - The index of the newly added element.
|
|
559
|
-
*/
|
|
560
621
|
protected _bubbleUp(index: number): boolean {
|
|
561
622
|
const element = this.elements[index];
|
|
562
623
|
while (index > 0) {
|
|
@@ -570,14 +631,6 @@ export class Heap<E = any, R = any> extends IterableElementBase<E, R> {
|
|
|
570
631
|
return true;
|
|
571
632
|
}
|
|
572
633
|
|
|
573
|
-
/**
|
|
574
|
-
* Time Complexity: O(log n)
|
|
575
|
-
* Space Complexity: O(1)
|
|
576
|
-
*
|
|
577
|
-
* Sinking operation to maintain heap properties after removing the top element.
|
|
578
|
-
* @param index - The index from which to start sinking.
|
|
579
|
-
* @param halfLength
|
|
580
|
-
*/
|
|
581
634
|
protected _sinkDown(index: number, halfLength: number): boolean {
|
|
582
635
|
const element = this.elements[index];
|
|
583
636
|
while (index < halfLength) {
|
|
@@ -595,8 +648,57 @@ export class Heap<E = any, R = any> extends IterableElementBase<E, R> {
|
|
|
595
648
|
this.elements[index] = element;
|
|
596
649
|
return true;
|
|
597
650
|
}
|
|
651
|
+
|
|
652
|
+
/**
|
|
653
|
+
* (Protected) Create an empty instance of the same concrete class.
|
|
654
|
+
* @remarks Time O(1), Space O(1)
|
|
655
|
+
* @param [options] - Options to override comparator or toElementFn.
|
|
656
|
+
* @returns A like-kind empty heap instance.
|
|
657
|
+
*/
|
|
658
|
+
|
|
659
|
+
protected _createInstance(options?: HeapOptions<E, R>): this {
|
|
660
|
+
const Ctor: any = this.constructor;
|
|
661
|
+
const next: any = new Ctor([], { comparator: this.comparator, toElementFn: this.toElementFn, ...(options ?? {}) });
|
|
662
|
+
return next as this;
|
|
663
|
+
}
|
|
664
|
+
|
|
665
|
+
/**
|
|
666
|
+
* (Protected) Create a like-kind instance seeded by elements.
|
|
667
|
+
* @remarks Time O(N log N), Space O(N)
|
|
668
|
+
* @template EM
|
|
669
|
+
* @template RM
|
|
670
|
+
* @param [elements] - Iterable of elements or raw values to seed.
|
|
671
|
+
* @param [options] - Options forwarded to the constructor.
|
|
672
|
+
* @returns A like-kind heap instance.
|
|
673
|
+
*/
|
|
674
|
+
|
|
675
|
+
protected _createLike<EM, RM>(
|
|
676
|
+
elements: Iterable<EM> | Iterable<RM> = [],
|
|
677
|
+
options?: HeapOptions<EM, RM>
|
|
678
|
+
): Heap<EM, RM> {
|
|
679
|
+
const Ctor: any = this.constructor;
|
|
680
|
+
return new Ctor(elements, options) as Heap<EM, RM>;
|
|
681
|
+
}
|
|
682
|
+
|
|
683
|
+
/**
|
|
684
|
+
* (Protected) Spawn an empty like-kind heap instance.
|
|
685
|
+
* @remarks Time O(1), Space O(1)
|
|
686
|
+
* @template EM
|
|
687
|
+
* @template RM
|
|
688
|
+
* @param [options] - Options forwarded to the constructor.
|
|
689
|
+
* @returns An empty like-kind heap instance.
|
|
690
|
+
*/
|
|
691
|
+
|
|
692
|
+
protected _spawnLike<EM, RM>(options?: HeapOptions<EM, RM>): Heap<EM, RM> {
|
|
693
|
+
return this._createLike<EM, RM>([], options);
|
|
694
|
+
}
|
|
598
695
|
}
|
|
599
696
|
|
|
697
|
+
/**
|
|
698
|
+
* Node container used by FibonacciHeap.
|
|
699
|
+
* @remarks Time O(1), Space O(1)
|
|
700
|
+
* @template E
|
|
701
|
+
*/
|
|
600
702
|
export class FibonacciHeapNode<E> {
|
|
601
703
|
element: E;
|
|
602
704
|
degree: number;
|
|
@@ -606,16 +708,6 @@ export class FibonacciHeapNode<E> {
|
|
|
606
708
|
parent?: FibonacciHeapNode<E>;
|
|
607
709
|
marked: boolean;
|
|
608
710
|
|
|
609
|
-
/**
|
|
610
|
-
* The constructor function initializes an object with an element and a degree, and sets the marked
|
|
611
|
-
* property to false.
|
|
612
|
-
* @param {E} element - The "element" parameter represents the value or data that will be stored in
|
|
613
|
-
* the node of a data structure. It can be any type of data, such as a number, string, object, or
|
|
614
|
-
* even another data structure.
|
|
615
|
-
* @param [degree=0] - The degree parameter represents the degree of the element in a data structure
|
|
616
|
-
* called a Fibonacci heap. The degree of a node is the number of children it has. By default, the
|
|
617
|
-
* degree is set to 0 when a new node is created.
|
|
618
|
-
*/
|
|
619
711
|
constructor(element: E, degree = 0) {
|
|
620
712
|
this.element = element;
|
|
621
713
|
this.degree = degree;
|
|
@@ -623,39 +715,39 @@ export class FibonacciHeapNode<E> {
|
|
|
623
715
|
}
|
|
624
716
|
}
|
|
625
717
|
|
|
718
|
+
/**
|
|
719
|
+
* Fibonacci heap (min-heap) optimized for fast merges and amortized operations.
|
|
720
|
+
* @remarks Time O(1), Space O(1)
|
|
721
|
+
* @template E
|
|
722
|
+
* @example examples will be generated by unit test
|
|
723
|
+
*/
|
|
626
724
|
export class FibonacciHeap<E> {
|
|
627
725
|
/**
|
|
628
|
-
*
|
|
629
|
-
* @
|
|
630
|
-
*
|
|
631
|
-
*
|
|
632
|
-
* provided, a default comparator function will be used.
|
|
726
|
+
* Create a FibonacciHeap.
|
|
727
|
+
* @remarks Time O(1), Space O(1)
|
|
728
|
+
* @param [comparator] - Comparator to order elements (min-heap by default).
|
|
729
|
+
* @returns New FibonacciHeap instance.
|
|
633
730
|
*/
|
|
731
|
+
|
|
634
732
|
constructor(comparator?: Comparator<E>) {
|
|
635
733
|
this.clear();
|
|
636
734
|
this._comparator = comparator || this._defaultComparator;
|
|
637
|
-
|
|
638
|
-
if (typeof this.comparator !== 'function') {
|
|
639
|
-
throw new Error('FibonacciHeap constructor: given comparator should be a function.');
|
|
640
|
-
}
|
|
735
|
+
if (typeof this.comparator !== 'function') throw new Error('FibonacciHeap: comparator must be a function.');
|
|
641
736
|
}
|
|
642
737
|
|
|
643
738
|
protected _root?: FibonacciHeapNode<E>;
|
|
644
739
|
|
|
645
740
|
/**
|
|
646
|
-
*
|
|
647
|
-
* @
|
|
741
|
+
* Get the circular root list head.
|
|
742
|
+
* @remarks Time O(1), Space O(1)
|
|
743
|
+
* @returns Root node or undefined.
|
|
648
744
|
*/
|
|
745
|
+
|
|
649
746
|
get root(): FibonacciHeapNode<E> | undefined {
|
|
650
747
|
return this._root;
|
|
651
748
|
}
|
|
652
749
|
|
|
653
750
|
protected _size = 0;
|
|
654
|
-
|
|
655
|
-
/**
|
|
656
|
-
* The function returns the size of an object.
|
|
657
|
-
* @returns The size of the object, which is a number.
|
|
658
|
-
*/
|
|
659
751
|
get size(): number {
|
|
660
752
|
return this._size;
|
|
661
753
|
}
|
|
@@ -663,120 +755,84 @@ export class FibonacciHeap<E> {
|
|
|
663
755
|
protected _min?: FibonacciHeapNode<E>;
|
|
664
756
|
|
|
665
757
|
/**
|
|
666
|
-
*
|
|
667
|
-
* @
|
|
668
|
-
*
|
|
758
|
+
* Get the current minimum node.
|
|
759
|
+
* @remarks Time O(1), Space O(1)
|
|
760
|
+
* @returns Min node or undefined.
|
|
669
761
|
*/
|
|
762
|
+
|
|
670
763
|
get min(): FibonacciHeapNode<E> | undefined {
|
|
671
764
|
return this._min;
|
|
672
765
|
}
|
|
673
766
|
|
|
674
767
|
protected _comparator: Comparator<E>;
|
|
675
|
-
|
|
676
|
-
/**
|
|
677
|
-
* The function returns the comparator used for comparing elements.
|
|
678
|
-
* @returns The `_comparator` property of the object.
|
|
679
|
-
*/
|
|
680
768
|
get comparator(): Comparator<E> {
|
|
681
769
|
return this._comparator;
|
|
682
770
|
}
|
|
683
771
|
|
|
684
|
-
/**
|
|
685
|
-
* Get the size (number of elements) of the heap.
|
|
686
|
-
* @returns {number} The size of the heap. Returns 0 if the heap is empty. Returns -1 if the heap is invalid.
|
|
687
|
-
*/
|
|
688
772
|
clear(): void {
|
|
689
773
|
this._root = undefined;
|
|
690
774
|
this._min = undefined;
|
|
691
775
|
this._size = 0;
|
|
692
776
|
}
|
|
693
777
|
|
|
694
|
-
|
|
695
|
-
|
|
696
|
-
|
|
697
|
-
*
|
|
698
|
-
* Insert an element into the heap and maintain the heap properties.
|
|
699
|
-
* @param element
|
|
700
|
-
* @returns {FibonacciHeap<E>} FibonacciHeap<E> - The heap itself.
|
|
701
|
-
*/
|
|
702
|
-
add(element: E): FibonacciHeap<E> {
|
|
703
|
-
return this.push(element);
|
|
778
|
+
add(element: E): boolean {
|
|
779
|
+
this.push(element);
|
|
780
|
+
return true;
|
|
704
781
|
}
|
|
705
782
|
|
|
706
783
|
/**
|
|
707
|
-
*
|
|
708
|
-
*
|
|
709
|
-
*
|
|
710
|
-
*
|
|
711
|
-
* @param element
|
|
712
|
-
* @returns {FibonacciHeap<E>} FibonacciHeap<E> - The heap itself.
|
|
784
|
+
* Push an element into the root list.
|
|
785
|
+
* @remarks Time O(1) amortized, Space O(1)
|
|
786
|
+
* @param element - Element to insert.
|
|
787
|
+
* @returns This heap.
|
|
713
788
|
*/
|
|
714
|
-
|
|
715
|
-
|
|
789
|
+
|
|
790
|
+
push(element: E): this {
|
|
791
|
+
const node = this._createNode(element);
|
|
716
792
|
node.left = node;
|
|
717
793
|
node.right = node;
|
|
718
794
|
this.mergeWithRoot(node);
|
|
719
|
-
|
|
720
|
-
if (!this.min || this.comparator(node.element, this.min.element) <= 0) {
|
|
721
|
-
this._min = node;
|
|
722
|
-
}
|
|
723
|
-
|
|
795
|
+
if (!this.min || this.comparator(node.element, this.min.element) <= 0) this._min = node;
|
|
724
796
|
this._size++;
|
|
725
797
|
return this;
|
|
726
798
|
}
|
|
727
799
|
|
|
728
|
-
/**
|
|
729
|
-
* Time Complexity: O(1)
|
|
730
|
-
* Space Complexity: O(1)
|
|
731
|
-
*
|
|
732
|
-
* Peek at the top element of the heap without removing it.
|
|
733
|
-
* @returns The top element or undefined if the heap is empty.
|
|
734
|
-
* @protected
|
|
735
|
-
*/
|
|
736
800
|
peek(): E | undefined {
|
|
737
801
|
return this.min ? this.min.element : undefined;
|
|
738
802
|
}
|
|
739
803
|
|
|
740
804
|
/**
|
|
741
|
-
*
|
|
742
|
-
*
|
|
743
|
-
*
|
|
744
|
-
*
|
|
745
|
-
* @param {FibonacciHeapNode<E>} head - The head of the linked list.
|
|
746
|
-
* @protected
|
|
747
|
-
* @returns FibonacciHeapNode<E>[] - An array containing the elements of the linked list.
|
|
805
|
+
* Collect nodes from a circular doubly linked list starting at head.
|
|
806
|
+
* @remarks Time O(K), Space O(K)
|
|
807
|
+
* @param [head] - Start node of the circular list.
|
|
808
|
+
* @returns Array of nodes from the list.
|
|
748
809
|
*/
|
|
810
|
+
|
|
749
811
|
consumeLinkedList(head?: FibonacciHeapNode<E>): FibonacciHeapNode<E>[] {
|
|
750
812
|
const elements: FibonacciHeapNode<E>[] = [];
|
|
751
813
|
if (!head) return elements;
|
|
752
|
-
|
|
753
814
|
let node: FibonacciHeapNode<E> | undefined = head;
|
|
754
|
-
let
|
|
755
|
-
|
|
815
|
+
let started = false;
|
|
756
816
|
while (true) {
|
|
757
|
-
if (node === head &&
|
|
758
|
-
else if (node === head)
|
|
759
|
-
|
|
760
|
-
|
|
761
|
-
elements.push(node);
|
|
762
|
-
node = node.right;
|
|
763
|
-
}
|
|
817
|
+
if (node === head && started) break;
|
|
818
|
+
else if (node === head) started = true;
|
|
819
|
+
elements.push(node!);
|
|
820
|
+
node = node!.right;
|
|
764
821
|
}
|
|
765
|
-
|
|
766
822
|
return elements;
|
|
767
823
|
}
|
|
768
824
|
|
|
769
825
|
/**
|
|
770
|
-
*
|
|
771
|
-
*
|
|
772
|
-
*
|
|
773
|
-
* @param
|
|
774
|
-
* @
|
|
826
|
+
* Insert a node into a parent's child list (circular).
|
|
827
|
+
* @remarks Time O(1), Space O(1)
|
|
828
|
+
* @param parent - Parent node.
|
|
829
|
+
* @param node - Child node to insert.
|
|
830
|
+
* @returns void
|
|
775
831
|
*/
|
|
832
|
+
|
|
776
833
|
mergeWithChild(parent: FibonacciHeapNode<E>, node: FibonacciHeapNode<E>): void {
|
|
777
|
-
if (!parent.child)
|
|
778
|
-
|
|
779
|
-
} else {
|
|
834
|
+
if (!parent.child) parent.child = node;
|
|
835
|
+
else {
|
|
780
836
|
node.right = parent.child.right;
|
|
781
837
|
node.left = parent.child;
|
|
782
838
|
parent.child.right!.left = node;
|
|
@@ -784,27 +840,18 @@ export class FibonacciHeap<E> {
|
|
|
784
840
|
}
|
|
785
841
|
}
|
|
786
842
|
|
|
787
|
-
/**
|
|
788
|
-
* Time Complexity: O(log n)
|
|
789
|
-
* Space Complexity: O(1)
|
|
790
|
-
*
|
|
791
|
-
* Remove and return the top element (the smallest or largest element) from the heap.
|
|
792
|
-
* @returns The top element or undefined if the heap is empty.
|
|
793
|
-
*/
|
|
794
843
|
poll(): E | undefined {
|
|
795
844
|
return this.pop();
|
|
796
845
|
}
|
|
797
846
|
|
|
798
847
|
/**
|
|
799
|
-
*
|
|
800
|
-
*
|
|
801
|
-
*
|
|
802
|
-
* Remove and return the top element (the smallest or largest element) from the heap.
|
|
803
|
-
* @returns The top element or undefined if the heap is empty.
|
|
848
|
+
* Remove and return the minimum element, consolidating the root list.
|
|
849
|
+
* @remarks Time O(log N) amortized, Space O(1)
|
|
850
|
+
* @returns Minimum element or undefined.
|
|
804
851
|
*/
|
|
852
|
+
|
|
805
853
|
pop(): E | undefined {
|
|
806
854
|
if (this._size === 0) return undefined;
|
|
807
|
-
|
|
808
855
|
const z = this.min!;
|
|
809
856
|
if (z.child) {
|
|
810
857
|
const elements = this.consumeLinkedList(z.child);
|
|
@@ -813,9 +860,7 @@ export class FibonacciHeap<E> {
|
|
|
813
860
|
node.parent = undefined;
|
|
814
861
|
}
|
|
815
862
|
}
|
|
816
|
-
|
|
817
863
|
this.removeFromRoot(z);
|
|
818
|
-
|
|
819
864
|
if (z === z.right) {
|
|
820
865
|
this._min = undefined;
|
|
821
866
|
this._root = undefined;
|
|
@@ -823,83 +868,55 @@ export class FibonacciHeap<E> {
|
|
|
823
868
|
this._min = z.right;
|
|
824
869
|
this._consolidate();
|
|
825
870
|
}
|
|
826
|
-
|
|
827
871
|
this._size--;
|
|
828
|
-
|
|
829
872
|
return z.element;
|
|
830
873
|
}
|
|
831
874
|
|
|
832
875
|
/**
|
|
833
|
-
*
|
|
834
|
-
*
|
|
835
|
-
*
|
|
836
|
-
*
|
|
837
|
-
* @param heapToMerge
|
|
876
|
+
* Meld another heap into this heap.
|
|
877
|
+
* @remarks Time O(1), Space O(1)
|
|
878
|
+
* @param heapToMerge - Another FibonacciHeap to meld into this one.
|
|
879
|
+
* @returns void
|
|
838
880
|
*/
|
|
839
|
-
merge(heapToMerge: FibonacciHeap<E>): void {
|
|
840
|
-
if (heapToMerge.size === 0) {
|
|
841
|
-
return; // Nothing to merge
|
|
842
|
-
}
|
|
843
881
|
|
|
844
|
-
|
|
882
|
+
merge(heapToMerge: FibonacciHeap<E>): void {
|
|
883
|
+
if (heapToMerge.size === 0) return;
|
|
845
884
|
if (this.root && heapToMerge.root) {
|
|
846
|
-
const thisRoot = this.root
|
|
847
|
-
|
|
848
|
-
|
|
849
|
-
|
|
850
|
-
const otherRootLeft = otherRoot.left!;
|
|
851
|
-
|
|
885
|
+
const thisRoot = this.root,
|
|
886
|
+
otherRoot = heapToMerge.root;
|
|
887
|
+
const thisRootRight = thisRoot.right!,
|
|
888
|
+
otherRootLeft = otherRoot.left!;
|
|
852
889
|
thisRoot.right = otherRoot;
|
|
853
890
|
otherRoot.left = thisRoot;
|
|
854
|
-
|
|
855
891
|
thisRootRight.left = otherRootLeft;
|
|
856
892
|
otherRootLeft.right = thisRootRight;
|
|
893
|
+
} else if (!this.root && heapToMerge.root) {
|
|
894
|
+
this._root = heapToMerge.root;
|
|
857
895
|
}
|
|
858
|
-
|
|
859
|
-
// Update the minimum node
|
|
860
896
|
if (!this.min || (heapToMerge.min && this.comparator(heapToMerge.min.element, this.min.element) < 0)) {
|
|
861
897
|
this._min = heapToMerge.min;
|
|
862
898
|
}
|
|
863
|
-
|
|
864
|
-
// Update the size
|
|
865
899
|
this._size += heapToMerge.size;
|
|
866
|
-
|
|
867
|
-
// Clear the heap that was merged
|
|
868
900
|
heapToMerge.clear();
|
|
869
901
|
}
|
|
870
902
|
|
|
871
|
-
|
|
872
|
-
* Create a new node.
|
|
873
|
-
* @param element
|
|
874
|
-
* @protected
|
|
875
|
-
*/
|
|
876
|
-
createNode(element: E): FibonacciHeapNode<E> {
|
|
903
|
+
_createNode(element: E): FibonacciHeapNode<E> {
|
|
877
904
|
return new FibonacciHeapNode<E>(element);
|
|
878
905
|
}
|
|
879
906
|
|
|
880
|
-
|
|
881
|
-
|
|
882
|
-
|
|
883
|
-
|
|
884
|
-
* @protected
|
|
885
|
-
*/
|
|
907
|
+
isEmpty(): boolean {
|
|
908
|
+
return this._size === 0;
|
|
909
|
+
}
|
|
910
|
+
|
|
886
911
|
protected _defaultComparator(a: E, b: E): number {
|
|
887
912
|
if (a < b) return -1;
|
|
888
913
|
if (a > b) return 1;
|
|
889
914
|
return 0;
|
|
890
915
|
}
|
|
891
916
|
|
|
892
|
-
/**
|
|
893
|
-
* Time Complexity: O(1)
|
|
894
|
-
* Space Complexity: O(1)
|
|
895
|
-
*
|
|
896
|
-
* Merge the given node with the root list.
|
|
897
|
-
* @param node - The node to be merged.
|
|
898
|
-
*/
|
|
899
917
|
protected mergeWithRoot(node: FibonacciHeapNode<E>): void {
|
|
900
|
-
if (!this.root)
|
|
901
|
-
|
|
902
|
-
} else {
|
|
918
|
+
if (!this.root) this._root = node;
|
|
919
|
+
else {
|
|
903
920
|
node.right = this.root.right;
|
|
904
921
|
node.left = this.root;
|
|
905
922
|
this.root.right!.left = node;
|
|
@@ -907,29 +924,12 @@ export class FibonacciHeap<E> {
|
|
|
907
924
|
}
|
|
908
925
|
}
|
|
909
926
|
|
|
910
|
-
/**
|
|
911
|
-
* Time Complexity: O(1)
|
|
912
|
-
* Space Complexity: O(1)
|
|
913
|
-
*
|
|
914
|
-
* Remove and return the top element (the smallest or largest element) from the heap.
|
|
915
|
-
* @param node - The node to be removed.
|
|
916
|
-
* @protected
|
|
917
|
-
*/
|
|
918
927
|
protected removeFromRoot(node: FibonacciHeapNode<E>): void {
|
|
919
928
|
if (this.root === node) this._root = node.right;
|
|
920
929
|
if (node.left) node.left.right = node.right;
|
|
921
930
|
if (node.right) node.right.left = node.left;
|
|
922
931
|
}
|
|
923
932
|
|
|
924
|
-
/**
|
|
925
|
-
* Time Complexity: O(1)
|
|
926
|
-
* Space Complexity: O(1)
|
|
927
|
-
*
|
|
928
|
-
* Remove and return the top element (the smallest or largest element) from the heap.
|
|
929
|
-
* @param y
|
|
930
|
-
* @param x
|
|
931
|
-
* @protected
|
|
932
|
-
*/
|
|
933
933
|
protected _link(y: FibonacciHeapNode<E>, x: FibonacciHeapNode<E>): void {
|
|
934
934
|
this.removeFromRoot(y);
|
|
935
935
|
y.left = y;
|
|
@@ -939,13 +939,6 @@ export class FibonacciHeap<E> {
|
|
|
939
939
|
y.parent = x;
|
|
940
940
|
}
|
|
941
941
|
|
|
942
|
-
/**
|
|
943
|
-
* Time Complexity: O(n log n)
|
|
944
|
-
* Space Complexity: O(n)
|
|
945
|
-
*
|
|
946
|
-
* Remove and return the top element (the smallest or largest element) from the heap.
|
|
947
|
-
* @protected
|
|
948
|
-
*/
|
|
949
942
|
protected _consolidate(): void {
|
|
950
943
|
const A: (FibonacciHeapNode<E> | undefined)[] = new Array(this._size);
|
|
951
944
|
const elements = this.consumeLinkedList(this.root);
|
|
@@ -957,28 +950,22 @@ export class FibonacciHeap<E> {
|
|
|
957
950
|
for (const node of elements) {
|
|
958
951
|
x = node;
|
|
959
952
|
d = x.degree;
|
|
960
|
-
|
|
961
953
|
while (A[d]) {
|
|
962
954
|
y = A[d] as FibonacciHeapNode<E>;
|
|
963
|
-
|
|
964
955
|
if (this.comparator(x.element, y.element) > 0) {
|
|
965
956
|
t = x;
|
|
966
957
|
x = y;
|
|
967
958
|
y = t;
|
|
968
959
|
}
|
|
969
|
-
|
|
970
960
|
this._link(y, x);
|
|
971
961
|
A[d] = undefined;
|
|
972
962
|
d++;
|
|
973
963
|
}
|
|
974
|
-
|
|
975
964
|
A[d] = x;
|
|
976
965
|
}
|
|
977
966
|
|
|
978
|
-
for (let i = 0; i <
|
|
979
|
-
if (A[i] && this.comparator(A[i]!.element, this.min
|
|
980
|
-
this._min = A[i]!;
|
|
981
|
-
}
|
|
967
|
+
for (let i = 0; i < A.length; i++) {
|
|
968
|
+
if (A[i] && (!this.min || this.comparator(A[i]!.element, this.min.element) <= 0)) this._min = A[i]!;
|
|
982
969
|
}
|
|
983
970
|
}
|
|
984
971
|
}
|