【问题标题】:Unexpected functioning of Trie delete functionTrie删除功能的意外功能
【发布时间】:2023-04-01 18:35:01
【问题描述】:

我是 Java 编程新手,我编写了尝试将数字存储为位的代码(右起最后 31 位)。因此每个节点只有两个可能的子节点,最大值为 0 或 1。

每个trie节点对应的节点有以下属性

  • Node next[] : 指向下一个节点的大小为 2 的数组
  • int visCnt : 节点被访问的次数,这将是
    用于稍后删除节点(检查下面的删除功能)
  • int number : 叶节点存储的数字,例如,如果我们插入 5 进行尝试,则叶节点的 'number' 值为 5,同时从根到叶的所有其他节点都有默认值为 -1

我实现的功能是

  • void insert(int num) : 将 'num' 插入到全局 trie
  • void remove(int num, Node A,int ind) : 递归函数删除一个数字,如果它 存在于全局 trie 中。对于节点 A ,我通过根(全局特里) 从主节点,到达要删除的节点。从叶子,节点 通过检查 visCnt 的值,自下而上删除。
  • boolean isExist(int num) : 检查全局 trie 中是否存在 num

实现中的 remove 功能没有按预期工作,我已将代码粘贴在下面以供参考,(您可以尝试在 onlineGDB 之类的站点上运行它会正常工作)。在我插入(4)然后删除(4)之后的主函数中,我希望isExist(4)返回false,但事实并非如此,它返回为true。将节点对象设置为null不会删除节点吗?

代码:

import java.util.*;
import java.lang.*;
import java.io.*;
public class Main
{
    static class Node{
        Node next[] = new Node[2];
        int visCnt=0;
        int number = -1;
    }
    static Node root = new Node();
    void insert(int num){
        System.out.println("added "+num);
        Node cur =root;
        for(int i = 30;i>=0;i--){
            cur.visCnt++;
            int tmp = 1<<i;
            int curBit = ((tmp&num)==0)?0:1;
            if(cur.next[curBit]==null)
                cur.next[curBit] = new Node();
            cur=cur.next[curBit];
        }
        cur.visCnt++;
        cur.number = num;
    }
    void remove(int num, Node A,int ind){
        if(A==null){
            System.out.println("removed "+num);
            return;
        }
        A.visCnt--;
        int curBit = ((1<<ind)&num)==0?0:1;
        remove(num,A.next[curBit],ind-1);
        if(A.visCnt==0){
            A=null;
        }
    }
    boolean isExist(int num){
        System.out.println("checking for  "+num);
        Node cur =root;
        for(int i = 30;i>=0;i--){
            cur.visCnt++;
            int tmp = 1<<i;
            int curBit = ((tmp&num)==0)?0:1;
            if(cur.next[curBit]==null){
                System.out.println(num+ " does not exist in trie ");
                return false;
            }
            cur=cur.next[curBit];
        }
        System.out.println(cur.number+ " exists in trie ");
        return true;
    }
    public static void main(String[] args) {
        Main trie = new Main();
        trie.root.visCnt++;
        trie.insert(1);
        trie.insert(2);
        trie.insert(4);
        trie.remove(4,root,30);
        trie.isExist(4);
        // return ans;
    }
}

输出

added 1
added 2
added 4
removed 4
checking for  4
4 exists in trie 

【问题讨论】:

    标签: java algorithm data-structures implementation trie


    【解决方案1】:

    我将您的 remove() 更改为:

    void remove(int num, Node A,int ind){
        A.visCnt--;
        if(A.next[0]==null && A.next[1] == null){
            System.out.println("removed " + num);
            return;
        }
        int curBit = ((1<<ind)&num)==0?0:1;
        remove(num,A.next[curBit],ind-1);
        if(A.next[curBit].visCnt == 0){
            A.next[curBit]=null;
        }
    }
    

    它正在工作......

    added 1
    added 2
    added 4
    added 4
    removed 4
    checking for  4
    4 exists in trie 
    removed 4
    checking for  4
    4 does not exist in trie 
    

    添加了 4 两次。

    说明:

    你的问题在这里:

    if(A.visCnt==0){
        A=null;
    }
    

    当您将 null 放入引用 A 中时,A 的父级没有得到它。因为 Java 是按值调用,而不是按引用调用。所以你需要这样做:

    if(A.next[curBit].visCnt == 0){
        A.next[curBit]=null;
    }
    

    其余代码是为了应对这些变化。我希望,你知道原因。

    【讨论】:

    • 谢谢你的代码,但我正在寻找我的函数中的错误
    • 我添加了一些解释。希望它会帮助你。如果有帮助,您可以接受答案。 @95_96
    猜你喜欢
    • 1970-01-01
    • 2012-12-23
    • 2015-12-15
    • 1970-01-01
    • 2020-08-07
    • 2019-03-29
    • 2021-08-22
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多