老师,能帮忙看看我写的Trie的两种删除的版本对吗?
/**
* 循环版本
* @param word
*/
public void remove(String word) {
// 如果不包含单词,直接返回
if (!contains(word)) {
return;
}
/*
循环思路:
从root开始,因为前面已经判断过包含这个word,所以在每轮遍历中:
如果map内只有一组映射关系,即size==1,则必然是word中的字符,此时移除这个映射关系即可,移除前要拿到下一个节点的位置以便循环继续执行
如果map还包含其他映射关系,即size>1,则不作处理
到最后一个节点时,isWord必然为true,将其置为false
*/
Node cur = root;
for (int i = 0; i < word.length(); i++) {
char c = word.charAt(i);
if (cur.next.size() == 1) {
Node next = cur.next.get(c);
cur.next.remove(c);
cur = next;
}
cur.isWord = false;
}
// 维护size
size --;
}
/**
* 递归版本
* @param word
*/
public void removeR(String word){
if (contains(word)){
removeR(word, root, 0);
}
}
private void removeR(String word, Node node, int index){
// 退出条件:递归至word最后一个字符所对应的节点。此时,将这个节点的isWord置为false,开始返回
if(index == word.length()){
node.isWord = false;
size --;
return;
}
char c = word.charAt(index);
// 递归至最末端,开始返回后,倒序删除每个map中对应字符的映射关系
removeR(word, node.next.get(c), index+1);
if (node.next.size() == 1){
node.next.remove(c);
}
}16
收起
正在回答
1回答
是有问题的。
你的注释里这个假设是错的:
如果map内只有一组映射关系,即size==1,则必然是word中的字符,此时移除这个映射关系即可
map 内的这组映射关系确实肯定是 word 中的字符,但不一定仅仅是 word 中的字符。
比如 Trie 中存了 "ab" 和 "ac" 两个词。"a" 是 “ab" 和 "ac" 共有的前缀。此时,在你的逻辑下,删除 "ab",将会导致把 a 这个节点删除。"ac" 这个词对应的所有节点也就没有了。
继续加油!:)
恭喜解决一个难题,获得1积分~
来为老师/同学的回答评分吧
0 星