mirror of
https://github.moeyy.xyz/https://github.com/trekhleb/javascript-algorithms.git
synced 2024-12-26 23:21:18 +08:00
Add Trie.deleteWord and TrieNode.removeChild (#181)
This commit is contained in:
parent
6e2ff9b604
commit
d25eff49e6
@ -24,6 +24,35 @@ export default class Trie {
|
|||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param {string} word
|
||||||
|
* @return {Trie}
|
||||||
|
*/
|
||||||
|
deleteWord(word) {
|
||||||
|
function depthFirstDelete(currentNode, charIndex) {
|
||||||
|
if (charIndex >= word.length) return;
|
||||||
|
|
||||||
|
const character = word[charIndex];
|
||||||
|
const nextNode = currentNode.getChild(character);
|
||||||
|
|
||||||
|
if (nextNode == null) return;
|
||||||
|
|
||||||
|
depthFirstDelete(nextNode, charIndex + 1);
|
||||||
|
|
||||||
|
if (charIndex === word.length - 1) {
|
||||||
|
nextNode.isCompleteWord = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// childNode is deleted only if:
|
||||||
|
// - childNode has NO children
|
||||||
|
// - childNode.isCompleteWord === false
|
||||||
|
currentNode.removeChild(character);
|
||||||
|
}
|
||||||
|
|
||||||
|
depthFirstDelete(this.head, 0);
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @param {string} word
|
* @param {string} word
|
||||||
* @return {string[]}
|
* @return {string[]}
|
||||||
|
@ -37,6 +37,31 @@ export default class TrieNode {
|
|||||||
return childNode;
|
return childNode;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param {string} character
|
||||||
|
* @return {TrieNode}
|
||||||
|
*/
|
||||||
|
removeChild(character) {
|
||||||
|
function isSafeToDelete(node) {
|
||||||
|
return (
|
||||||
|
node
|
||||||
|
&& !node.isCompleteWord
|
||||||
|
&& node.children.getKeys().length === 0
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
const childNode = this.getChild(character);
|
||||||
|
|
||||||
|
// delete childNode only if:
|
||||||
|
// - childNode has NO children
|
||||||
|
// - childNode.isCompleteWord === false
|
||||||
|
if (isSafeToDelete(childNode)) {
|
||||||
|
this.children.delete(character);
|
||||||
|
}
|
||||||
|
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @param {string} character
|
* @param {string} character
|
||||||
* @return {boolean}
|
* @return {boolean}
|
||||||
|
@ -23,6 +23,18 @@ describe('Trie', () => {
|
|||||||
expect(trie.head.getChild('c').getChild('a').getChild('t').toString()).toBe('t*');
|
expect(trie.head.getChild('c').getChild('a').getChild('t').toString()).toBe('t*');
|
||||||
});
|
});
|
||||||
|
|
||||||
|
it('should delete words from trie', () => {
|
||||||
|
const trie = new Trie();
|
||||||
|
|
||||||
|
trie.addWord('carpet');
|
||||||
|
trie.addWord('car');
|
||||||
|
expect(trie.doesWordExist('carpet')).toBe(true);
|
||||||
|
|
||||||
|
trie.deleteWord('carpet');
|
||||||
|
expect(trie.doesWordExist('carpet')).toEqual(false);
|
||||||
|
expect(trie.doesWordExist('car')).toEqual(true);
|
||||||
|
});
|
||||||
|
|
||||||
it('should suggests next characters', () => {
|
it('should suggests next characters', () => {
|
||||||
const trie = new Trie();
|
const trie = new Trie();
|
||||||
|
|
||||||
|
@ -18,6 +18,36 @@ describe('TrieNode', () => {
|
|||||||
expect(trieNode.toString()).toBe('c:a,o');
|
expect(trieNode.toString()).toBe('c:a,o');
|
||||||
});
|
});
|
||||||
|
|
||||||
|
describe('removing child nodes', () => {
|
||||||
|
it('should delete child node if the child node has NO children', () => {
|
||||||
|
const trieNode = new TrieNode('c');
|
||||||
|
trieNode.addChild('a');
|
||||||
|
expect(trieNode.hasChild('a')).toBe(true);
|
||||||
|
|
||||||
|
trieNode.removeChild('a');
|
||||||
|
expect(trieNode.hasChild('a')).toBe(false);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should NOT delete child node if the child node has children', () => {
|
||||||
|
const trieNode = new TrieNode('c');
|
||||||
|
trieNode.addChild('a');
|
||||||
|
const childNode = trieNode.getChild('a');
|
||||||
|
childNode.addChild('r');
|
||||||
|
|
||||||
|
trieNode.removeChild('a');
|
||||||
|
expect(trieNode.hasChild('a')).toEqual(true);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should NOT delete child node if the child node completes a word', () => {
|
||||||
|
const trieNode = new TrieNode('c');
|
||||||
|
const IS_COMPLETE_WORD = true;
|
||||||
|
trieNode.addChild('a', IS_COMPLETE_WORD);
|
||||||
|
|
||||||
|
trieNode.removeChild('a');
|
||||||
|
expect(trieNode.hasChild('a')).toEqual(true);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
it('should get child nodes', () => {
|
it('should get child nodes', () => {
|
||||||
const trieNode = new TrieNode('c');
|
const trieNode = new TrieNode('c');
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user