data-structure-typed 1.36.4 → 1.36.6
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 +2 -20
- package/.travis.yml +3 -4
- package/CHANGELOG.md +5 -1
- package/CONTRIBUTING.md +13 -0
- package/README.md +1 -0
- package/dist/data-structures/binary-tree/binary-tree.d.ts +3 -2
- package/dist/data-structures/binary-tree/binary-tree.js +10 -4
- package/dist/data-structures/binary-tree/binary-tree.js.map +1 -1
- package/dist/data-structures/tree/tree.js +3 -5
- package/dist/data-structures/tree/tree.js.map +1 -1
- package/dist/data-structures/trie/trie.d.ts +40 -21
- package/dist/data-structures/trie/trie.js +49 -30
- package/dist/data-structures/trie/trie.js.map +1 -1
- package/lib/data-structures/binary-tree/binary-tree.d.ts +3 -2
- package/lib/data-structures/binary-tree/binary-tree.js +10 -4
- package/lib/data-structures/tree/tree.js +3 -5
- package/lib/data-structures/trie/trie.d.ts +40 -21
- package/lib/data-structures/trie/trie.js +47 -28
- package/package.json +5 -5
- package/src/data-structures/binary-tree/binary-tree.ts +9 -5
- package/src/data-structures/tree/tree.ts +3 -5
- package/src/data-structures/trie/trie.ts +54 -29
- package/test/unit/data-structures/binary-tree/binary-tree.test.ts +13 -0
- package/test/unit/data-structures/heap/heap.test.ts +0 -1
- package/test/unit/data-structures/tree/tree.test.ts +2 -2
- package/test/unit/data-structures/trie/trie.test.ts +77 -7
- package/umd/bundle.min.js +1 -1
- package/umd/bundle.min.js.map +1 -1
- package/scripts/rename_clear_files.sh +0 -29
|
@@ -309,16 +309,22 @@ export class BinaryTree {
|
|
|
309
309
|
}
|
|
310
310
|
/**
|
|
311
311
|
* The function calculates the depth of a node in a binary tree.
|
|
312
|
-
* @param {N | BinaryTreeNodeKey | null}
|
|
312
|
+
* @param {N | BinaryTreeNodeKey | null} distNode - The `distNode` parameter can be any node of the tree
|
|
313
|
+
* @param {N | BinaryTreeNodeKey | null} beginRoot - The `beginRoot` parameter can be the predecessor node of distNode
|
|
313
314
|
* @returns the depth of the given node or binary tree.
|
|
314
315
|
*/
|
|
315
|
-
getDepth(beginRoot = this.root) {
|
|
316
|
+
getDepth(distNode, beginRoot = this.root) {
|
|
317
|
+
if (typeof distNode === 'number')
|
|
318
|
+
distNode = this.get(distNode, 'key');
|
|
316
319
|
if (typeof beginRoot === 'number')
|
|
317
320
|
beginRoot = this.get(beginRoot, 'key');
|
|
318
321
|
let depth = 0;
|
|
319
|
-
while (
|
|
322
|
+
while (distNode === null || distNode === void 0 ? void 0 : distNode.parent) {
|
|
323
|
+
if (distNode === beginRoot) {
|
|
324
|
+
return depth;
|
|
325
|
+
}
|
|
320
326
|
depth++;
|
|
321
|
-
|
|
327
|
+
distNode = distNode.parent;
|
|
322
328
|
}
|
|
323
329
|
return depth;
|
|
324
330
|
}
|
|
@@ -34,10 +34,8 @@ export class TreeNode {
|
|
|
34
34
|
}
|
|
35
35
|
}
|
|
36
36
|
getHeight() {
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
let maxDepth = 1;
|
|
40
|
-
if (beginRoot) {
|
|
37
|
+
let maxDepth = 0;
|
|
38
|
+
if (this) {
|
|
41
39
|
const bfs = (node, level) => {
|
|
42
40
|
if (level > maxDepth) {
|
|
43
41
|
maxDepth = level;
|
|
@@ -49,7 +47,7 @@ export class TreeNode {
|
|
|
49
47
|
}
|
|
50
48
|
}
|
|
51
49
|
};
|
|
52
|
-
bfs(
|
|
50
|
+
bfs(this, 0);
|
|
53
51
|
}
|
|
54
52
|
return maxDepth;
|
|
55
53
|
}
|
|
@@ -5,8 +5,12 @@
|
|
|
5
5
|
* @copyright Copyright (c) 2022 Tyler Zeng <zrwusa@gmail.com>
|
|
6
6
|
* @license MIT License
|
|
7
7
|
*/
|
|
8
|
+
/**
|
|
9
|
+
* TrieNode represents a node in the Trie data structure. It holds a character key, a map of children nodes,
|
|
10
|
+
* and a flag indicating whether it's the end of a word.
|
|
11
|
+
*/
|
|
8
12
|
export declare class TrieNode {
|
|
9
|
-
constructor(
|
|
13
|
+
constructor(key: string);
|
|
10
14
|
private _key;
|
|
11
15
|
get key(): string;
|
|
12
16
|
set key(v: string);
|
|
@@ -17,41 +21,56 @@ export declare class TrieNode {
|
|
|
17
21
|
get isEnd(): boolean;
|
|
18
22
|
set isEnd(v: boolean);
|
|
19
23
|
}
|
|
24
|
+
/**
|
|
25
|
+
* Trie represents a Trie data structure. It provides basic Trie operations and additional methods.
|
|
26
|
+
*/
|
|
20
27
|
export declare class Trie {
|
|
21
28
|
constructor(words?: string[], caseSensitive?: boolean);
|
|
22
29
|
protected _root: TrieNode;
|
|
23
30
|
get root(): TrieNode;
|
|
24
31
|
set root(v: TrieNode);
|
|
25
|
-
private _caseSensitive;
|
|
32
|
+
private readonly _caseSensitive;
|
|
33
|
+
/**
|
|
34
|
+
* Add a word to the Trie structure.
|
|
35
|
+
* @param {string} word - The word to add.
|
|
36
|
+
* @returns {boolean} True if the word was successfully added.
|
|
37
|
+
*/
|
|
26
38
|
add(word: string): boolean;
|
|
27
|
-
|
|
39
|
+
/**
|
|
40
|
+
* Check if the Trie contains a given word.
|
|
41
|
+
* @param {string} word - The word to check for.
|
|
42
|
+
* @returns {boolean} True if the word is present in the Trie.
|
|
43
|
+
*/
|
|
44
|
+
has(word: string): boolean;
|
|
28
45
|
private _caseProcess;
|
|
46
|
+
/**
|
|
47
|
+
* Remove a word from the Trie structure.
|
|
48
|
+
* @param{string} word - The word to remove.
|
|
49
|
+
* @returns {boolean} True if the word was successfully removed.
|
|
50
|
+
*/
|
|
29
51
|
remove(word: string): boolean;
|
|
30
52
|
getHeight(): number;
|
|
31
53
|
/**
|
|
32
|
-
*
|
|
33
|
-
* @param {string} input - The input
|
|
34
|
-
* @returns
|
|
54
|
+
* Check if a given input string has an absolute prefix in the Trie, meaning it's not a complete word.
|
|
55
|
+
* @param {string} input - The input string to check.
|
|
56
|
+
* @returns {boolean} True if it's an absolute prefix in the Trie.
|
|
35
57
|
*/
|
|
36
|
-
|
|
58
|
+
hasPurePrefix(input: string): boolean;
|
|
37
59
|
/**
|
|
38
|
-
*
|
|
39
|
-
* @param {string} input - The input
|
|
40
|
-
* @returns a
|
|
60
|
+
* Check if a given input string is a prefix of any existing word in the Trie, whether as an absolute prefix or a complete word.
|
|
61
|
+
* @param {string} input - The input string representing the prefix to check.
|
|
62
|
+
* @returns {boolean} True if it's a prefix in the Trie.
|
|
41
63
|
*/
|
|
42
|
-
|
|
64
|
+
hasPrefix(input: string): boolean;
|
|
43
65
|
/**
|
|
44
|
-
*
|
|
45
|
-
* @param {string} input - The input
|
|
46
|
-
* in the Trie
|
|
47
|
-
* @returns a boolean value indicating whether the input string is a common prefix in the Trie data structure.
|
|
66
|
+
* Check if the input string is a common prefix in the Trie, meaning it's a prefix shared by all words in the Trie.
|
|
67
|
+
* @param {string} input - The input string representing the common prefix to check for.
|
|
68
|
+
* @returns {boolean} True if it's a common prefix in the Trie.
|
|
48
69
|
*/
|
|
49
|
-
|
|
70
|
+
hasCommonPrefix(input: string): boolean;
|
|
50
71
|
/**
|
|
51
|
-
*
|
|
52
|
-
*
|
|
53
|
-
* @returns The function `getLongestCommonPrefix` returns a string, which is the longest common prefix found in the
|
|
54
|
-
* Trie.
|
|
72
|
+
* Get the longest common prefix among all the words stored in the Trie.
|
|
73
|
+
* @returns {string} The longest common prefix found in the Trie.
|
|
55
74
|
*/
|
|
56
75
|
getLongestCommonPrefix(): string;
|
|
57
76
|
/**
|
|
@@ -59,7 +78,7 @@ export declare class Trie {
|
|
|
59
78
|
* @param {string} prefix - The `prefix` parameter is a string that represents the prefix that we want to search for in the
|
|
60
79
|
* trie. It is an optional parameter, so if no prefix is provided, it will default to an empty string.
|
|
61
80
|
* @param {number} max - The max count of words will be found
|
|
62
|
-
* @returns an array of strings.
|
|
81
|
+
* @returns {string[]} an array of strings.
|
|
63
82
|
*/
|
|
64
83
|
getWords(prefix?: string, max?: number): string[];
|
|
65
84
|
}
|
|
@@ -5,9 +5,13 @@
|
|
|
5
5
|
* @copyright Copyright (c) 2022 Tyler Zeng <zrwusa@gmail.com>
|
|
6
6
|
* @license MIT License
|
|
7
7
|
*/
|
|
8
|
+
/**
|
|
9
|
+
* TrieNode represents a node in the Trie data structure. It holds a character key, a map of children nodes,
|
|
10
|
+
* and a flag indicating whether it's the end of a word.
|
|
11
|
+
*/
|
|
8
12
|
export class TrieNode {
|
|
9
|
-
constructor(
|
|
10
|
-
this._key =
|
|
13
|
+
constructor(key) {
|
|
14
|
+
this._key = key;
|
|
11
15
|
this._isEnd = false;
|
|
12
16
|
this._children = new Map();
|
|
13
17
|
}
|
|
@@ -30,6 +34,9 @@ export class TrieNode {
|
|
|
30
34
|
this._isEnd = v;
|
|
31
35
|
}
|
|
32
36
|
}
|
|
37
|
+
/**
|
|
38
|
+
* Trie represents a Trie data structure. It provides basic Trie operations and additional methods.
|
|
39
|
+
*/
|
|
33
40
|
export class Trie {
|
|
34
41
|
constructor(words, caseSensitive = true) {
|
|
35
42
|
this._root = new TrieNode('');
|
|
@@ -46,6 +53,11 @@ export class Trie {
|
|
|
46
53
|
set root(v) {
|
|
47
54
|
this._root = v;
|
|
48
55
|
}
|
|
56
|
+
/**
|
|
57
|
+
* Add a word to the Trie structure.
|
|
58
|
+
* @param {string} word - The word to add.
|
|
59
|
+
* @returns {boolean} True if the word was successfully added.
|
|
60
|
+
*/
|
|
49
61
|
add(word) {
|
|
50
62
|
word = this._caseProcess(word);
|
|
51
63
|
let cur = this.root;
|
|
@@ -60,10 +72,15 @@ export class Trie {
|
|
|
60
72
|
cur.isEnd = true;
|
|
61
73
|
return true;
|
|
62
74
|
}
|
|
63
|
-
|
|
64
|
-
|
|
75
|
+
/**
|
|
76
|
+
* Check if the Trie contains a given word.
|
|
77
|
+
* @param {string} word - The word to check for.
|
|
78
|
+
* @returns {boolean} True if the word is present in the Trie.
|
|
79
|
+
*/
|
|
80
|
+
has(word) {
|
|
81
|
+
word = this._caseProcess(word);
|
|
65
82
|
let cur = this.root;
|
|
66
|
-
for (const c of
|
|
83
|
+
for (const c of word) {
|
|
67
84
|
const nodeC = cur.children.get(c);
|
|
68
85
|
if (!nodeC)
|
|
69
86
|
return false;
|
|
@@ -71,12 +88,17 @@ export class Trie {
|
|
|
71
88
|
}
|
|
72
89
|
return cur.isEnd;
|
|
73
90
|
}
|
|
74
|
-
_caseProcess(
|
|
91
|
+
_caseProcess(str) {
|
|
75
92
|
if (!this._caseSensitive) {
|
|
76
|
-
|
|
93
|
+
str = str.toLowerCase(); // Convert str to lowercase if case-insensitive
|
|
77
94
|
}
|
|
78
|
-
return
|
|
95
|
+
return str;
|
|
79
96
|
}
|
|
97
|
+
/**
|
|
98
|
+
* Remove a word from the Trie structure.
|
|
99
|
+
* @param{string} word - The word to remove.
|
|
100
|
+
* @returns {boolean} True if the word was successfully removed.
|
|
101
|
+
*/
|
|
80
102
|
remove(word) {
|
|
81
103
|
word = this._caseProcess(word);
|
|
82
104
|
let isDeleted = false;
|
|
@@ -111,7 +133,7 @@ export class Trie {
|
|
|
111
133
|
}
|
|
112
134
|
getHeight() {
|
|
113
135
|
const beginRoot = this.root;
|
|
114
|
-
let maxDepth =
|
|
136
|
+
let maxDepth = 0;
|
|
115
137
|
if (beginRoot) {
|
|
116
138
|
const bfs = (node, level) => {
|
|
117
139
|
if (level > maxDepth) {
|
|
@@ -124,17 +146,17 @@ export class Trie {
|
|
|
124
146
|
}
|
|
125
147
|
}
|
|
126
148
|
};
|
|
127
|
-
bfs(beginRoot,
|
|
149
|
+
bfs(beginRoot, 0);
|
|
128
150
|
}
|
|
129
151
|
return maxDepth;
|
|
130
152
|
}
|
|
131
153
|
// --- start additional methods ---
|
|
132
154
|
/**
|
|
133
|
-
*
|
|
134
|
-
* @param {string} input - The input
|
|
135
|
-
* @returns
|
|
155
|
+
* Check if a given input string has an absolute prefix in the Trie, meaning it's not a complete word.
|
|
156
|
+
* @param {string} input - The input string to check.
|
|
157
|
+
* @returns {boolean} True if it's an absolute prefix in the Trie.
|
|
136
158
|
*/
|
|
137
|
-
|
|
159
|
+
hasPurePrefix(input) {
|
|
138
160
|
input = this._caseProcess(input);
|
|
139
161
|
let cur = this.root;
|
|
140
162
|
for (const c of input) {
|
|
@@ -146,11 +168,11 @@ export class Trie {
|
|
|
146
168
|
return !cur.isEnd;
|
|
147
169
|
}
|
|
148
170
|
/**
|
|
149
|
-
*
|
|
150
|
-
* @param {string} input - The input
|
|
151
|
-
* @returns a
|
|
171
|
+
* Check if a given input string is a prefix of any existing word in the Trie, whether as an absolute prefix or a complete word.
|
|
172
|
+
* @param {string} input - The input string representing the prefix to check.
|
|
173
|
+
* @returns {boolean} True if it's a prefix in the Trie.
|
|
152
174
|
*/
|
|
153
|
-
|
|
175
|
+
hasPrefix(input) {
|
|
154
176
|
input = this._caseProcess(input);
|
|
155
177
|
let cur = this.root;
|
|
156
178
|
for (const c of input) {
|
|
@@ -162,12 +184,11 @@ export class Trie {
|
|
|
162
184
|
return true;
|
|
163
185
|
}
|
|
164
186
|
/**
|
|
165
|
-
*
|
|
166
|
-
* @param {string} input - The input
|
|
167
|
-
* in the Trie
|
|
168
|
-
* @returns a boolean value indicating whether the input string is a common prefix in the Trie data structure.
|
|
187
|
+
* Check if the input string is a common prefix in the Trie, meaning it's a prefix shared by all words in the Trie.
|
|
188
|
+
* @param {string} input - The input string representing the common prefix to check for.
|
|
189
|
+
* @returns {boolean} True if it's a common prefix in the Trie.
|
|
169
190
|
*/
|
|
170
|
-
|
|
191
|
+
hasCommonPrefix(input) {
|
|
171
192
|
input = this._caseProcess(input);
|
|
172
193
|
let commonPre = '';
|
|
173
194
|
const dfs = (cur) => {
|
|
@@ -185,10 +206,8 @@ export class Trie {
|
|
|
185
206
|
return commonPre === input;
|
|
186
207
|
}
|
|
187
208
|
/**
|
|
188
|
-
*
|
|
189
|
-
*
|
|
190
|
-
* @returns The function `getLongestCommonPrefix` returns a string, which is the longest common prefix found in the
|
|
191
|
-
* Trie.
|
|
209
|
+
* Get the longest common prefix among all the words stored in the Trie.
|
|
210
|
+
* @returns {string} The longest common prefix found in the Trie.
|
|
192
211
|
*/
|
|
193
212
|
getLongestCommonPrefix() {
|
|
194
213
|
let commonPre = '';
|
|
@@ -209,7 +228,7 @@ export class Trie {
|
|
|
209
228
|
* @param {string} prefix - The `prefix` parameter is a string that represents the prefix that we want to search for in the
|
|
210
229
|
* trie. It is an optional parameter, so if no prefix is provided, it will default to an empty string.
|
|
211
230
|
* @param {number} max - The max count of words will be found
|
|
212
|
-
* @returns an array of strings.
|
|
231
|
+
* @returns {string[]} an array of strings.
|
|
213
232
|
*/
|
|
214
233
|
getWords(prefix = '', max = Number.MAX_SAFE_INTEGER) {
|
|
215
234
|
prefix = this._caseProcess(prefix);
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "data-structure-typed",
|
|
3
|
-
"version": "1.36.
|
|
3
|
+
"version": "1.36.6",
|
|
4
4
|
"description": "Data Structures of Javascript & TypeScript. Binary Tree, BST, Graph, Heap, Priority Queue, Linked List, Queue, Deque, Stack, AVL Tree, Tree Multiset, Trie, Directed Graph, Undirected Graph, Singly Linked List, Doubly Linked List, Max Heap, Max Priority Queue, Min Heap, Min Priority Queue.",
|
|
5
5
|
"main": "dist/index.js",
|
|
6
6
|
"module": "lib/index.js",
|
|
@@ -54,17 +54,17 @@
|
|
|
54
54
|
"@typescript-eslint/eslint-plugin": "^6.7.4",
|
|
55
55
|
"@typescript-eslint/parser": "^6.7.4",
|
|
56
56
|
"auto-changelog": "^2.4.0",
|
|
57
|
-
"avl-tree-typed": "^1.36.
|
|
57
|
+
"avl-tree-typed": "^1.36.4",
|
|
58
58
|
"benchmark": "^2.1.4",
|
|
59
|
-
"binary-tree-typed": "^1.36.
|
|
60
|
-
"bst-typed": "^1.36.
|
|
59
|
+
"binary-tree-typed": "^1.36.4",
|
|
60
|
+
"bst-typed": "^1.36.4",
|
|
61
61
|
"dependency-cruiser": "^14.1.0",
|
|
62
62
|
"eslint": "^8.50.0",
|
|
63
63
|
"eslint-config-prettier": "^9.0.0",
|
|
64
64
|
"eslint-import-resolver-alias": "^1.1.2",
|
|
65
65
|
"eslint-import-resolver-typescript": "^3.6.1",
|
|
66
66
|
"eslint-plugin-import": "^2.28.1",
|
|
67
|
-
"heap-typed": "^1.36.
|
|
67
|
+
"heap-typed": "^1.36.4",
|
|
68
68
|
"istanbul-badges-readme": "^1.8.5",
|
|
69
69
|
"jest": "^29.7.0",
|
|
70
70
|
"prettier": "^3.0.3",
|
|
@@ -350,16 +350,20 @@ export class BinaryTree<N extends BinaryTreeNode<N['val'], N> = BinaryTreeNode>
|
|
|
350
350
|
|
|
351
351
|
/**
|
|
352
352
|
* The function calculates the depth of a node in a binary tree.
|
|
353
|
-
* @param {N | BinaryTreeNodeKey | null}
|
|
353
|
+
* @param {N | BinaryTreeNodeKey | null} distNode - The `distNode` parameter can be any node of the tree
|
|
354
|
+
* @param {N | BinaryTreeNodeKey | null} beginRoot - The `beginRoot` parameter can be the predecessor node of distNode
|
|
354
355
|
* @returns the depth of the given node or binary tree.
|
|
355
356
|
*/
|
|
356
|
-
getDepth(beginRoot: N | BinaryTreeNodeKey | null = this.root): number {
|
|
357
|
+
getDepth(distNode: N | BinaryTreeNodeKey | null, beginRoot: N | BinaryTreeNodeKey | null = this.root): number {
|
|
358
|
+
if (typeof distNode === 'number') distNode = this.get(distNode, 'key');
|
|
357
359
|
if (typeof beginRoot === 'number') beginRoot = this.get(beginRoot, 'key');
|
|
358
|
-
|
|
359
360
|
let depth = 0;
|
|
360
|
-
while (
|
|
361
|
+
while (distNode?.parent) {
|
|
362
|
+
if (distNode === beginRoot) {
|
|
363
|
+
return depth;
|
|
364
|
+
}
|
|
361
365
|
depth++;
|
|
362
|
-
|
|
366
|
+
distNode = distNode.parent;
|
|
363
367
|
}
|
|
364
368
|
return depth;
|
|
365
369
|
}
|
|
@@ -47,10 +47,8 @@ export class TreeNode<V = any> {
|
|
|
47
47
|
}
|
|
48
48
|
|
|
49
49
|
getHeight() {
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
let maxDepth = 1;
|
|
53
|
-
if (beginRoot) {
|
|
50
|
+
let maxDepth = 0;
|
|
51
|
+
if (this) {
|
|
54
52
|
const bfs = (node: TreeNode<V>, level: number) => {
|
|
55
53
|
if (level > maxDepth) {
|
|
56
54
|
maxDepth = level;
|
|
@@ -62,7 +60,7 @@ export class TreeNode<V = any> {
|
|
|
62
60
|
}
|
|
63
61
|
}
|
|
64
62
|
};
|
|
65
|
-
bfs(
|
|
63
|
+
bfs(this, 0);
|
|
66
64
|
}
|
|
67
65
|
return maxDepth;
|
|
68
66
|
}
|
|
@@ -5,9 +5,14 @@
|
|
|
5
5
|
* @copyright Copyright (c) 2022 Tyler Zeng <zrwusa@gmail.com>
|
|
6
6
|
* @license MIT License
|
|
7
7
|
*/
|
|
8
|
+
|
|
9
|
+
/**
|
|
10
|
+
* TrieNode represents a node in the Trie data structure. It holds a character key, a map of children nodes,
|
|
11
|
+
* and a flag indicating whether it's the end of a word.
|
|
12
|
+
*/
|
|
8
13
|
export class TrieNode {
|
|
9
|
-
constructor(
|
|
10
|
-
this._key =
|
|
14
|
+
constructor(key: string) {
|
|
15
|
+
this._key = key;
|
|
11
16
|
this._isEnd = false;
|
|
12
17
|
this._children = new Map<string, TrieNode>();
|
|
13
18
|
}
|
|
@@ -43,6 +48,9 @@ export class TrieNode {
|
|
|
43
48
|
}
|
|
44
49
|
}
|
|
45
50
|
|
|
51
|
+
/**
|
|
52
|
+
* Trie represents a Trie data structure. It provides basic Trie operations and additional methods.
|
|
53
|
+
*/
|
|
46
54
|
export class Trie {
|
|
47
55
|
constructor(words?: string[], caseSensitive = true) {
|
|
48
56
|
this._root = new TrieNode('');
|
|
@@ -63,8 +71,14 @@ export class Trie {
|
|
|
63
71
|
set root(v: TrieNode) {
|
|
64
72
|
this._root = v;
|
|
65
73
|
}
|
|
66
|
-
private _caseSensitive: boolean;
|
|
67
74
|
|
|
75
|
+
private readonly _caseSensitive: boolean;
|
|
76
|
+
|
|
77
|
+
/**
|
|
78
|
+
* Add a word to the Trie structure.
|
|
79
|
+
* @param {string} word - The word to add.
|
|
80
|
+
* @returns {boolean} True if the word was successfully added.
|
|
81
|
+
*/
|
|
68
82
|
add(word: string): boolean {
|
|
69
83
|
word = this._caseProcess(word);
|
|
70
84
|
let cur = this.root;
|
|
@@ -80,22 +94,34 @@ export class Trie {
|
|
|
80
94
|
return true;
|
|
81
95
|
}
|
|
82
96
|
|
|
83
|
-
|
|
84
|
-
|
|
97
|
+
/**
|
|
98
|
+
* Check if the Trie contains a given word.
|
|
99
|
+
* @param {string} word - The word to check for.
|
|
100
|
+
* @returns {boolean} True if the word is present in the Trie.
|
|
101
|
+
*/
|
|
102
|
+
has(word: string): boolean {
|
|
103
|
+
word = this._caseProcess(word);
|
|
85
104
|
let cur = this.root;
|
|
86
|
-
for (const c of
|
|
105
|
+
for (const c of word) {
|
|
87
106
|
const nodeC = cur.children.get(c);
|
|
88
107
|
if (!nodeC) return false;
|
|
89
108
|
cur = nodeC;
|
|
90
109
|
}
|
|
91
110
|
return cur.isEnd;
|
|
92
111
|
}
|
|
93
|
-
|
|
112
|
+
|
|
113
|
+
private _caseProcess(str: string) {
|
|
94
114
|
if (!this._caseSensitive) {
|
|
95
|
-
|
|
115
|
+
str = str.toLowerCase(); // Convert str to lowercase if case-insensitive
|
|
96
116
|
}
|
|
97
|
-
return
|
|
117
|
+
return str;
|
|
98
118
|
}
|
|
119
|
+
|
|
120
|
+
/**
|
|
121
|
+
* Remove a word from the Trie structure.
|
|
122
|
+
* @param{string} word - The word to remove.
|
|
123
|
+
* @returns {boolean} True if the word was successfully removed.
|
|
124
|
+
*/
|
|
99
125
|
remove(word: string) {
|
|
100
126
|
word = this._caseProcess(word);
|
|
101
127
|
let isDeleted = false;
|
|
@@ -131,7 +157,7 @@ export class Trie {
|
|
|
131
157
|
|
|
132
158
|
getHeight() {
|
|
133
159
|
const beginRoot = this.root;
|
|
134
|
-
let maxDepth =
|
|
160
|
+
let maxDepth = 0;
|
|
135
161
|
if (beginRoot) {
|
|
136
162
|
const bfs = (node: TrieNode, level: number) => {
|
|
137
163
|
if (level > maxDepth) {
|
|
@@ -144,17 +170,18 @@ export class Trie {
|
|
|
144
170
|
}
|
|
145
171
|
}
|
|
146
172
|
};
|
|
147
|
-
bfs(beginRoot,
|
|
173
|
+
bfs(beginRoot, 0);
|
|
148
174
|
}
|
|
149
175
|
return maxDepth;
|
|
150
176
|
}
|
|
177
|
+
|
|
151
178
|
// --- start additional methods ---
|
|
152
179
|
/**
|
|
153
|
-
*
|
|
154
|
-
* @param {string} input - The input
|
|
155
|
-
* @returns
|
|
180
|
+
* Check if a given input string has an absolute prefix in the Trie, meaning it's not a complete word.
|
|
181
|
+
* @param {string} input - The input string to check.
|
|
182
|
+
* @returns {boolean} True if it's an absolute prefix in the Trie.
|
|
156
183
|
*/
|
|
157
|
-
|
|
184
|
+
hasPurePrefix(input: string): boolean {
|
|
158
185
|
input = this._caseProcess(input);
|
|
159
186
|
let cur = this.root;
|
|
160
187
|
for (const c of input) {
|
|
@@ -166,11 +193,11 @@ export class Trie {
|
|
|
166
193
|
}
|
|
167
194
|
|
|
168
195
|
/**
|
|
169
|
-
*
|
|
170
|
-
* @param {string} input - The input
|
|
171
|
-
* @returns a
|
|
196
|
+
* Check if a given input string is a prefix of any existing word in the Trie, whether as an absolute prefix or a complete word.
|
|
197
|
+
* @param {string} input - The input string representing the prefix to check.
|
|
198
|
+
* @returns {boolean} True if it's a prefix in the Trie.
|
|
172
199
|
*/
|
|
173
|
-
|
|
200
|
+
hasPrefix(input: string): boolean {
|
|
174
201
|
input = this._caseProcess(input);
|
|
175
202
|
let cur = this.root;
|
|
176
203
|
for (const c of input) {
|
|
@@ -182,12 +209,11 @@ export class Trie {
|
|
|
182
209
|
}
|
|
183
210
|
|
|
184
211
|
/**
|
|
185
|
-
*
|
|
186
|
-
* @param {string} input - The input
|
|
187
|
-
* in the Trie
|
|
188
|
-
* @returns a boolean value indicating whether the input string is a common prefix in the Trie data structure.
|
|
212
|
+
* Check if the input string is a common prefix in the Trie, meaning it's a prefix shared by all words in the Trie.
|
|
213
|
+
* @param {string} input - The input string representing the common prefix to check for.
|
|
214
|
+
* @returns {boolean} True if it's a common prefix in the Trie.
|
|
189
215
|
*/
|
|
190
|
-
|
|
216
|
+
hasCommonPrefix(input: string): boolean {
|
|
191
217
|
input = this._caseProcess(input);
|
|
192
218
|
let commonPre = '';
|
|
193
219
|
const dfs = (cur: TrieNode) => {
|
|
@@ -202,10 +228,8 @@ export class Trie {
|
|
|
202
228
|
}
|
|
203
229
|
|
|
204
230
|
/**
|
|
205
|
-
*
|
|
206
|
-
*
|
|
207
|
-
* @returns The function `getLongestCommonPrefix` returns a string, which is the longest common prefix found in the
|
|
208
|
-
* Trie.
|
|
231
|
+
* Get the longest common prefix among all the words stored in the Trie.
|
|
232
|
+
* @returns {string} The longest common prefix found in the Trie.
|
|
209
233
|
*/
|
|
210
234
|
getLongestCommonPrefix(): string {
|
|
211
235
|
let commonPre = '';
|
|
@@ -224,12 +248,13 @@ export class Trie {
|
|
|
224
248
|
* @param {string} prefix - The `prefix` parameter is a string that represents the prefix that we want to search for in the
|
|
225
249
|
* trie. It is an optional parameter, so if no prefix is provided, it will default to an empty string.
|
|
226
250
|
* @param {number} max - The max count of words will be found
|
|
227
|
-
* @returns an array of strings.
|
|
251
|
+
* @returns {string[]} an array of strings.
|
|
228
252
|
*/
|
|
229
253
|
getWords(prefix = '', max = Number.MAX_SAFE_INTEGER): string[] {
|
|
230
254
|
prefix = this._caseProcess(prefix);
|
|
231
255
|
const words: string[] = [];
|
|
232
256
|
let found = 0;
|
|
257
|
+
|
|
233
258
|
function dfs(node: TrieNode, word: string) {
|
|
234
259
|
for (const char of node.children.keys()) {
|
|
235
260
|
const charNode = node.children.get(char);
|
|
@@ -105,6 +105,19 @@ describe('BinaryTree', () => {
|
|
|
105
105
|
expect(binaryTree.has(4)).toBe(false);
|
|
106
106
|
});
|
|
107
107
|
|
|
108
|
+
test('should getDepth return correct depth', () => {
|
|
109
|
+
binaryTree.add(1);
|
|
110
|
+
expect(binaryTree.getDepth(1)).toBe(0);
|
|
111
|
+
binaryTree.add(2);
|
|
112
|
+
expect(binaryTree.getDepth(2)).toBe(1);
|
|
113
|
+
binaryTree.add(3);
|
|
114
|
+
expect(binaryTree.getDepth(3, 1)).toBe(1);
|
|
115
|
+
binaryTree.add(4);
|
|
116
|
+
expect(binaryTree.getDepth(4, 1)).toBe(2);
|
|
117
|
+
expect(binaryTree.getDepth(4)).toBe(2);
|
|
118
|
+
expect(binaryTree.getDepth(4, 2)).toBe(1);
|
|
119
|
+
});
|
|
120
|
+
|
|
108
121
|
test('should traverse in-order', () => {
|
|
109
122
|
binaryTree.add(4);
|
|
110
123
|
binaryTree.add(2);
|
|
@@ -28,7 +28,6 @@ describe('Heap Operation Test', () => {
|
|
|
28
28
|
minHeap.add({key: 0, a: 'a0'});
|
|
29
29
|
|
|
30
30
|
expect(minHeap.peek()).toEqual({a: 'a0', key: 0});
|
|
31
|
-
console.log('---', minHeap.toArray());
|
|
32
31
|
expect(minHeap.toArray().map(item => ({a: item.a}))).toEqual([{a: 'a0'}, {a: 'a1'}, {a: 'a2'}, {a: 'a6'}]);
|
|
33
32
|
let i = 0;
|
|
34
33
|
const expectPolled = [{a: 'a0'}, {a: 'a1'}, {a: 'a2'}, {a: 'a6'}];
|
|
@@ -29,11 +29,11 @@ describe('TreeNode', () => {
|
|
|
29
29
|
child1.addChildren([grandchild1]);
|
|
30
30
|
child2.addChildren([grandchild2]);
|
|
31
31
|
|
|
32
|
-
expect(rootNode.getHeight()).toBe(
|
|
32
|
+
expect(rootNode.getHeight()).toBe(2); // Height of the tree should be 2
|
|
33
33
|
});
|
|
34
34
|
|
|
35
35
|
it('should handle nodes without children when calculating height', () => {
|
|
36
36
|
const rootNode = new TreeNode<string>('1', 'Root Node');
|
|
37
|
-
expect(rootNode.getHeight()).toBe(
|
|
37
|
+
expect(rootNode.getHeight()).toBe(0); // Height of a single node should be 0
|
|
38
38
|
});
|
|
39
39
|
});
|