trie-typed 2.4.5 → 2.5.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/README.md +0 -49
- package/dist/cjs/index.cjs +302 -105
- package/dist/cjs/index.cjs.map +1 -1
- package/dist/cjs-legacy/index.cjs +301 -104
- package/dist/cjs-legacy/index.cjs.map +1 -1
- package/dist/esm/index.mjs +302 -105
- package/dist/esm/index.mjs.map +1 -1
- package/dist/esm-legacy/index.mjs +301 -104
- package/dist/esm-legacy/index.mjs.map +1 -1
- package/dist/types/data-structures/base/iterable-element-base.d.ts +1 -1
- package/dist/types/data-structures/binary-tree/avl-tree.d.ts +128 -51
- package/dist/types/data-structures/binary-tree/binary-indexed-tree.d.ts +210 -164
- package/dist/types/data-structures/binary-tree/binary-tree.d.ts +429 -78
- package/dist/types/data-structures/binary-tree/bst.d.ts +311 -28
- package/dist/types/data-structures/binary-tree/red-black-tree.d.ts +212 -32
- package/dist/types/data-structures/binary-tree/segment-tree.d.ts +218 -152
- package/dist/types/data-structures/binary-tree/tree-map.d.ts +1281 -5
- package/dist/types/data-structures/binary-tree/tree-multi-map.d.ts +1087 -201
- package/dist/types/data-structures/binary-tree/tree-multi-set.d.ts +858 -65
- package/dist/types/data-structures/binary-tree/tree-set.d.ts +1133 -5
- package/dist/types/data-structures/graph/directed-graph.d.ts +219 -47
- package/dist/types/data-structures/graph/map-graph.d.ts +59 -1
- package/dist/types/data-structures/graph/undirected-graph.d.ts +204 -59
- package/dist/types/data-structures/hash/hash-map.d.ts +230 -77
- package/dist/types/data-structures/heap/heap.d.ts +287 -99
- package/dist/types/data-structures/heap/max-heap.d.ts +46 -0
- package/dist/types/data-structures/heap/min-heap.d.ts +59 -0
- package/dist/types/data-structures/linked-list/doubly-linked-list.d.ts +286 -44
- package/dist/types/data-structures/linked-list/singly-linked-list.d.ts +278 -65
- package/dist/types/data-structures/linked-list/skip-linked-list.d.ts +415 -12
- package/dist/types/data-structures/matrix/matrix.d.ts +331 -0
- package/dist/types/data-structures/priority-queue/max-priority-queue.d.ts +57 -0
- package/dist/types/data-structures/priority-queue/min-priority-queue.d.ts +60 -0
- package/dist/types/data-structures/priority-queue/priority-queue.d.ts +60 -0
- package/dist/types/data-structures/queue/deque.d.ts +272 -65
- package/dist/types/data-structures/queue/queue.d.ts +211 -42
- package/dist/types/data-structures/stack/stack.d.ts +174 -32
- package/dist/types/data-structures/trie/trie.d.ts +213 -43
- package/dist/types/types/data-structures/binary-tree/segment-tree.d.ts +1 -1
- package/dist/types/types/data-structures/linked-list/skip-linked-list.d.ts +1 -4
- package/dist/umd/trie-typed.js +299 -102
- package/dist/umd/trie-typed.js.map +1 -1
- package/dist/umd/trie-typed.min.js +1 -1
- package/dist/umd/trie-typed.min.js.map +1 -1
- package/package.json +2 -2
- package/src/data-structures/base/iterable-element-base.ts +4 -5
- package/src/data-structures/binary-tree/avl-tree.ts +134 -51
- package/src/data-structures/binary-tree/binary-indexed-tree.ts +302 -247
- package/src/data-structures/binary-tree/binary-tree.ts +429 -79
- package/src/data-structures/binary-tree/bst.ts +335 -34
- package/src/data-structures/binary-tree/red-black-tree.ts +290 -97
- package/src/data-structures/binary-tree/segment-tree.ts +372 -248
- package/src/data-structures/binary-tree/tree-map.ts +1284 -6
- package/src/data-structures/binary-tree/tree-multi-map.ts +1094 -211
- package/src/data-structures/binary-tree/tree-multi-set.ts +858 -65
- package/src/data-structures/binary-tree/tree-set.ts +1136 -9
- package/src/data-structures/graph/directed-graph.ts +219 -47
- package/src/data-structures/graph/map-graph.ts +59 -1
- package/src/data-structures/graph/undirected-graph.ts +204 -59
- package/src/data-structures/hash/hash-map.ts +230 -77
- package/src/data-structures/heap/heap.ts +287 -99
- package/src/data-structures/heap/max-heap.ts +46 -0
- package/src/data-structures/heap/min-heap.ts +59 -0
- package/src/data-structures/linked-list/doubly-linked-list.ts +286 -44
- package/src/data-structures/linked-list/singly-linked-list.ts +278 -65
- package/src/data-structures/linked-list/skip-linked-list.ts +689 -90
- package/src/data-structures/matrix/matrix.ts +416 -12
- package/src/data-structures/priority-queue/max-priority-queue.ts +57 -0
- package/src/data-structures/priority-queue/min-priority-queue.ts +60 -0
- package/src/data-structures/priority-queue/priority-queue.ts +60 -0
- package/src/data-structures/queue/deque.ts +272 -65
- package/src/data-structures/queue/queue.ts +211 -42
- package/src/data-structures/stack/stack.ts +174 -32
- package/src/data-structures/trie/trie.ts +213 -43
- package/src/types/data-structures/binary-tree/segment-tree.ts +1 -1
- package/src/types/data-structures/linked-list/skip-linked-list.ts +2 -1
package/README.md
CHANGED
|
@@ -35,36 +35,6 @@ yarn add trie-typed
|
|
|
35
35
|
|
|
36
36
|
[//]: # (No deletion!!! Start of Example Replace Section)
|
|
37
37
|
|
|
38
|
-
### basic Trie creation and add words
|
|
39
|
-
```typescript
|
|
40
|
-
// Create a simple Trie with initial words
|
|
41
|
-
const trie = new Trie(['apple', 'app', 'apply']);
|
|
42
|
-
|
|
43
|
-
// Verify size
|
|
44
|
-
console.log(trie.size); // 3;
|
|
45
|
-
|
|
46
|
-
// Check if words exist
|
|
47
|
-
console.log(trie.has('apple')); // true;
|
|
48
|
-
console.log(trie.has('app')); // true;
|
|
49
|
-
|
|
50
|
-
// Add a new word
|
|
51
|
-
trie.add('application');
|
|
52
|
-
console.log(trie.size); // 4;
|
|
53
|
-
```
|
|
54
|
-
|
|
55
|
-
### Trie getWords and prefix search
|
|
56
|
-
```typescript
|
|
57
|
-
const trie = new Trie(['apple', 'app', 'apply', 'application', 'apricot']);
|
|
58
|
-
|
|
59
|
-
// Get all words with prefix 'app'
|
|
60
|
-
const appWords = trie.getWords('app');
|
|
61
|
-
console.log(appWords); // contains 'app';
|
|
62
|
-
console.log(appWords); // contains 'apple';
|
|
63
|
-
console.log(appWords); // contains 'apply';
|
|
64
|
-
console.log(appWords); // contains 'application';
|
|
65
|
-
expect(appWords).not.toContain('apricot');
|
|
66
|
-
```
|
|
67
|
-
|
|
68
38
|
### Trie isPrefix and isAbsolutePrefix checks
|
|
69
39
|
```typescript
|
|
70
40
|
const trie = new Trie(['tree', 'trial', 'trick', 'trip', 'trie']);
|
|
@@ -82,25 +52,6 @@ yarn add trie-typed
|
|
|
82
52
|
console.log(trie.size); // 5;
|
|
83
53
|
```
|
|
84
54
|
|
|
85
|
-
### Trie delete and iteration
|
|
86
|
-
```typescript
|
|
87
|
-
const trie = new Trie(['car', 'card', 'care', 'careful', 'can', 'cat']);
|
|
88
|
-
|
|
89
|
-
// Delete a word
|
|
90
|
-
trie.delete('card');
|
|
91
|
-
console.log(trie.has('card')); // false;
|
|
92
|
-
|
|
93
|
-
// Word with same prefix still exists
|
|
94
|
-
console.log(trie.has('care')); // true;
|
|
95
|
-
|
|
96
|
-
// Size decreased
|
|
97
|
-
console.log(trie.size); // 5;
|
|
98
|
-
|
|
99
|
-
// Iterate through all words
|
|
100
|
-
const allWords = [...trie];
|
|
101
|
-
console.log(allWords.length); // 5;
|
|
102
|
-
```
|
|
103
|
-
|
|
104
55
|
### Trie for autocomplete search index
|
|
105
56
|
```typescript
|
|
106
57
|
// Trie is perfect for autocomplete: O(m + k) where m is prefix length, k is results
|
package/dist/cjs/index.cjs
CHANGED
|
@@ -3,55 +3,6 @@
|
|
|
3
3
|
var __defProp = Object.defineProperty;
|
|
4
4
|
var __name = (target, value) => __defProp(target, "name", { value, configurable: true });
|
|
5
5
|
|
|
6
|
-
// src/common/error.ts
|
|
7
|
-
var ERR = {
|
|
8
|
-
// Range / index
|
|
9
|
-
indexOutOfRange: /* @__PURE__ */ __name((index, min, max, ctx) => `${ctx ? ctx + ": " : ""}Index ${index} is out of range [${min}, ${max}].`, "indexOutOfRange"),
|
|
10
|
-
invalidIndex: /* @__PURE__ */ __name((ctx) => `${ctx ? ctx + ": " : ""}Index must be an integer.`, "invalidIndex"),
|
|
11
|
-
// Type / argument
|
|
12
|
-
invalidArgument: /* @__PURE__ */ __name((reason, ctx) => `${ctx ? ctx + ": " : ""}${reason}`, "invalidArgument"),
|
|
13
|
-
comparatorRequired: /* @__PURE__ */ __name((ctx) => `${ctx ? ctx + ": " : ""}Comparator is required for non-number/non-string/non-Date keys.`, "comparatorRequired"),
|
|
14
|
-
invalidKey: /* @__PURE__ */ __name((reason, ctx) => `${ctx ? ctx + ": " : ""}${reason}`, "invalidKey"),
|
|
15
|
-
notAFunction: /* @__PURE__ */ __name((name, ctx) => `${ctx ? ctx + ": " : ""}${name} must be a function.`, "notAFunction"),
|
|
16
|
-
invalidEntry: /* @__PURE__ */ __name((ctx) => `${ctx ? ctx + ": " : ""}Each entry must be a [key, value] tuple.`, "invalidEntry"),
|
|
17
|
-
invalidNaN: /* @__PURE__ */ __name((ctx) => `${ctx ? ctx + ": " : ""}NaN is not a valid key.`, "invalidNaN"),
|
|
18
|
-
invalidDate: /* @__PURE__ */ __name((ctx) => `${ctx ? ctx + ": " : ""}Invalid Date key.`, "invalidDate"),
|
|
19
|
-
reduceEmpty: /* @__PURE__ */ __name((ctx) => `${ctx ? ctx + ": " : ""}Reduce of empty structure with no initial value.`, "reduceEmpty"),
|
|
20
|
-
callbackReturnType: /* @__PURE__ */ __name((expected, got, ctx) => `${ctx ? ctx + ": " : ""}Callback must return ${expected}; got ${got}.`, "callbackReturnType"),
|
|
21
|
-
// State / operation
|
|
22
|
-
invalidOperation: /* @__PURE__ */ __name((reason, ctx) => `${ctx ? ctx + ": " : ""}${reason}`, "invalidOperation"),
|
|
23
|
-
// Matrix
|
|
24
|
-
matrixDimensionMismatch: /* @__PURE__ */ __name((op) => `Matrix: Dimensions must be compatible for ${op}.`, "matrixDimensionMismatch"),
|
|
25
|
-
matrixSingular: /* @__PURE__ */ __name(() => "Matrix: Singular matrix, inverse does not exist.", "matrixSingular"),
|
|
26
|
-
matrixNotSquare: /* @__PURE__ */ __name(() => "Matrix: Must be square for inversion.", "matrixNotSquare"),
|
|
27
|
-
matrixNotRectangular: /* @__PURE__ */ __name(() => "Matrix: Must be rectangular for transposition.", "matrixNotRectangular"),
|
|
28
|
-
matrixRowMismatch: /* @__PURE__ */ __name((expected, got) => `Matrix: Expected row length ${expected}, but got ${got}.`, "matrixRowMismatch")
|
|
29
|
-
};
|
|
30
|
-
|
|
31
|
-
// src/common/index.ts
|
|
32
|
-
var DFSOperation = /* @__PURE__ */ ((DFSOperation2) => {
|
|
33
|
-
DFSOperation2[DFSOperation2["VISIT"] = 0] = "VISIT";
|
|
34
|
-
DFSOperation2[DFSOperation2["PROCESS"] = 1] = "PROCESS";
|
|
35
|
-
return DFSOperation2;
|
|
36
|
-
})(DFSOperation || {});
|
|
37
|
-
var Range = class {
|
|
38
|
-
constructor(low, high, includeLow = true, includeHigh = true) {
|
|
39
|
-
this.low = low;
|
|
40
|
-
this.high = high;
|
|
41
|
-
this.includeLow = includeLow;
|
|
42
|
-
this.includeHigh = includeHigh;
|
|
43
|
-
}
|
|
44
|
-
static {
|
|
45
|
-
__name(this, "Range");
|
|
46
|
-
}
|
|
47
|
-
// Determine whether a key is within the range
|
|
48
|
-
isInRange(key, comparator) {
|
|
49
|
-
const lowCheck = this.includeLow ? comparator(key, this.low) >= 0 : comparator(key, this.low) > 0;
|
|
50
|
-
const highCheck = this.includeHigh ? comparator(key, this.high) <= 0 : comparator(key, this.high) < 0;
|
|
51
|
-
return lowCheck && highCheck;
|
|
52
|
-
}
|
|
53
|
-
};
|
|
54
|
-
|
|
55
6
|
// src/data-structures/base/iterable-element-base.ts
|
|
56
7
|
var IterableElementBase = class {
|
|
57
8
|
static {
|
|
@@ -70,7 +21,7 @@ var IterableElementBase = class {
|
|
|
70
21
|
if (options) {
|
|
71
22
|
const { toElementFn } = options;
|
|
72
23
|
if (typeof toElementFn === "function") this._toElementFn = toElementFn;
|
|
73
|
-
else if (toElementFn) throw new TypeError(
|
|
24
|
+
else if (toElementFn) throw new TypeError("toElementFn must be a function type");
|
|
74
25
|
}
|
|
75
26
|
}
|
|
76
27
|
/**
|
|
@@ -233,7 +184,7 @@ var IterableElementBase = class {
|
|
|
233
184
|
acc = initialValue;
|
|
234
185
|
} else {
|
|
235
186
|
const first = iter.next();
|
|
236
|
-
if (first.done) throw new TypeError(
|
|
187
|
+
if (first.done) throw new TypeError("Reduce of empty structure with no initial value");
|
|
237
188
|
acc = first.value;
|
|
238
189
|
index = 1;
|
|
239
190
|
}
|
|
@@ -275,6 +226,55 @@ var IterableElementBase = class {
|
|
|
275
226
|
}
|
|
276
227
|
};
|
|
277
228
|
|
|
229
|
+
// src/common/error.ts
|
|
230
|
+
var ERR = {
|
|
231
|
+
// Range / index
|
|
232
|
+
indexOutOfRange: /* @__PURE__ */ __name((index, min, max, ctx) => `${ctx ? ctx + ": " : ""}Index ${index} is out of range [${min}, ${max}].`, "indexOutOfRange"),
|
|
233
|
+
invalidIndex: /* @__PURE__ */ __name((ctx) => `${ctx ? ctx + ": " : ""}Index must be an integer.`, "invalidIndex"),
|
|
234
|
+
// Type / argument
|
|
235
|
+
invalidArgument: /* @__PURE__ */ __name((reason, ctx) => `${ctx ? ctx + ": " : ""}${reason}`, "invalidArgument"),
|
|
236
|
+
comparatorRequired: /* @__PURE__ */ __name((ctx) => `${ctx ? ctx + ": " : ""}Comparator is required for non-number/non-string/non-Date keys.`, "comparatorRequired"),
|
|
237
|
+
invalidKey: /* @__PURE__ */ __name((reason, ctx) => `${ctx ? ctx + ": " : ""}${reason}`, "invalidKey"),
|
|
238
|
+
notAFunction: /* @__PURE__ */ __name((name, ctx) => `${ctx ? ctx + ": " : ""}${name} must be a function.`, "notAFunction"),
|
|
239
|
+
invalidEntry: /* @__PURE__ */ __name((ctx) => `${ctx ? ctx + ": " : ""}Each entry must be a [key, value] tuple.`, "invalidEntry"),
|
|
240
|
+
invalidNaN: /* @__PURE__ */ __name((ctx) => `${ctx ? ctx + ": " : ""}NaN is not a valid key.`, "invalidNaN"),
|
|
241
|
+
invalidDate: /* @__PURE__ */ __name((ctx) => `${ctx ? ctx + ": " : ""}Invalid Date key.`, "invalidDate"),
|
|
242
|
+
reduceEmpty: /* @__PURE__ */ __name((ctx) => `${ctx ? ctx + ": " : ""}Reduce of empty structure with no initial value.`, "reduceEmpty"),
|
|
243
|
+
callbackReturnType: /* @__PURE__ */ __name((expected, got, ctx) => `${ctx ? ctx + ": " : ""}Callback must return ${expected}; got ${got}.`, "callbackReturnType"),
|
|
244
|
+
// State / operation
|
|
245
|
+
invalidOperation: /* @__PURE__ */ __name((reason, ctx) => `${ctx ? ctx + ": " : ""}${reason}`, "invalidOperation"),
|
|
246
|
+
// Matrix
|
|
247
|
+
matrixDimensionMismatch: /* @__PURE__ */ __name((op) => `Matrix: Dimensions must be compatible for ${op}.`, "matrixDimensionMismatch"),
|
|
248
|
+
matrixSingular: /* @__PURE__ */ __name(() => "Matrix: Singular matrix, inverse does not exist.", "matrixSingular"),
|
|
249
|
+
matrixNotSquare: /* @__PURE__ */ __name(() => "Matrix: Must be square for inversion.", "matrixNotSquare"),
|
|
250
|
+
matrixNotRectangular: /* @__PURE__ */ __name(() => "Matrix: Must be rectangular for transposition.", "matrixNotRectangular"),
|
|
251
|
+
matrixRowMismatch: /* @__PURE__ */ __name((expected, got) => `Matrix: Expected row length ${expected}, but got ${got}.`, "matrixRowMismatch")
|
|
252
|
+
};
|
|
253
|
+
|
|
254
|
+
// src/common/index.ts
|
|
255
|
+
var DFSOperation = /* @__PURE__ */ ((DFSOperation2) => {
|
|
256
|
+
DFSOperation2[DFSOperation2["VISIT"] = 0] = "VISIT";
|
|
257
|
+
DFSOperation2[DFSOperation2["PROCESS"] = 1] = "PROCESS";
|
|
258
|
+
return DFSOperation2;
|
|
259
|
+
})(DFSOperation || {});
|
|
260
|
+
var Range = class {
|
|
261
|
+
constructor(low, high, includeLow = true, includeHigh = true) {
|
|
262
|
+
this.low = low;
|
|
263
|
+
this.high = high;
|
|
264
|
+
this.includeLow = includeLow;
|
|
265
|
+
this.includeHigh = includeHigh;
|
|
266
|
+
}
|
|
267
|
+
static {
|
|
268
|
+
__name(this, "Range");
|
|
269
|
+
}
|
|
270
|
+
// Determine whether a key is within the range
|
|
271
|
+
isInRange(key, comparator) {
|
|
272
|
+
const lowCheck = this.includeLow ? comparator(key, this.low) >= 0 : comparator(key, this.low) > 0;
|
|
273
|
+
const highCheck = this.includeHigh ? comparator(key, this.high) <= 0 : comparator(key, this.high) < 0;
|
|
274
|
+
return lowCheck && highCheck;
|
|
275
|
+
}
|
|
276
|
+
};
|
|
277
|
+
|
|
278
278
|
// src/data-structures/trie/trie.ts
|
|
279
279
|
var TrieNode = class {
|
|
280
280
|
static {
|
|
@@ -402,11 +402,37 @@ var Trie = class extends IterableElementBase {
|
|
|
402
402
|
return this._size;
|
|
403
403
|
}
|
|
404
404
|
/**
|
|
405
|
-
|
|
406
|
-
|
|
407
|
-
|
|
408
|
-
|
|
409
|
-
|
|
405
|
+
* Insert one word into the trie.
|
|
406
|
+
* @remarks Time O(L), Space O(L)
|
|
407
|
+
* @param word - Word to insert.
|
|
408
|
+
* @returns True if the word was newly added.
|
|
409
|
+
|
|
410
|
+
|
|
411
|
+
|
|
412
|
+
|
|
413
|
+
|
|
414
|
+
|
|
415
|
+
|
|
416
|
+
|
|
417
|
+
|
|
418
|
+
|
|
419
|
+
|
|
420
|
+
* @example
|
|
421
|
+
* // basic Trie creation and add words
|
|
422
|
+
* // Create a simple Trie with initial words
|
|
423
|
+
* const trie = new Trie(['apple', 'app', 'apply']);
|
|
424
|
+
*
|
|
425
|
+
* // Verify size
|
|
426
|
+
* console.log(trie.size); // 3;
|
|
427
|
+
*
|
|
428
|
+
* // Check if words exist
|
|
429
|
+
* console.log(trie.has('apple')); // true;
|
|
430
|
+
* console.log(trie.has('app')); // true;
|
|
431
|
+
*
|
|
432
|
+
* // Add a new word
|
|
433
|
+
* trie.add('application');
|
|
434
|
+
* console.log(trie.size); // 4;
|
|
435
|
+
*/
|
|
410
436
|
add(word) {
|
|
411
437
|
word = this._caseProcess(word);
|
|
412
438
|
let cur = this.root;
|
|
@@ -427,11 +453,26 @@ var Trie = class extends IterableElementBase {
|
|
|
427
453
|
return isNewWord;
|
|
428
454
|
}
|
|
429
455
|
/**
|
|
430
|
-
|
|
431
|
-
|
|
432
|
-
|
|
433
|
-
|
|
434
|
-
|
|
456
|
+
* Insert many words from an iterable.
|
|
457
|
+
* @remarks Time O(ΣL), Space O(ΣL)
|
|
458
|
+
* @param words - Iterable of strings (or raw records if toElementFn is provided).
|
|
459
|
+
* @returns Array of per-word 'added' flags.
|
|
460
|
+
|
|
461
|
+
|
|
462
|
+
|
|
463
|
+
|
|
464
|
+
|
|
465
|
+
|
|
466
|
+
|
|
467
|
+
|
|
468
|
+
* @example
|
|
469
|
+
* // Add multiple words
|
|
470
|
+
* const trie = new Trie();
|
|
471
|
+
* trie.addMany(['cat', 'car', 'card']);
|
|
472
|
+
* console.log(trie.has('cat')); // true;
|
|
473
|
+
* console.log(trie.has('car')); // true;
|
|
474
|
+
* console.log(trie.size); // 3;
|
|
475
|
+
*/
|
|
435
476
|
addMany(words) {
|
|
436
477
|
const ans = [];
|
|
437
478
|
for (const word of words) {
|
|
@@ -444,11 +485,29 @@ var Trie = class extends IterableElementBase {
|
|
|
444
485
|
return ans;
|
|
445
486
|
}
|
|
446
487
|
/**
|
|
447
|
-
|
|
448
|
-
|
|
449
|
-
|
|
450
|
-
|
|
451
|
-
|
|
488
|
+
* Check whether a word exists.
|
|
489
|
+
* @remarks Time O(L), Space O(1)
|
|
490
|
+
* @param word - Word to search for.
|
|
491
|
+
* @returns True if present.
|
|
492
|
+
|
|
493
|
+
|
|
494
|
+
|
|
495
|
+
|
|
496
|
+
|
|
497
|
+
|
|
498
|
+
|
|
499
|
+
|
|
500
|
+
|
|
501
|
+
|
|
502
|
+
|
|
503
|
+
* @example
|
|
504
|
+
* // Check if a word exists
|
|
505
|
+
* const dict = new Trie(['apple', 'app', 'application']);
|
|
506
|
+
*
|
|
507
|
+
* console.log(dict.has('app')); // true;
|
|
508
|
+
* console.log(dict.has('apple')); // true;
|
|
509
|
+
* console.log(dict.has('ap')); // false;
|
|
510
|
+
*/
|
|
452
511
|
has(word) {
|
|
453
512
|
word = this._caseProcess(word);
|
|
454
513
|
let cur = this.root;
|
|
@@ -460,28 +519,83 @@ var Trie = class extends IterableElementBase {
|
|
|
460
519
|
return cur.isEnd;
|
|
461
520
|
}
|
|
462
521
|
/**
|
|
463
|
-
|
|
464
|
-
|
|
465
|
-
|
|
466
|
-
|
|
522
|
+
* Check whether the trie is empty.
|
|
523
|
+
* @remarks Time O(1), Space O(1)
|
|
524
|
+
* @returns True if size is 0.
|
|
525
|
+
|
|
526
|
+
|
|
527
|
+
|
|
528
|
+
|
|
529
|
+
|
|
530
|
+
|
|
531
|
+
|
|
532
|
+
|
|
533
|
+
* @example
|
|
534
|
+
* // Check if empty
|
|
535
|
+
* const trie = new Trie();
|
|
536
|
+
* console.log(trie.isEmpty()); // true;
|
|
537
|
+
* trie.add('word');
|
|
538
|
+
* console.log(trie.isEmpty()); // false;
|
|
539
|
+
*/
|
|
467
540
|
isEmpty() {
|
|
468
541
|
return this._size === 0;
|
|
469
542
|
}
|
|
470
543
|
/**
|
|
471
|
-
|
|
472
|
-
|
|
473
|
-
|
|
474
|
-
|
|
544
|
+
* Remove all words and reset to a fresh root.
|
|
545
|
+
* @remarks Time O(1), Space O(1)
|
|
546
|
+
* @returns void
|
|
547
|
+
|
|
548
|
+
|
|
549
|
+
|
|
550
|
+
|
|
551
|
+
|
|
552
|
+
|
|
553
|
+
|
|
554
|
+
|
|
555
|
+
* @example
|
|
556
|
+
* // Remove all words
|
|
557
|
+
* const trie = new Trie(['a', 'b', 'c']);
|
|
558
|
+
* trie.clear();
|
|
559
|
+
* console.log(trie.isEmpty()); // true;
|
|
560
|
+
*/
|
|
475
561
|
clear() {
|
|
476
562
|
this._size = 0;
|
|
477
563
|
this._root = new TrieNode("");
|
|
478
564
|
}
|
|
479
565
|
/**
|
|
480
|
-
|
|
481
|
-
|
|
482
|
-
|
|
483
|
-
|
|
484
|
-
|
|
566
|
+
* Delete one word if present.
|
|
567
|
+
* @remarks Time O(L), Space O(1)
|
|
568
|
+
* @param word - Word to delete.
|
|
569
|
+
* @returns True if a word was removed.
|
|
570
|
+
|
|
571
|
+
|
|
572
|
+
|
|
573
|
+
|
|
574
|
+
|
|
575
|
+
|
|
576
|
+
|
|
577
|
+
|
|
578
|
+
|
|
579
|
+
|
|
580
|
+
|
|
581
|
+
* @example
|
|
582
|
+
* // Trie delete and iteration
|
|
583
|
+
* const trie = new Trie(['car', 'card', 'care', 'careful', 'can', 'cat']);
|
|
584
|
+
*
|
|
585
|
+
* // Delete a word
|
|
586
|
+
* trie.delete('card');
|
|
587
|
+
* console.log(trie.has('card')); // false;
|
|
588
|
+
*
|
|
589
|
+
* // Word with same prefix still exists
|
|
590
|
+
* console.log(trie.has('care')); // true;
|
|
591
|
+
*
|
|
592
|
+
* // Size decreased
|
|
593
|
+
* console.log(trie.size); // 5;
|
|
594
|
+
*
|
|
595
|
+
* // Iterate through all words
|
|
596
|
+
* const allWords = [...trie];
|
|
597
|
+
* console.log(allWords.length); // 5;
|
|
598
|
+
*/
|
|
485
599
|
delete(word) {
|
|
486
600
|
word = this._caseProcess(word);
|
|
487
601
|
let isDeleted = false;
|
|
@@ -557,11 +671,29 @@ var Trie = class extends IterableElementBase {
|
|
|
557
671
|
return !cur.isEnd;
|
|
558
672
|
}
|
|
559
673
|
/**
|
|
560
|
-
|
|
561
|
-
|
|
562
|
-
|
|
563
|
-
|
|
564
|
-
|
|
674
|
+
* Check whether any word starts with input.
|
|
675
|
+
* @remarks Time O(L), Space O(1)
|
|
676
|
+
* @param input - String to test as prefix.
|
|
677
|
+
* @returns True if input matches a path from root.
|
|
678
|
+
|
|
679
|
+
|
|
680
|
+
|
|
681
|
+
|
|
682
|
+
|
|
683
|
+
|
|
684
|
+
|
|
685
|
+
|
|
686
|
+
|
|
687
|
+
|
|
688
|
+
|
|
689
|
+
* @example
|
|
690
|
+
* // Check if a prefix exists
|
|
691
|
+
* const trie = new Trie(['hello', 'help', 'world']);
|
|
692
|
+
*
|
|
693
|
+
* console.log(trie.hasPrefix('hel')); // true;
|
|
694
|
+
* console.log(trie.hasPrefix('wor')); // true;
|
|
695
|
+
* console.log(trie.hasPrefix('xyz')); // false;
|
|
696
|
+
*/
|
|
565
697
|
hasPrefix(input) {
|
|
566
698
|
input = this._caseProcess(input);
|
|
567
699
|
let cur = this.root;
|
|
@@ -592,10 +724,26 @@ var Trie = class extends IterableElementBase {
|
|
|
592
724
|
return commonPre === input;
|
|
593
725
|
}
|
|
594
726
|
/**
|
|
595
|
-
|
|
596
|
-
|
|
597
|
-
|
|
598
|
-
|
|
727
|
+
* Return the longest common prefix among all words.
|
|
728
|
+
* @remarks Time O(H), Space O(1)
|
|
729
|
+
* @returns The longest common prefix string.
|
|
730
|
+
|
|
731
|
+
|
|
732
|
+
|
|
733
|
+
|
|
734
|
+
|
|
735
|
+
|
|
736
|
+
|
|
737
|
+
|
|
738
|
+
|
|
739
|
+
|
|
740
|
+
|
|
741
|
+
* @example
|
|
742
|
+
* // Find shared prefix
|
|
743
|
+
* const trie = new Trie(['flower', 'flow', 'flight']);
|
|
744
|
+
*
|
|
745
|
+
* console.log(trie.getLongestCommonPrefix()); // 'fl';
|
|
746
|
+
*/
|
|
599
747
|
getLongestCommonPrefix() {
|
|
600
748
|
let commonPre = "";
|
|
601
749
|
const dfs = /* @__PURE__ */ __name((cur) => {
|
|
@@ -608,13 +756,35 @@ var Trie = class extends IterableElementBase {
|
|
|
608
756
|
return commonPre;
|
|
609
757
|
}
|
|
610
758
|
/**
|
|
611
|
-
|
|
612
|
-
|
|
613
|
-
|
|
614
|
-
|
|
615
|
-
|
|
616
|
-
|
|
617
|
-
|
|
759
|
+
* Collect words under a prefix up to a maximum count.
|
|
760
|
+
* @remarks Time O(K·L), Space O(K·L)
|
|
761
|
+
* @param [prefix] - Prefix to match; default empty string for root.
|
|
762
|
+
* @param [max] - Maximum number of words to return; default is Number.MAX_SAFE_INTEGER.
|
|
763
|
+
* @param [isAllWhenEmptyPrefix] - When true, collect from root even if prefix is empty.
|
|
764
|
+
* @returns Array of collected words (at most max).
|
|
765
|
+
|
|
766
|
+
|
|
767
|
+
|
|
768
|
+
|
|
769
|
+
|
|
770
|
+
|
|
771
|
+
|
|
772
|
+
|
|
773
|
+
|
|
774
|
+
|
|
775
|
+
|
|
776
|
+
* @example
|
|
777
|
+
* // Trie getWords and prefix search
|
|
778
|
+
* const trie = new Trie(['apple', 'app', 'apply', 'application', 'apricot']);
|
|
779
|
+
*
|
|
780
|
+
* // Get all words with prefix 'app'
|
|
781
|
+
* const appWords = trie.getWords('app');
|
|
782
|
+
* console.log(appWords); // contains 'app';
|
|
783
|
+
* console.log(appWords); // contains 'apple';
|
|
784
|
+
* console.log(appWords); // contains 'apply';
|
|
785
|
+
* console.log(appWords); // contains 'application';
|
|
786
|
+
* expect(appWords).not.toContain('apricot');
|
|
787
|
+
*/
|
|
618
788
|
getWords(prefix = "", max = Number.MAX_SAFE_INTEGER, isAllWhenEmptyPrefix = false) {
|
|
619
789
|
prefix = this._caseProcess(prefix);
|
|
620
790
|
const words = [];
|
|
@@ -645,22 +815,49 @@ var Trie = class extends IterableElementBase {
|
|
|
645
815
|
return words;
|
|
646
816
|
}
|
|
647
817
|
/**
|
|
648
|
-
|
|
649
|
-
|
|
650
|
-
|
|
651
|
-
|
|
818
|
+
* Deep clone this trie by iterating and inserting all words.
|
|
819
|
+
* @remarks Time O(ΣL), Space O(ΣL)
|
|
820
|
+
* @returns A new trie with the same words and options.
|
|
821
|
+
|
|
822
|
+
|
|
823
|
+
|
|
824
|
+
|
|
825
|
+
|
|
826
|
+
|
|
827
|
+
|
|
828
|
+
|
|
829
|
+
* @example
|
|
830
|
+
* // Create independent copy
|
|
831
|
+
* const trie = new Trie(['hello', 'world']);
|
|
832
|
+
* const copy = trie.clone();
|
|
833
|
+
* copy.delete('hello');
|
|
834
|
+
* console.log(trie.has('hello')); // true;
|
|
835
|
+
*/
|
|
652
836
|
clone() {
|
|
653
837
|
const next = this._createInstance();
|
|
654
838
|
for (const x of this) next.add(x);
|
|
655
839
|
return next;
|
|
656
840
|
}
|
|
657
841
|
/**
|
|
658
|
-
|
|
659
|
-
|
|
660
|
-
|
|
661
|
-
|
|
662
|
-
|
|
663
|
-
|
|
842
|
+
* Filter words into a new trie of the same class.
|
|
843
|
+
* @remarks Time O(ΣL), Space O(ΣL)
|
|
844
|
+
* @param predicate - Predicate (word, index, trie) → boolean to keep word.
|
|
845
|
+
* @param [thisArg] - Value for `this` inside the predicate.
|
|
846
|
+
* @returns A new trie containing words that satisfy the predicate.
|
|
847
|
+
|
|
848
|
+
|
|
849
|
+
|
|
850
|
+
|
|
851
|
+
|
|
852
|
+
|
|
853
|
+
|
|
854
|
+
|
|
855
|
+
* @example
|
|
856
|
+
* // Filter words
|
|
857
|
+
* const trie = new Trie(['cat', 'car', 'dog', 'card']);
|
|
858
|
+
* const result = trie.filter(w => w.startsWith('ca'));
|
|
859
|
+
* console.log(result.size); // 3;
|
|
860
|
+
*/
|
|
664
861
|
filter(predicate, thisArg) {
|
|
665
862
|
const results = this._createInstance();
|
|
666
863
|
let index = 0;
|