老师,能帮忙看看我写的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 星