Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

Commit a81f6e1

Browse files
feat(trie): remove method
1 parent 524670e commit a81f6e1

File tree

3 files changed

+137
-0
lines changed

3 files changed

+137
-0
lines changed

‎src/data-structures/trees/trie-1.js

Lines changed: 48 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -67,6 +67,54 @@ class Trie {
6767

6868
return words;
6969
}
70+
71+
/**
72+
* Return true if found the word to be removed, otherwise false.
73+
* Iterative approach
74+
* @param {string} word - The word to remove
75+
* @returns {boolean}
76+
*/
77+
remove(word) {
78+
const stack = [];
79+
let curr = this;
80+
81+
for (const char of word) {
82+
if (!curr.children[char]) { return false; }
83+
stack.push(curr);
84+
curr = curr.children[char];
85+
}
86+
87+
if (!curr.isWord) { return false; }
88+
let node = stack.pop();
89+
90+
do {
91+
node.children = {};
92+
node = stack.pop();
93+
} while (node && !node.isWord);
94+
95+
return true;
96+
}
97+
98+
/**
99+
* Return true if found the word to be removed, otherwise false.
100+
* recursive approach
101+
* @param {string} word - The word to remove
102+
* @returns {boolean}
103+
*/
104+
remove2(word, i = 0, parent = this) {
105+
if (i === word.length - 1) {
106+
return true;
107+
}
108+
const child = parent.children[word.charAt(i)];
109+
if (!child) return false;
110+
111+
const found = this.remove(word, i + 1, child);
112+
113+
if (found) {
114+
delete parent.children[word.charAt(i)];
115+
}
116+
return true;
117+
}
70118
}
71119

72120
// Aliases

‎src/data-structures/trees/trie.js

Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,40 @@ class Trie {
2121
curr.isWord = true;
2222
}
2323

24+
/**
25+
* Return true if found the word to be removed, otherwise false.
26+
* @param {string} word - The word to remove
27+
* @returns {boolean}
28+
*/
29+
remove(word) {
30+
return this.removeHelper(word);
31+
}
32+
33+
/**
34+
* Remove word from trie, return true if found, otherwise false.
35+
* @param {string} word - The word to remove.
36+
* @param {Trie} parent - The parent node.
37+
* @param {number} index - The index.
38+
* @param {number} meta.stop - Keeps track of the last letter that won't be removed.
39+
* @returns {boolean}
40+
*/
41+
removeHelper(word, parent = this, index = 0, meta = { stop: 0 }) {
42+
if (index === word.length) {
43+
parent.isWord = false;
44+
if (Object.keys(parent.children)) { meta.stop = index; }
45+
return true;
46+
}
47+
const child = parent.children[word.charAt(index)];
48+
if (!child) { return false; }
49+
if (parent.isWord) { meta.stop = index; }
50+
const found = this.removeHelper(word, child, index + 1, meta);
51+
// deletes all the nodes beyond `meta.stop`.
52+
if (found && index >= meta.stop) {
53+
delete parent.children[word.charAt(index)];
54+
}
55+
return found;
56+
}
57+
2458
/**
2559
* Retun last node that matches word or prefix or false if not found.
2660
* @param {string} word - Word to search.

‎src/data-structures/trees/trie.spec.js

Lines changed: 55 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -69,6 +69,13 @@ describe('Trie', () => {
6969
expect(trie.startsWith('do')).toEqual(true);
7070
});
7171

72+
it('should match full words if partial is set', () => {
73+
expect(trie.search('dogs', {
74+
partial: true,
75+
})).toEqual(true);
76+
expect(trie.startsWith('dogs')).toEqual(true);
77+
});
78+
7279
it('should not match non existing words', () => {
7380
expect(trie.search('doors')).toEqual(false);
7481
});
@@ -129,5 +136,53 @@ describe('Trie', () => {
129136
expect(words).toEqual([]);
130137
});
131138
});
139+
140+
describe('remove', () => {
141+
it('should remove a word', () => {
142+
trie = new Trie();
143+
trie.insert('a');
144+
expect(trie.remove('a')).toEqual(true);
145+
expect(trie.getAllWords()).toEqual([]);
146+
});
147+
148+
it('should remove word and keep other words', () => {
149+
trie = new Trie();
150+
trie.insert('a');
151+
trie.insert('ab');
152+
expect(trie.remove('a')).toEqual(true);
153+
expect(trie.getAllWords()).toEqual(['ab']);
154+
});
155+
156+
it('should remove surrounding word', () => {
157+
trie = new Trie();
158+
trie.insert('a');
159+
trie.insert('ab');
160+
expect(trie.remove('ab')).toEqual(true);
161+
expect(trie.getAllWords()).toEqual(['a']);
162+
});
163+
164+
it('should return false when word is not found', () => {
165+
expect(trie.remove('not there')).toBe(false);
166+
});
167+
168+
it('should remove words in between and still match', () => {
169+
expect(trie.remove('dog')).toBe(true);
170+
expect(trie.search('dogs')).toBe(true);
171+
expect(trie.startsWith('dog')).toBe(true);
172+
expect(trie.getAllWords()).toEqual([
173+
'dogs', 'door', 'day', 'cat',
174+
]);
175+
});
176+
177+
it('should remove word and no longer match partials', () => {
178+
expect(trie.remove('dogs')).toBe(true);
179+
expect(trie.search('dogs')).toBe(false);
180+
expect(trie.search('dog')).toBe(true);
181+
expect(trie.startsWith('dog')).toBe(true);
182+
expect(trie.getAllWords()).toEqual([
183+
'dog', 'door', 'day', 'cat',
184+
]);
185+
});
186+
});
132187
});
133188
});

0 commit comments

Comments
(0)

AltStyle によって変換されたページ (->オリジナル) /