data-structure-typed 2.6.0 → 2.6.1
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/.github/workflows/ci.yml +7 -2
- package/.github/workflows/release-package.yml +9 -2
- package/docs-site-docusaurus/docs/api/classes/AVLTree.md +108 -108
- package/docs-site-docusaurus/docs/api/classes/BST.md +101 -101
- package/docs-site-docusaurus/docs/api/classes/BinaryIndexedTree.md +13 -13
- package/docs-site-docusaurus/docs/api/classes/BinaryTree.md +66 -66
- package/docs-site-docusaurus/docs/api/classes/Deque.md +235 -51
- package/docs-site-docusaurus/docs/api/classes/DirectedGraph.md +21 -21
- package/docs-site-docusaurus/docs/api/classes/DoublyLinkedList.md +231 -67
- package/docs-site-docusaurus/docs/api/classes/FibonacciHeap.md +9 -9
- package/docs-site-docusaurus/docs/api/classes/FibonacciHeapNode.md +1 -1
- package/docs-site-docusaurus/docs/api/classes/HashMap.md +14 -14
- package/docs-site-docusaurus/docs/api/classes/Heap.md +117 -34
- package/docs-site-docusaurus/docs/api/classes/IterableElementBase.md +83 -13
- package/docs-site-docusaurus/docs/api/classes/LinearBase.md +124 -20
- package/docs-site-docusaurus/docs/api/classes/LinearLinkedBase.md +140 -32
- package/docs-site-docusaurus/docs/api/classes/LinkedHashMap.md +23 -23
- package/docs-site-docusaurus/docs/api/classes/LinkedListQueue.md +159 -51
- package/docs-site-docusaurus/docs/api/classes/MapGraph.md +20 -20
- package/docs-site-docusaurus/docs/api/classes/Matrix.md +23 -23
- package/docs-site-docusaurus/docs/api/classes/MaxHeap.md +117 -34
- package/docs-site-docusaurus/docs/api/classes/MaxPriorityQueue.md +117 -34
- package/docs-site-docusaurus/docs/api/classes/MinHeap.md +117 -34
- package/docs-site-docusaurus/docs/api/classes/MinPriorityQueue.md +117 -34
- package/docs-site-docusaurus/docs/api/classes/PriorityQueue.md +117 -34
- package/docs-site-docusaurus/docs/api/classes/Queue.md +142 -34
- package/docs-site-docusaurus/docs/api/classes/RedBlackTree.md +117 -117
- package/docs-site-docusaurus/docs/api/classes/SegmentTree.md +8 -8
- package/docs-site-docusaurus/docs/api/classes/SinglyLinkedList.md +158 -50
- package/docs-site-docusaurus/docs/api/classes/SkipList.md +21 -21
- package/docs-site-docusaurus/docs/api/classes/Stack.md +108 -26
- package/docs-site-docusaurus/docs/api/classes/TreeMap.md +33 -33
- package/docs-site-docusaurus/docs/api/classes/TreeMultiMap.md +75 -39
- package/docs-site-docusaurus/docs/api/classes/TreeSet.md +301 -39
- package/docs-site-docusaurus/docs/api/classes/Trie.md +110 -28
- package/docs-site-docusaurus/docs/api/classes/UndirectedGraph.md +20 -20
- package/package.json +45 -46
- package/src/common/error.ts +15 -32
- package/src/common/index.ts +0 -3
- package/src/data-structures/base/iterable-element-base.ts +0 -3
- package/src/data-structures/base/linear-base.ts +2 -36
- package/src/data-structures/binary-tree/avl-tree.ts +31 -529
- package/src/data-structures/binary-tree/binary-indexed-tree.ts +47 -572
- package/src/data-structures/binary-tree/binary-tree.ts +326 -1311
- package/src/data-structures/binary-tree/bst.ts +158 -1082
- package/src/data-structures/binary-tree/red-black-tree.ts +451 -1290
- package/src/data-structures/binary-tree/segment-tree.ts +73 -351
- package/src/data-structures/binary-tree/tree-map.ts +462 -5124
- package/src/data-structures/binary-tree/tree-multi-map.ts +302 -4914
- package/src/data-structures/binary-tree/tree-multi-set.ts +284 -3972
- package/src/data-structures/binary-tree/tree-set.ts +338 -4836
- package/src/data-structures/graph/abstract-graph.ts +98 -167
- package/src/data-structures/graph/directed-graph.ts +137 -562
- package/src/data-structures/graph/map-graph.ts +0 -3
- package/src/data-structures/graph/undirected-graph.ts +132 -511
- package/src/data-structures/hash/hash-map.ts +154 -582
- package/src/data-structures/heap/heap.ts +200 -795
- package/src/data-structures/linked-list/doubly-linked-list.ts +121 -865
- package/src/data-structures/linked-list/singly-linked-list.ts +122 -794
- package/src/data-structures/linked-list/skip-linked-list.ts +211 -918
- package/src/data-structures/matrix/matrix.ts +179 -518
- package/src/data-structures/matrix/navigator.ts +0 -1
- package/src/data-structures/priority-queue/max-priority-queue.ts +1 -6
- package/src/data-structures/priority-queue/min-priority-queue.ts +6 -11
- package/src/data-structures/priority-queue/priority-queue.ts +1 -2
- package/src/data-structures/queue/deque.ts +214 -882
- package/src/data-structures/queue/queue.ts +102 -625
- package/src/data-structures/stack/stack.ts +76 -505
- package/src/data-structures/trie/trie.ts +98 -628
- package/src/types/common.ts +0 -10
- package/src/types/data-structures/binary-tree/bst.ts +0 -7
- package/src/types/data-structures/binary-tree/red-black-tree.ts +0 -1
- package/src/types/data-structures/graph/abstract-graph.ts +0 -2
- package/src/types/data-structures/hash/hash-map.ts +0 -3
- package/src/types/data-structures/hash/index.ts +0 -1
- package/src/types/data-structures/matrix/navigator.ts +0 -2
- package/src/types/utils/utils.ts +0 -7
- package/src/types/utils/validate-type.ts +0 -7
- package/src/utils/number.ts +0 -2
- package/src/utils/utils.ts +0 -5
|
@@ -5,7 +5,6 @@
|
|
|
5
5
|
* @copyright Copyright (c) 2022 Pablo Zeng <zrwusa@gmail.com>
|
|
6
6
|
* @license MIT License
|
|
7
7
|
*/
|
|
8
|
-
|
|
9
8
|
import type { ElementCallback, TrieOptions } from '../../types';
|
|
10
9
|
import { IterableElementBase } from '../base';
|
|
11
10
|
import { ERR, raise } from '../../common';
|
|
@@ -20,7 +19,6 @@ export class TrieNode {
|
|
|
20
19
|
* @remarks Time O(1), Space O(1)
|
|
21
20
|
* @returns New TrieNode instance.
|
|
22
21
|
*/
|
|
23
|
-
|
|
24
22
|
constructor(key: string) {
|
|
25
23
|
this._key = key;
|
|
26
24
|
this._isEnd = false;
|
|
@@ -34,7 +32,6 @@ export class TrieNode {
|
|
|
34
32
|
* @remarks Time O(1), Space O(1)
|
|
35
33
|
* @returns Character key string.
|
|
36
34
|
*/
|
|
37
|
-
|
|
38
35
|
get key(): string {
|
|
39
36
|
return this._key;
|
|
40
37
|
}
|
|
@@ -45,7 +42,6 @@ export class TrieNode {
|
|
|
45
42
|
* @param value - New character key.
|
|
46
43
|
* @returns void
|
|
47
44
|
*/
|
|
48
|
-
|
|
49
45
|
set key(value: string) {
|
|
50
46
|
this._key = value;
|
|
51
47
|
}
|
|
@@ -57,7 +53,6 @@ export class TrieNode {
|
|
|
57
53
|
* @remarks Time O(1), Space O(1)
|
|
58
54
|
* @returns Map from character to child node.
|
|
59
55
|
*/
|
|
60
|
-
|
|
61
56
|
get children(): Map<string, TrieNode> {
|
|
62
57
|
return this._children;
|
|
63
58
|
}
|
|
@@ -68,7 +63,6 @@ export class TrieNode {
|
|
|
68
63
|
* @param value - New map of character → node.
|
|
69
64
|
* @returns void
|
|
70
65
|
*/
|
|
71
|
-
|
|
72
66
|
set children(value: Map<string, TrieNode>) {
|
|
73
67
|
this._children = value;
|
|
74
68
|
}
|
|
@@ -80,7 +74,6 @@ export class TrieNode {
|
|
|
80
74
|
* @remarks Time O(1), Space O(1)
|
|
81
75
|
* @returns True if this node ends a word.
|
|
82
76
|
*/
|
|
83
|
-
|
|
84
77
|
get isEnd(): boolean {
|
|
85
78
|
return this._isEnd;
|
|
86
79
|
}
|
|
@@ -91,7 +84,6 @@ export class TrieNode {
|
|
|
91
84
|
* @param value - Whether this node ends a word.
|
|
92
85
|
* @returns void
|
|
93
86
|
*/
|
|
94
|
-
|
|
95
87
|
set isEnd(value: boolean) {
|
|
96
88
|
this._isEnd = value;
|
|
97
89
|
}
|
|
@@ -221,7 +213,6 @@ export class Trie<R = any> extends IterableElementBase<string, R> {
|
|
|
221
213
|
* @param [options] - Options such as toElementFn and caseSensitive.
|
|
222
214
|
* @returns New Trie instance.
|
|
223
215
|
*/
|
|
224
|
-
|
|
225
216
|
constructor(words: Iterable<string> | Iterable<R> = [], options?: TrieOptions<R>) {
|
|
226
217
|
super(options);
|
|
227
218
|
if (options) {
|
|
@@ -240,7 +231,6 @@ export class Trie<R = any> extends IterableElementBase<string, R> {
|
|
|
240
231
|
* @remarks Time O(1), Space O(1)
|
|
241
232
|
* @returns Word count.
|
|
242
233
|
*/
|
|
243
|
-
|
|
244
234
|
get size(): number {
|
|
245
235
|
return this._size;
|
|
246
236
|
}
|
|
@@ -252,7 +242,6 @@ export class Trie<R = any> extends IterableElementBase<string, R> {
|
|
|
252
242
|
* @remarks Time O(1), Space O(1)
|
|
253
243
|
* @returns True if case-sensitive.
|
|
254
244
|
*/
|
|
255
|
-
|
|
256
245
|
get caseSensitive(): boolean {
|
|
257
246
|
return this._caseSensitive;
|
|
258
247
|
}
|
|
@@ -264,7 +253,6 @@ export class Trie<R = any> extends IterableElementBase<string, R> {
|
|
|
264
253
|
* @remarks Time O(1), Space O(1)
|
|
265
254
|
* @returns Root TrieNode.
|
|
266
255
|
*/
|
|
267
|
-
|
|
268
256
|
get root() {
|
|
269
257
|
return this._root;
|
|
270
258
|
}
|
|
@@ -274,7 +262,6 @@ export class Trie<R = any> extends IterableElementBase<string, R> {
|
|
|
274
262
|
* @remarks Time O(1), Space O(1)
|
|
275
263
|
* @returns Total number of elements.
|
|
276
264
|
*/
|
|
277
|
-
|
|
278
265
|
protected get _total() {
|
|
279
266
|
return this._size;
|
|
280
267
|
}
|
|
@@ -284,65 +271,22 @@ export class Trie<R = any> extends IterableElementBase<string, R> {
|
|
|
284
271
|
* @remarks Time O(L), Space O(L)
|
|
285
272
|
* @param word - Word to insert.
|
|
286
273
|
* @returns True if the word was newly added.
|
|
287
|
-
|
|
288
|
-
|
|
289
|
-
|
|
290
|
-
|
|
291
|
-
|
|
292
|
-
|
|
293
|
-
|
|
294
|
-
|
|
295
|
-
|
|
296
|
-
|
|
297
|
-
|
|
298
|
-
|
|
299
|
-
|
|
300
|
-
|
|
301
|
-
|
|
302
|
-
|
|
303
|
-
|
|
304
|
-
|
|
305
|
-
|
|
306
|
-
|
|
307
|
-
|
|
308
|
-
|
|
309
|
-
|
|
310
|
-
|
|
311
|
-
|
|
312
|
-
|
|
313
|
-
|
|
314
|
-
|
|
315
|
-
|
|
316
|
-
|
|
317
|
-
|
|
318
|
-
|
|
319
|
-
|
|
320
|
-
|
|
321
|
-
|
|
322
|
-
|
|
323
|
-
|
|
324
|
-
|
|
325
|
-
|
|
326
|
-
|
|
327
|
-
|
|
328
|
-
|
|
329
|
-
* @example
|
|
330
|
-
* // basic Trie creation and add words
|
|
331
|
-
* // Create a simple Trie with initial words
|
|
332
|
-
* const trie = new Trie(['apple', 'app', 'apply']);
|
|
333
|
-
*
|
|
334
|
-
* // Verify size
|
|
335
|
-
* console.log(trie.size); // 3;
|
|
336
|
-
*
|
|
337
|
-
* // Check if words exist
|
|
338
|
-
* console.log(trie.has('apple')); // true;
|
|
339
|
-
* console.log(trie.has('app')); // true;
|
|
340
|
-
*
|
|
341
|
-
* // Add a new word
|
|
342
|
-
* trie.add('application');
|
|
343
|
-
* console.log(trie.size); // 4;
|
|
274
|
+
* @example
|
|
275
|
+
* // basic Trie creation and add words
|
|
276
|
+
* // Create a simple Trie with initial words
|
|
277
|
+
* const trie = new Trie(['apple', 'app', 'apply']);
|
|
278
|
+
*
|
|
279
|
+
* // Verify size
|
|
280
|
+
* console.log(trie.size); // 3;
|
|
281
|
+
*
|
|
282
|
+
* // Check if words exist
|
|
283
|
+
* console.log(trie.has('apple')); // true;
|
|
284
|
+
* console.log(trie.has('app')); // true;
|
|
285
|
+
*
|
|
286
|
+
* // Add a new word
|
|
287
|
+
* trie.add('application');
|
|
288
|
+
* console.log(trie.size); // 4;
|
|
344
289
|
*/
|
|
345
|
-
|
|
346
290
|
add(word: string): boolean {
|
|
347
291
|
word = this._caseProcess(word);
|
|
348
292
|
let cur = this.root;
|
|
@@ -368,54 +312,14 @@ export class Trie<R = any> extends IterableElementBase<string, R> {
|
|
|
368
312
|
* @remarks Time O(ΣL), Space O(ΣL)
|
|
369
313
|
* @param words - Iterable of strings (or raw records if toElementFn is provided).
|
|
370
314
|
* @returns Array of per-word 'added' flags.
|
|
371
|
-
|
|
372
|
-
|
|
373
|
-
|
|
374
|
-
|
|
375
|
-
|
|
376
|
-
|
|
377
|
-
|
|
378
|
-
|
|
379
|
-
|
|
380
|
-
|
|
381
|
-
|
|
382
|
-
|
|
383
|
-
|
|
384
|
-
|
|
385
|
-
|
|
386
|
-
|
|
387
|
-
|
|
388
|
-
|
|
389
|
-
|
|
390
|
-
|
|
391
|
-
|
|
392
|
-
|
|
393
|
-
|
|
394
|
-
|
|
395
|
-
|
|
396
|
-
|
|
397
|
-
|
|
398
|
-
|
|
399
|
-
|
|
400
|
-
|
|
401
|
-
|
|
402
|
-
|
|
403
|
-
|
|
404
|
-
|
|
405
|
-
|
|
406
|
-
|
|
407
|
-
|
|
408
|
-
|
|
409
|
-
|
|
410
|
-
* @example
|
|
411
|
-
* // Add multiple words
|
|
412
|
-
* const trie = new Trie();
|
|
413
|
-
* trie.addMany(['cat', 'car', 'card']);
|
|
414
|
-
* console.log(trie.has('cat')); // true;
|
|
415
|
-
* console.log(trie.has('car')); // true;
|
|
416
|
-
* console.log(trie.size); // 3;
|
|
315
|
+
* @example
|
|
316
|
+
* // Add multiple words
|
|
317
|
+
* const trie = new Trie();
|
|
318
|
+
* trie.addMany(['cat', 'car', 'card']);
|
|
319
|
+
* console.log(trie.has('cat')); // true;
|
|
320
|
+
* console.log(trie.has('car')); // true;
|
|
321
|
+
* console.log(trie.size); // 3;
|
|
417
322
|
*/
|
|
418
|
-
|
|
419
323
|
addMany(words: Iterable<string> | Iterable<R>): boolean[] {
|
|
420
324
|
const ans: boolean[] = [];
|
|
421
325
|
for (const word of words) {
|
|
@@ -433,57 +337,14 @@ export class Trie<R = any> extends IterableElementBase<string, R> {
|
|
|
433
337
|
* @remarks Time O(L), Space O(1)
|
|
434
338
|
* @param word - Word to search for.
|
|
435
339
|
* @returns True if present.
|
|
436
|
-
|
|
437
|
-
|
|
438
|
-
|
|
439
|
-
|
|
440
|
-
|
|
441
|
-
|
|
442
|
-
|
|
443
|
-
|
|
444
|
-
|
|
445
|
-
|
|
446
|
-
|
|
447
|
-
|
|
448
|
-
|
|
449
|
-
|
|
450
|
-
|
|
451
|
-
|
|
452
|
-
|
|
453
|
-
|
|
454
|
-
|
|
455
|
-
|
|
456
|
-
|
|
457
|
-
|
|
458
|
-
|
|
459
|
-
|
|
460
|
-
|
|
461
|
-
|
|
462
|
-
|
|
463
|
-
|
|
464
|
-
|
|
465
|
-
|
|
466
|
-
|
|
467
|
-
|
|
468
|
-
|
|
469
|
-
|
|
470
|
-
|
|
471
|
-
|
|
472
|
-
|
|
473
|
-
|
|
474
|
-
|
|
475
|
-
|
|
476
|
-
|
|
477
|
-
|
|
478
|
-
* @example
|
|
479
|
-
* // Check if a word exists
|
|
480
|
-
* const dict = new Trie(['apple', 'app', 'application']);
|
|
481
|
-
*
|
|
482
|
-
* console.log(dict.has('app')); // true;
|
|
483
|
-
* console.log(dict.has('apple')); // true;
|
|
484
|
-
* console.log(dict.has('ap')); // false;
|
|
340
|
+
* @example
|
|
341
|
+
* // Check if a word exists
|
|
342
|
+
* const dict = new Trie(['apple', 'app', 'application']);
|
|
343
|
+
*
|
|
344
|
+
* console.log(dict.has('app')); // true;
|
|
345
|
+
* console.log(dict.has('apple')); // true;
|
|
346
|
+
* console.log(dict.has('ap')); // false;
|
|
485
347
|
*/
|
|
486
|
-
|
|
487
348
|
override has(word: string): boolean {
|
|
488
349
|
word = this._caseProcess(word);
|
|
489
350
|
let cur = this.root;
|
|
@@ -499,53 +360,13 @@ export class Trie<R = any> extends IterableElementBase<string, R> {
|
|
|
499
360
|
* Check whether the trie is empty.
|
|
500
361
|
* @remarks Time O(1), Space O(1)
|
|
501
362
|
* @returns True if size is 0.
|
|
502
|
-
|
|
503
|
-
|
|
504
|
-
|
|
505
|
-
|
|
506
|
-
|
|
507
|
-
|
|
508
|
-
|
|
509
|
-
|
|
510
|
-
|
|
511
|
-
|
|
512
|
-
|
|
513
|
-
|
|
514
|
-
|
|
515
|
-
|
|
516
|
-
|
|
517
|
-
|
|
518
|
-
|
|
519
|
-
|
|
520
|
-
|
|
521
|
-
|
|
522
|
-
|
|
523
|
-
|
|
524
|
-
|
|
525
|
-
|
|
526
|
-
|
|
527
|
-
|
|
528
|
-
|
|
529
|
-
|
|
530
|
-
|
|
531
|
-
|
|
532
|
-
|
|
533
|
-
|
|
534
|
-
|
|
535
|
-
|
|
536
|
-
|
|
537
|
-
|
|
538
|
-
|
|
539
|
-
|
|
540
|
-
|
|
541
|
-
* @example
|
|
542
|
-
* // Check if empty
|
|
543
|
-
* const trie = new Trie();
|
|
544
|
-
* console.log(trie.isEmpty()); // true;
|
|
545
|
-
* trie.add('word');
|
|
546
|
-
* console.log(trie.isEmpty()); // false;
|
|
363
|
+
* @example
|
|
364
|
+
* // Check if empty
|
|
365
|
+
* const trie = new Trie();
|
|
366
|
+
* console.log(trie.isEmpty()); // true;
|
|
367
|
+
* trie.add('word');
|
|
368
|
+
* console.log(trie.isEmpty()); // false;
|
|
547
369
|
*/
|
|
548
|
-
|
|
549
370
|
isEmpty(): boolean {
|
|
550
371
|
return this._size === 0;
|
|
551
372
|
}
|
|
@@ -554,52 +375,12 @@ export class Trie<R = any> extends IterableElementBase<string, R> {
|
|
|
554
375
|
* Remove all words and reset to a fresh root.
|
|
555
376
|
* @remarks Time O(1), Space O(1)
|
|
556
377
|
* @returns void
|
|
557
|
-
|
|
558
|
-
|
|
559
|
-
|
|
560
|
-
|
|
561
|
-
|
|
562
|
-
|
|
563
|
-
|
|
564
|
-
|
|
565
|
-
|
|
566
|
-
|
|
567
|
-
|
|
568
|
-
|
|
569
|
-
|
|
570
|
-
|
|
571
|
-
|
|
572
|
-
|
|
573
|
-
|
|
574
|
-
|
|
575
|
-
|
|
576
|
-
|
|
577
|
-
|
|
578
|
-
|
|
579
|
-
|
|
580
|
-
|
|
581
|
-
|
|
582
|
-
|
|
583
|
-
|
|
584
|
-
|
|
585
|
-
|
|
586
|
-
|
|
587
|
-
|
|
588
|
-
|
|
589
|
-
|
|
590
|
-
|
|
591
|
-
|
|
592
|
-
|
|
593
|
-
|
|
594
|
-
|
|
595
|
-
|
|
596
|
-
* @example
|
|
597
|
-
* // Remove all words
|
|
598
|
-
* const trie = new Trie(['a', 'b', 'c']);
|
|
599
|
-
* trie.clear();
|
|
600
|
-
* console.log(trie.isEmpty()); // true;
|
|
378
|
+
* @example
|
|
379
|
+
* // Remove all words
|
|
380
|
+
* const trie = new Trie(['a', 'b', 'c']);
|
|
381
|
+
* trie.clear();
|
|
382
|
+
* console.log(trie.isEmpty()); // true;
|
|
601
383
|
*/
|
|
602
|
-
|
|
603
384
|
clear(): void {
|
|
604
385
|
this._size = 0;
|
|
605
386
|
this._root = new TrieNode('');
|
|
@@ -610,67 +391,24 @@ export class Trie<R = any> extends IterableElementBase<string, R> {
|
|
|
610
391
|
* @remarks Time O(L), Space O(1)
|
|
611
392
|
* @param word - Word to delete.
|
|
612
393
|
* @returns True if a word was removed.
|
|
613
|
-
|
|
614
|
-
|
|
615
|
-
|
|
616
|
-
|
|
617
|
-
|
|
618
|
-
|
|
619
|
-
|
|
620
|
-
|
|
621
|
-
|
|
622
|
-
|
|
623
|
-
|
|
624
|
-
|
|
625
|
-
|
|
626
|
-
|
|
627
|
-
|
|
628
|
-
|
|
629
|
-
|
|
630
|
-
|
|
631
|
-
|
|
632
|
-
|
|
633
|
-
|
|
634
|
-
|
|
635
|
-
|
|
636
|
-
|
|
637
|
-
|
|
638
|
-
|
|
639
|
-
|
|
640
|
-
|
|
641
|
-
|
|
642
|
-
|
|
643
|
-
|
|
644
|
-
|
|
645
|
-
|
|
646
|
-
|
|
647
|
-
|
|
648
|
-
|
|
649
|
-
|
|
650
|
-
|
|
651
|
-
|
|
652
|
-
|
|
653
|
-
|
|
654
|
-
|
|
655
|
-
* @example
|
|
656
|
-
* // Trie delete and iteration
|
|
657
|
-
* const trie = new Trie(['car', 'card', 'care', 'careful', 'can', 'cat']);
|
|
658
|
-
*
|
|
659
|
-
* // Delete a word
|
|
660
|
-
* trie.delete('card');
|
|
661
|
-
* console.log(trie.has('card')); // false;
|
|
662
|
-
*
|
|
663
|
-
* // Word with same prefix still exists
|
|
664
|
-
* console.log(trie.has('care')); // true;
|
|
665
|
-
*
|
|
666
|
-
* // Size decreased
|
|
667
|
-
* console.log(trie.size); // 5;
|
|
668
|
-
*
|
|
669
|
-
* // Iterate through all words
|
|
670
|
-
* const allWords = [...trie];
|
|
671
|
-
* console.log(allWords.length); // 5;
|
|
394
|
+
* @example
|
|
395
|
+
* // Trie delete and iteration
|
|
396
|
+
* const trie = new Trie(['car', 'card', 'care', 'careful', 'can', 'cat']);
|
|
397
|
+
*
|
|
398
|
+
* // Delete a word
|
|
399
|
+
* trie.delete('card');
|
|
400
|
+
* console.log(trie.has('card')); // false;
|
|
401
|
+
*
|
|
402
|
+
* // Word with same prefix still exists
|
|
403
|
+
* console.log(trie.has('care')); // true;
|
|
404
|
+
*
|
|
405
|
+
* // Size decreased
|
|
406
|
+
* console.log(trie.size); // 5;
|
|
407
|
+
*
|
|
408
|
+
* // Iterate through all words
|
|
409
|
+
* const allWords = [...trie];
|
|
410
|
+
* console.log(allWords.length); // 5;
|
|
672
411
|
*/
|
|
673
|
-
|
|
674
412
|
delete(word: string): boolean {
|
|
675
413
|
word = this._caseProcess(word);
|
|
676
414
|
let isDeleted = false;
|
|
@@ -699,7 +437,6 @@ export class Trie<R = any> extends IterableElementBase<string, R> {
|
|
|
699
437
|
}
|
|
700
438
|
return false;
|
|
701
439
|
};
|
|
702
|
-
|
|
703
440
|
dfs(this.root, 0);
|
|
704
441
|
if (isDeleted) {
|
|
705
442
|
this._size--;
|
|
@@ -712,7 +449,6 @@ export class Trie<R = any> extends IterableElementBase<string, R> {
|
|
|
712
449
|
* @remarks Time O(N), Space O(H)
|
|
713
450
|
* @returns Maximum depth from root to a leaf.
|
|
714
451
|
*/
|
|
715
|
-
|
|
716
452
|
getHeight(): number {
|
|
717
453
|
const startNode = this.root;
|
|
718
454
|
let maxDepth = 0;
|
|
@@ -739,7 +475,6 @@ export class Trie<R = any> extends IterableElementBase<string, R> {
|
|
|
739
475
|
* @param input - String to test as prefix.
|
|
740
476
|
* @returns True if input is a prefix but not a full word.
|
|
741
477
|
*/
|
|
742
|
-
|
|
743
478
|
hasPurePrefix(input: string): boolean {
|
|
744
479
|
input = this._caseProcess(input);
|
|
745
480
|
let cur = this.root;
|
|
@@ -756,57 +491,14 @@ export class Trie<R = any> extends IterableElementBase<string, R> {
|
|
|
756
491
|
* @remarks Time O(L), Space O(1)
|
|
757
492
|
* @param input - String to test as prefix.
|
|
758
493
|
* @returns True if input matches a path from root.
|
|
759
|
-
|
|
760
|
-
|
|
761
|
-
|
|
762
|
-
|
|
763
|
-
|
|
764
|
-
|
|
765
|
-
|
|
766
|
-
|
|
767
|
-
|
|
768
|
-
|
|
769
|
-
|
|
770
|
-
|
|
771
|
-
|
|
772
|
-
|
|
773
|
-
|
|
774
|
-
|
|
775
|
-
|
|
776
|
-
|
|
777
|
-
|
|
778
|
-
|
|
779
|
-
|
|
780
|
-
|
|
781
|
-
|
|
782
|
-
|
|
783
|
-
|
|
784
|
-
|
|
785
|
-
|
|
786
|
-
|
|
787
|
-
|
|
788
|
-
|
|
789
|
-
|
|
790
|
-
|
|
791
|
-
|
|
792
|
-
|
|
793
|
-
|
|
794
|
-
|
|
795
|
-
|
|
796
|
-
|
|
797
|
-
|
|
798
|
-
|
|
799
|
-
|
|
800
|
-
|
|
801
|
-
* @example
|
|
802
|
-
* // Check if a prefix exists
|
|
803
|
-
* const trie = new Trie(['hello', 'help', 'world']);
|
|
804
|
-
*
|
|
805
|
-
* console.log(trie.hasPrefix('hel')); // true;
|
|
806
|
-
* console.log(trie.hasPrefix('wor')); // true;
|
|
807
|
-
* console.log(trie.hasPrefix('xyz')); // false;
|
|
494
|
+
* @example
|
|
495
|
+
* // Check if a prefix exists
|
|
496
|
+
* const trie = new Trie(['hello', 'help', 'world']);
|
|
497
|
+
*
|
|
498
|
+
* console.log(trie.hasPrefix('hel')); // true;
|
|
499
|
+
* console.log(trie.hasPrefix('wor')); // true;
|
|
500
|
+
* console.log(trie.hasPrefix('xyz')); // false;
|
|
808
501
|
*/
|
|
809
|
-
|
|
810
502
|
hasPrefix(input: string): boolean {
|
|
811
503
|
input = this._caseProcess(input);
|
|
812
504
|
let cur = this.root;
|
|
@@ -824,7 +516,6 @@ export class Trie<R = any> extends IterableElementBase<string, R> {
|
|
|
824
516
|
* @param input - Candidate longest common prefix.
|
|
825
517
|
* @returns True if input equals the common prefix.
|
|
826
518
|
*/
|
|
827
|
-
|
|
828
519
|
hasCommonPrefix(input: string): boolean {
|
|
829
520
|
input = this._caseProcess(input);
|
|
830
521
|
let commonPre = '';
|
|
@@ -843,55 +534,12 @@ export class Trie<R = any> extends IterableElementBase<string, R> {
|
|
|
843
534
|
* Return the longest common prefix among all words.
|
|
844
535
|
* @remarks Time O(H), Space O(1)
|
|
845
536
|
* @returns The longest common prefix string.
|
|
846
|
-
|
|
847
|
-
|
|
848
|
-
|
|
849
|
-
|
|
850
|
-
|
|
851
|
-
|
|
852
|
-
|
|
853
|
-
|
|
854
|
-
|
|
855
|
-
|
|
856
|
-
|
|
857
|
-
|
|
858
|
-
|
|
859
|
-
|
|
860
|
-
|
|
861
|
-
|
|
862
|
-
|
|
863
|
-
|
|
864
|
-
|
|
865
|
-
|
|
866
|
-
|
|
867
|
-
|
|
868
|
-
|
|
869
|
-
|
|
870
|
-
|
|
871
|
-
|
|
872
|
-
|
|
873
|
-
|
|
874
|
-
|
|
875
|
-
|
|
876
|
-
|
|
877
|
-
|
|
878
|
-
|
|
879
|
-
|
|
880
|
-
|
|
881
|
-
|
|
882
|
-
|
|
883
|
-
|
|
884
|
-
|
|
885
|
-
|
|
886
|
-
|
|
887
|
-
|
|
888
|
-
* @example
|
|
889
|
-
* // Find shared prefix
|
|
890
|
-
* const trie = new Trie(['flower', 'flow', 'flight']);
|
|
891
|
-
*
|
|
892
|
-
* console.log(trie.getLongestCommonPrefix()); // 'fl';
|
|
537
|
+
* @example
|
|
538
|
+
* // Find shared prefix
|
|
539
|
+
* const trie = new Trie(['flower', 'flow', 'flight']);
|
|
540
|
+
*
|
|
541
|
+
* console.log(trie.getLongestCommonPrefix()); // 'fl';
|
|
893
542
|
*/
|
|
894
|
-
|
|
895
543
|
getLongestCommonPrefix(): string {
|
|
896
544
|
let commonPre = '';
|
|
897
545
|
const dfs = (cur: TrieNode) => {
|
|
@@ -911,66 +559,22 @@ export class Trie<R = any> extends IterableElementBase<string, R> {
|
|
|
911
559
|
* @param [max] - Maximum number of words to return; default is Number.MAX_SAFE_INTEGER.
|
|
912
560
|
* @param [isAllWhenEmptyPrefix] - When true, collect from root even if prefix is empty.
|
|
913
561
|
* @returns Array of collected words (at most max).
|
|
914
|
-
|
|
915
|
-
|
|
916
|
-
|
|
917
|
-
|
|
918
|
-
|
|
919
|
-
|
|
920
|
-
|
|
921
|
-
|
|
922
|
-
|
|
923
|
-
|
|
924
|
-
|
|
925
|
-
|
|
926
|
-
|
|
927
|
-
|
|
928
|
-
|
|
929
|
-
|
|
930
|
-
|
|
931
|
-
|
|
932
|
-
|
|
933
|
-
|
|
934
|
-
|
|
935
|
-
|
|
936
|
-
|
|
937
|
-
|
|
938
|
-
|
|
939
|
-
|
|
940
|
-
|
|
941
|
-
|
|
942
|
-
|
|
943
|
-
|
|
944
|
-
|
|
945
|
-
|
|
946
|
-
|
|
947
|
-
|
|
948
|
-
|
|
949
|
-
|
|
950
|
-
|
|
951
|
-
|
|
952
|
-
|
|
953
|
-
|
|
954
|
-
|
|
955
|
-
|
|
956
|
-
* @example
|
|
957
|
-
* // Trie getWords and prefix search
|
|
958
|
-
* const trie = new Trie(['apple', 'app', 'apply', 'application', 'apricot']);
|
|
959
|
-
*
|
|
960
|
-
* // Get all words with prefix 'app'
|
|
961
|
-
* const appWords = trie.getWords('app');
|
|
962
|
-
* console.log(appWords); // contains 'app';
|
|
963
|
-
* console.log(appWords); // contains 'apple';
|
|
964
|
-
* console.log(appWords); // contains 'apply';
|
|
965
|
-
* console.log(appWords); // contains 'application';
|
|
966
|
-
* expect(appWords).not.toContain('apricot');
|
|
562
|
+
* @example
|
|
563
|
+
* // Trie getWords and prefix search
|
|
564
|
+
* const trie = new Trie(['apple', 'app', 'apply', 'application', 'apricot']);
|
|
565
|
+
*
|
|
566
|
+
* // Get all words with prefix 'app'
|
|
567
|
+
* const appWords = trie.getWords('app');
|
|
568
|
+
* console.log(appWords); // contains 'app';
|
|
569
|
+
* console.log(appWords); // contains 'apple';
|
|
570
|
+
* console.log(appWords); // contains 'apply';
|
|
571
|
+
* console.log(appWords); // contains 'application';
|
|
572
|
+
* expect(appWords).not.toContain('apricot');
|
|
967
573
|
*/
|
|
968
|
-
|
|
969
574
|
getWords(prefix = '', max = Number.MAX_SAFE_INTEGER, isAllWhenEmptyPrefix = false): string[] {
|
|
970
575
|
prefix = this._caseProcess(prefix);
|
|
971
576
|
const words: string[] = [];
|
|
972
577
|
let found = 0;
|
|
973
|
-
|
|
974
578
|
const dfs = (node: TrieNode, word: string): void => {
|
|
975
579
|
for (const [char, childNode] of node.children) {
|
|
976
580
|
if (found >= max) return;
|
|
@@ -982,9 +586,7 @@ export class Trie<R = any> extends IterableElementBase<string, R> {
|
|
|
982
586
|
found++;
|
|
983
587
|
}
|
|
984
588
|
};
|
|
985
|
-
|
|
986
589
|
let startNode = this.root;
|
|
987
|
-
|
|
988
590
|
if (prefix) {
|
|
989
591
|
for (const c of prefix) {
|
|
990
592
|
const nodeC = startNode.children.get(c);
|
|
@@ -995,9 +597,7 @@ export class Trie<R = any> extends IterableElementBase<string, R> {
|
|
|
995
597
|
}
|
|
996
598
|
}
|
|
997
599
|
}
|
|
998
|
-
|
|
999
600
|
if (isAllWhenEmptyPrefix || startNode !== this.root) dfs(startNode, prefix);
|
|
1000
|
-
|
|
1001
601
|
return words;
|
|
1002
602
|
}
|
|
1003
603
|
|
|
@@ -1005,53 +605,13 @@ export class Trie<R = any> extends IterableElementBase<string, R> {
|
|
|
1005
605
|
* Deep clone this trie by iterating and inserting all words.
|
|
1006
606
|
* @remarks Time O(ΣL), Space O(ΣL)
|
|
1007
607
|
* @returns A new trie with the same words and options.
|
|
1008
|
-
|
|
1009
|
-
|
|
1010
|
-
|
|
1011
|
-
|
|
1012
|
-
|
|
1013
|
-
|
|
1014
|
-
|
|
1015
|
-
|
|
1016
|
-
|
|
1017
|
-
|
|
1018
|
-
|
|
1019
|
-
|
|
1020
|
-
|
|
1021
|
-
|
|
1022
|
-
|
|
1023
|
-
|
|
1024
|
-
|
|
1025
|
-
|
|
1026
|
-
|
|
1027
|
-
|
|
1028
|
-
|
|
1029
|
-
|
|
1030
|
-
|
|
1031
|
-
|
|
1032
|
-
|
|
1033
|
-
|
|
1034
|
-
|
|
1035
|
-
|
|
1036
|
-
|
|
1037
|
-
|
|
1038
|
-
|
|
1039
|
-
|
|
1040
|
-
|
|
1041
|
-
|
|
1042
|
-
|
|
1043
|
-
|
|
1044
|
-
|
|
1045
|
-
|
|
1046
|
-
|
|
1047
|
-
* @example
|
|
1048
|
-
* // Create independent copy
|
|
1049
|
-
* const trie = new Trie(['hello', 'world']);
|
|
1050
|
-
* const copy = trie.clone();
|
|
1051
|
-
* copy.delete('hello');
|
|
1052
|
-
* console.log(trie.has('hello')); // true;
|
|
608
|
+
* @example
|
|
609
|
+
* // Create independent copy
|
|
610
|
+
* const trie = new Trie(['hello', 'world']);
|
|
611
|
+
* const copy = trie.clone();
|
|
612
|
+
* copy.delete('hello');
|
|
613
|
+
* console.log(trie.has('hello')); // true;
|
|
1053
614
|
*/
|
|
1054
|
-
|
|
1055
615
|
clone(): this {
|
|
1056
616
|
const next = this._createInstance();
|
|
1057
617
|
for (const x of this) next.add(x);
|
|
@@ -1064,52 +624,12 @@ export class Trie<R = any> extends IterableElementBase<string, R> {
|
|
|
1064
624
|
* @param predicate - Predicate (word, index, trie) → boolean to keep word.
|
|
1065
625
|
* @param [thisArg] - Value for `this` inside the predicate.
|
|
1066
626
|
* @returns A new trie containing words that satisfy the predicate.
|
|
1067
|
-
|
|
1068
|
-
|
|
1069
|
-
|
|
1070
|
-
|
|
1071
|
-
|
|
1072
|
-
|
|
1073
|
-
|
|
1074
|
-
|
|
1075
|
-
|
|
1076
|
-
|
|
1077
|
-
|
|
1078
|
-
|
|
1079
|
-
|
|
1080
|
-
|
|
1081
|
-
|
|
1082
|
-
|
|
1083
|
-
|
|
1084
|
-
|
|
1085
|
-
|
|
1086
|
-
|
|
1087
|
-
|
|
1088
|
-
|
|
1089
|
-
|
|
1090
|
-
|
|
1091
|
-
|
|
1092
|
-
|
|
1093
|
-
|
|
1094
|
-
|
|
1095
|
-
|
|
1096
|
-
|
|
1097
|
-
|
|
1098
|
-
|
|
1099
|
-
|
|
1100
|
-
|
|
1101
|
-
|
|
1102
|
-
|
|
1103
|
-
|
|
1104
|
-
|
|
1105
|
-
|
|
1106
|
-
* @example
|
|
1107
|
-
* // Filter words
|
|
1108
|
-
* const trie = new Trie(['cat', 'car', 'dog', 'card']);
|
|
1109
|
-
* const result = trie.filter(w => w.startsWith('ca'));
|
|
1110
|
-
* console.log(result.size); // 3;
|
|
627
|
+
* @example
|
|
628
|
+
* // Filter words
|
|
629
|
+
* const trie = new Trie(['cat', 'car', 'dog', 'card']);
|
|
630
|
+
* const result = trie.filter(w => w.startsWith('ca'));
|
|
631
|
+
* console.log(result.size); // 3;
|
|
1111
632
|
*/
|
|
1112
|
-
|
|
1113
633
|
filter(predicate: ElementCallback<string, R, boolean>, thisArg?: unknown): this {
|
|
1114
634
|
const results = this._createInstance();
|
|
1115
635
|
let index = 0;
|
|
@@ -1122,52 +642,13 @@ export class Trie<R = any> extends IterableElementBase<string, R> {
|
|
|
1122
642
|
return results;
|
|
1123
643
|
}
|
|
1124
644
|
|
|
1125
|
-
|
|
645
|
+
/**
|
|
1126
646
|
* Transform words
|
|
1127
|
-
|
|
1128
|
-
|
|
1129
|
-
|
|
1130
|
-
|
|
1131
|
-
|
|
1132
|
-
|
|
1133
|
-
|
|
1134
|
-
|
|
1135
|
-
|
|
1136
|
-
|
|
1137
|
-
|
|
1138
|
-
|
|
1139
|
-
|
|
1140
|
-
|
|
1141
|
-
|
|
1142
|
-
|
|
1143
|
-
|
|
1144
|
-
|
|
1145
|
-
|
|
1146
|
-
|
|
1147
|
-
|
|
1148
|
-
|
|
1149
|
-
|
|
1150
|
-
|
|
1151
|
-
|
|
1152
|
-
|
|
1153
|
-
|
|
1154
|
-
|
|
1155
|
-
|
|
1156
|
-
|
|
1157
|
-
|
|
1158
|
-
|
|
1159
|
-
|
|
1160
|
-
|
|
1161
|
-
|
|
1162
|
-
|
|
1163
|
-
|
|
1164
|
-
|
|
1165
|
-
|
|
1166
|
-
* @example
|
|
1167
|
-
* // Transform words
|
|
1168
|
-
* const trie = new Trie(['hello', 'world']);
|
|
1169
|
-
* const upper = trie.map(w => w.toUpperCase());
|
|
1170
|
-
* console.log(upper.has('HELLO')); // true;
|
|
647
|
+
* @example
|
|
648
|
+
* // Transform words
|
|
649
|
+
* const trie = new Trie(['hello', 'world']);
|
|
650
|
+
* const upper = trie.map(w => w.toUpperCase());
|
|
651
|
+
* console.log(upper.has('HELLO')); // true;
|
|
1171
652
|
*/
|
|
1172
653
|
map<RM>(callback: ElementCallback<string, R, string>, options?: TrieOptions<RM>, thisArg?: unknown): Trie<RM>;
|
|
1173
654
|
|
|
@@ -1181,13 +662,11 @@ export class Trie<R = any> extends IterableElementBase<string, R> {
|
|
|
1181
662
|
* @param [thisArg] - Value for `this` inside the callback.
|
|
1182
663
|
* @returns A new Trie constructed from mapped words.
|
|
1183
664
|
*/
|
|
1184
|
-
|
|
1185
665
|
map<EM, RM>(
|
|
1186
666
|
callback: ElementCallback<string, R, EM>,
|
|
1187
667
|
options?: TrieOptions<RM>,
|
|
1188
668
|
thisArg?: unknown
|
|
1189
669
|
): IterableElementBase<EM, RM>;
|
|
1190
|
-
|
|
1191
670
|
map<EM, RM>(callback: ElementCallback<string, R, EM>, options?: TrieOptions<RM>, thisArg?: unknown): any {
|
|
1192
671
|
const newTrie = this._createLike<RM>([], options);
|
|
1193
672
|
let i = 0;
|
|
@@ -1208,7 +687,6 @@ export class Trie<R = any> extends IterableElementBase<string, R> {
|
|
|
1208
687
|
* @param [thisArg] - Value for `this` inside the callback.
|
|
1209
688
|
* @returns A new trie with mapped words.
|
|
1210
689
|
*/
|
|
1211
|
-
|
|
1212
690
|
mapSame(callback: ElementCallback<string, R, string>, thisArg?: unknown): this {
|
|
1213
691
|
const next = this._createInstance();
|
|
1214
692
|
let i = 0;
|
|
@@ -1225,12 +703,8 @@ export class Trie<R = any> extends IterableElementBase<string, R> {
|
|
|
1225
703
|
* @param [options] - Options forwarded to the constructor.
|
|
1226
704
|
* @returns An empty like-kind trie instance.
|
|
1227
705
|
*/
|
|
1228
|
-
|
|
1229
706
|
protected _createInstance(options?: TrieOptions<R>): this {
|
|
1230
|
-
const Ctor = this.constructor as new (
|
|
1231
|
-
elements?: Iterable<string> | Iterable<R>,
|
|
1232
|
-
options?: TrieOptions<R>
|
|
1233
|
-
) => this;
|
|
707
|
+
const Ctor = this.constructor as new (elements?: Iterable<string> | Iterable<R>, options?: TrieOptions<R>) => this;
|
|
1234
708
|
return new Ctor([], {
|
|
1235
709
|
toElementFn: this.toElementFn,
|
|
1236
710
|
caseSensitive: this.caseSensitive,
|
|
@@ -1246,7 +720,6 @@ export class Trie<R = any> extends IterableElementBase<string, R> {
|
|
|
1246
720
|
* @param [options] - Options forwarded to the constructor.
|
|
1247
721
|
* @returns A like-kind Trie instance.
|
|
1248
722
|
*/
|
|
1249
|
-
|
|
1250
723
|
protected _createLike<RM>(elements: Iterable<string> | Iterable<RM> = [], options?: TrieOptions<RM>): Trie<RM> {
|
|
1251
724
|
const Ctor = this.constructor as new (
|
|
1252
725
|
elements?: Iterable<string> | Iterable<RM>,
|
|
@@ -1262,7 +735,6 @@ export class Trie<R = any> extends IterableElementBase<string, R> {
|
|
|
1262
735
|
* @param [options] - Options forwarded to the constructor.
|
|
1263
736
|
* @returns An empty like-kind Trie instance.
|
|
1264
737
|
*/
|
|
1265
|
-
|
|
1266
738
|
protected _spawnLike<RM>(options?: TrieOptions<RM>): Trie<RM> {
|
|
1267
739
|
return this._createLike<RM>([], options);
|
|
1268
740
|
}
|
|
@@ -1272,7 +744,6 @@ export class Trie<R = any> extends IterableElementBase<string, R> {
|
|
|
1272
744
|
* @remarks Time O(ΣL), Space O(H)
|
|
1273
745
|
* @returns Iterator of words.
|
|
1274
746
|
*/
|
|
1275
|
-
|
|
1276
747
|
protected *_getIterator(): IterableIterator<string> {
|
|
1277
748
|
function* _dfs(node: TrieNode, path: string): IterableIterator<string> {
|
|
1278
749
|
if (node.isEnd) {
|
|
@@ -1292,7 +763,6 @@ export class Trie<R = any> extends IterableElementBase<string, R> {
|
|
|
1292
763
|
* @param str - Input string to normalize.
|
|
1293
764
|
* @returns Normalized string based on caseSensitive.
|
|
1294
765
|
*/
|
|
1295
|
-
|
|
1296
766
|
protected _caseProcess(str: string) {
|
|
1297
767
|
if (!this._caseSensitive) {
|
|
1298
768
|
str = str.toLowerCase();
|