data-structure-typed 1.36.3 → 1.36.4
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/CHANGELOG.md +2 -1
- package/dist/data-structures/trie/trie.d.ts +10 -6
- package/dist/data-structures/trie/trie.js +57 -18
- package/dist/data-structures/trie/trie.js.map +1 -1
- package/lib/data-structures/trie/trie.d.ts +10 -6
- package/lib/data-structures/trie/trie.js +57 -18
- package/package.json +5 -5
- package/src/data-structures/trie/trie.ts +57 -21
- package/test/unit/data-structures/trie/trie.test.ts +663 -3
- package/umd/bundle.min.js +1 -1
- package/umd/bundle.min.js.map +1 -1
|
@@ -7,19 +7,19 @@
|
|
|
7
7
|
*/
|
|
8
8
|
export class TrieNode {
|
|
9
9
|
constructor(v: string) {
|
|
10
|
-
this.
|
|
10
|
+
this._key = v;
|
|
11
11
|
this._isEnd = false;
|
|
12
12
|
this._children = new Map<string, TrieNode>();
|
|
13
13
|
}
|
|
14
14
|
|
|
15
|
-
private
|
|
15
|
+
private _key;
|
|
16
16
|
|
|
17
|
-
get
|
|
18
|
-
return this.
|
|
17
|
+
get key(): string {
|
|
18
|
+
return this._key;
|
|
19
19
|
}
|
|
20
20
|
|
|
21
|
-
set
|
|
22
|
-
this.
|
|
21
|
+
set key(v: string) {
|
|
22
|
+
this._key = v;
|
|
23
23
|
}
|
|
24
24
|
|
|
25
25
|
protected _children: Map<string, TrieNode>;
|
|
@@ -44,8 +44,9 @@ export class TrieNode {
|
|
|
44
44
|
}
|
|
45
45
|
|
|
46
46
|
export class Trie {
|
|
47
|
-
constructor(words?: string[]) {
|
|
47
|
+
constructor(words?: string[], caseSensitive = true) {
|
|
48
48
|
this._root = new TrieNode('');
|
|
49
|
+
this._caseSensitive = caseSensitive;
|
|
49
50
|
if (words) {
|
|
50
51
|
for (const i of words) {
|
|
51
52
|
this.add(i);
|
|
@@ -62,9 +63,11 @@ export class Trie {
|
|
|
62
63
|
set root(v: TrieNode) {
|
|
63
64
|
this._root = v;
|
|
64
65
|
}
|
|
66
|
+
private _caseSensitive: boolean;
|
|
65
67
|
|
|
66
68
|
add(word: string): boolean {
|
|
67
|
-
|
|
69
|
+
word = this._caseProcess(word);
|
|
70
|
+
let cur = this.root;
|
|
68
71
|
for (const c of word) {
|
|
69
72
|
let nodeC = cur.children.get(c);
|
|
70
73
|
if (!nodeC) {
|
|
@@ -78,7 +81,8 @@ export class Trie {
|
|
|
78
81
|
}
|
|
79
82
|
|
|
80
83
|
has(input: string): boolean {
|
|
81
|
-
|
|
84
|
+
input = this._caseProcess(input);
|
|
85
|
+
let cur = this.root;
|
|
82
86
|
for (const c of input) {
|
|
83
87
|
const nodeC = cur.children.get(c);
|
|
84
88
|
if (!nodeC) return false;
|
|
@@ -86,8 +90,14 @@ export class Trie {
|
|
|
86
90
|
}
|
|
87
91
|
return cur.isEnd;
|
|
88
92
|
}
|
|
89
|
-
|
|
93
|
+
private _caseProcess(input: string) {
|
|
94
|
+
if (!this._caseSensitive) {
|
|
95
|
+
input = input.toLowerCase(); // Convert input to lowercase if case insensitive
|
|
96
|
+
}
|
|
97
|
+
return input;
|
|
98
|
+
}
|
|
90
99
|
remove(word: string) {
|
|
100
|
+
word = this._caseProcess(word);
|
|
91
101
|
let isDeleted = false;
|
|
92
102
|
const dfs = (cur: TrieNode, i: number): boolean => {
|
|
93
103
|
const char = word[i];
|
|
@@ -119,6 +129,25 @@ export class Trie {
|
|
|
119
129
|
return isDeleted;
|
|
120
130
|
}
|
|
121
131
|
|
|
132
|
+
getHeight() {
|
|
133
|
+
const beginRoot = this.root;
|
|
134
|
+
let maxDepth = 1;
|
|
135
|
+
if (beginRoot) {
|
|
136
|
+
const bfs = (node: TrieNode, level: number) => {
|
|
137
|
+
if (level > maxDepth) {
|
|
138
|
+
maxDepth = level;
|
|
139
|
+
}
|
|
140
|
+
const {children} = node;
|
|
141
|
+
if (children) {
|
|
142
|
+
for (const child of children.entries()) {
|
|
143
|
+
bfs(child[1], level + 1);
|
|
144
|
+
}
|
|
145
|
+
}
|
|
146
|
+
};
|
|
147
|
+
bfs(beginRoot, 1);
|
|
148
|
+
}
|
|
149
|
+
return maxDepth;
|
|
150
|
+
}
|
|
122
151
|
// --- start additional methods ---
|
|
123
152
|
/**
|
|
124
153
|
* The function checks if a given input string has an absolute prefix in a tree data structure.Only can present as a prefix, not a word
|
|
@@ -126,7 +155,8 @@ export class Trie {
|
|
|
126
155
|
* @returns a boolean value.
|
|
127
156
|
*/
|
|
128
157
|
isAbsPrefix(input: string): boolean {
|
|
129
|
-
|
|
158
|
+
input = this._caseProcess(input);
|
|
159
|
+
let cur = this.root;
|
|
130
160
|
for (const c of input) {
|
|
131
161
|
const nodeC = cur.children.get(c);
|
|
132
162
|
if (!nodeC) return false;
|
|
@@ -141,7 +171,8 @@ export class Trie {
|
|
|
141
171
|
* @returns a boolean value.
|
|
142
172
|
*/
|
|
143
173
|
isPrefix(input: string): boolean {
|
|
144
|
-
|
|
174
|
+
input = this._caseProcess(input);
|
|
175
|
+
let cur = this.root;
|
|
145
176
|
for (const c of input) {
|
|
146
177
|
const nodeC = cur.children.get(c);
|
|
147
178
|
if (!nodeC) return false;
|
|
@@ -157,15 +188,16 @@ export class Trie {
|
|
|
157
188
|
* @returns a boolean value indicating whether the input string is a common prefix in the Trie data structure.
|
|
158
189
|
*/
|
|
159
190
|
isCommonPrefix(input: string): boolean {
|
|
191
|
+
input = this._caseProcess(input);
|
|
160
192
|
let commonPre = '';
|
|
161
193
|
const dfs = (cur: TrieNode) => {
|
|
162
|
-
commonPre += cur.
|
|
194
|
+
commonPre += cur.key;
|
|
163
195
|
if (commonPre === input) return;
|
|
164
196
|
if (cur.isEnd) return;
|
|
165
197
|
if (cur && cur.children && cur.children.size === 1) dfs(Array.from(cur.children.values())[0]);
|
|
166
198
|
else return;
|
|
167
199
|
};
|
|
168
|
-
dfs(this.
|
|
200
|
+
dfs(this.root);
|
|
169
201
|
return commonPre === input;
|
|
170
202
|
}
|
|
171
203
|
|
|
@@ -178,24 +210,26 @@ export class Trie {
|
|
|
178
210
|
getLongestCommonPrefix(): string {
|
|
179
211
|
let commonPre = '';
|
|
180
212
|
const dfs = (cur: TrieNode) => {
|
|
181
|
-
commonPre += cur.
|
|
213
|
+
commonPre += cur.key;
|
|
182
214
|
if (cur.isEnd) return;
|
|
183
215
|
if (cur && cur.children && cur.children.size === 1) dfs(Array.from(cur.children.values())[0]);
|
|
184
216
|
else return;
|
|
185
217
|
};
|
|
186
|
-
dfs(this.
|
|
218
|
+
dfs(this.root);
|
|
187
219
|
return commonPre;
|
|
188
220
|
}
|
|
189
221
|
|
|
190
222
|
/**
|
|
191
223
|
* The `getAll` function returns an array of all words in a Trie data structure that start with a given prefix.
|
|
192
|
-
* @param
|
|
224
|
+
* @param {string} prefix - The `prefix` parameter is a string that represents the prefix that we want to search for in the
|
|
193
225
|
* trie. It is an optional parameter, so if no prefix is provided, it will default to an empty string.
|
|
226
|
+
* @param {number} max - The max count of words will be found
|
|
194
227
|
* @returns an array of strings.
|
|
195
228
|
*/
|
|
196
|
-
|
|
229
|
+
getWords(prefix = '', max = Number.MAX_SAFE_INTEGER): string[] {
|
|
230
|
+
prefix = this._caseProcess(prefix);
|
|
197
231
|
const words: string[] = [];
|
|
198
|
-
|
|
232
|
+
let found = 0;
|
|
199
233
|
function dfs(node: TrieNode, word: string) {
|
|
200
234
|
for (const char of node.children.keys()) {
|
|
201
235
|
const charNode = node.children.get(char);
|
|
@@ -204,11 +238,13 @@ export class Trie {
|
|
|
204
238
|
}
|
|
205
239
|
}
|
|
206
240
|
if (node.isEnd) {
|
|
241
|
+
if (found > max - 1) return;
|
|
207
242
|
words.push(word);
|
|
243
|
+
found++;
|
|
208
244
|
}
|
|
209
245
|
}
|
|
210
246
|
|
|
211
|
-
let startNode = this.
|
|
247
|
+
let startNode = this.root;
|
|
212
248
|
|
|
213
249
|
if (prefix) {
|
|
214
250
|
for (const c of prefix) {
|
|
@@ -216,8 +252,8 @@ export class Trie {
|
|
|
216
252
|
if (nodeC) startNode = nodeC;
|
|
217
253
|
}
|
|
218
254
|
}
|
|
255
|
+
if (startNode !== this.root) dfs(startNode, prefix);
|
|
219
256
|
|
|
220
|
-
dfs(startNode, prefix);
|
|
221
257
|
return words;
|
|
222
258
|
}
|
|
223
259
|
|