【问题标题】:NullPointerException when deleting a trie word删除 trie 字时出现 NullPointerException
【发布时间】:2015-03-05 06:06:43
【问题描述】:

下面是代码。数组索引表示小字符(a-z),索引为 26(英文字母的字符数)。它是一个单词字典,其中 children[character ascii value-97] 指向下一个节点。词尾给出 bool terminal=true。

所有函数都是递归的。在删除函数中,我们必须逐个字符地遍历到单词的末尾。遍历时,在第二次调用递归删除时,我丢失了所有引用并出现NullPointerException

出现问题的代码行前面有注释。首先检查字典中是否存在单词。

import java.io.File;
import java.util.Scanner;

public class xxx {

public static void main(String[] args) {
    Trie trie = new Trie();

                if (trie.delete(word)) {
                    System.out.println("Word deleted");
                } else {
                    System.out.println("Word not present");
                }
                break;
            }
            case "S": { //Search for the word
                String word = tokens[1];
                if (trie.isPresent(word)) {
                    System.out.println("Word found");
                } else {
                    System.out.println("Word not found");
                }
}

这个类只是调用 Node 类的递归函数。 trie 类从主类获取调用,然后将数据转移到 Node 类中的递归函数

class Trie {

Node root;

public Trie() {
    root = new Node();

}

boolean isPresent(String s) { // returns true if s is present, false otherwise
    current = root;
    for (int i = 0; i < s.length(); i++) {
        if (current.children[(int) s.charAt(i) - 97] == null) {
            return false;
        } else {
            current = current.children[(int) s.charAt(i) - 97];
        }

    }
    if (current.terminal == false) {
        return false;
    }

    return true;
}

boolean delete(String s) { // returns false if s is not present, true otherwise
    if (!isPresent(s)) {
        return false;
    }
    root.delete(root,s);
    return true;
}

int membership() { // returns the number of words in the data structure
    return root.membership(root, 0);
}

void listAll() { // list all members of the Trie in alphabetical orber
    root.listAll(root, "");

}

}

children[ascii value-97] 将引用一个节点,此链接将代表字母字符。 outDegree 将确保仅删除给定的字符串。该类具有所有递归函数。

 class Node {

boolean terminal;
int outDegree;
Node[] children;

public Node() {
    terminal = false;
    outDegree = 0;
    children = new Node[26];
}



public void delete(Node x, String s) {
    if (s.length() > 1){
        if(i<s.length())
        delete(children[s.charAt(0)-97],s.substring(1)); //this is where problem occurs

    }
    else if(children[((int)s.charAt(0))-97].outDegree>0)
        terminal =false;
    else if(children[((int)s.charAt(0))-97].outDegree==0){
        children[((int)s.charAt(0))-97]=null;
        return;
    }
    if(children[s.charAt(0)-97].outDegree==0)
        children[s.charAt(0)-97]=null;
    }

}

【问题讨论】:

标签: java data-structures trie


【解决方案1】:

您的问题不在您注释的代码行中。你的问题是你如何初始化数组:

children = new Node[26];

这行代码分配了数组的内存。但是,对于对象引用,数组中每个单独元素的值设置为 NULL,char 基元的 unicode NULL 字符,boolean 基元的 false 和数字基元的 0。如果你想让它工作,你必须正确初始化数组。

【讨论】:

  • 数组初始化就像insert() word, listall() words, ispresent()这些函数都完美运行。所有的引用最初都设置为 null,如果我添加 word,那么 children[char-97 的 ascii 值] 将引用一个新的 node.PS。节点不保存字符,它是表示字符的数组索引。
  • 第一个是输入图像:link 第二个图像显示字符串“abcd”的 trie 配置:link 第三个图像显示第一个递归:link 第四个图像是第二个递归引用的位置变为空:link
  • 如果您在那条线上获得 NPE,显然初始化并不好。我建议您在调试时运行并逐步执行您的代码。您在 isPresent 方法中有此代码:if (current.children[(int) s.charAt(i) - 97] == null) { return false;} 这告诉我您希望数组的某些元素为 NULL。我没有看到任何代码来纠正这个问题。
  • 数组中的所有元素都是空的,除了代表字符的索引。如果整个 trie 中只有一个单词,那么 children 数组中只有一个元素应该引用下一个元素。其他参考将无效。这种模式也在以下节点中继续存在。
  • @Fazeel,如果是这样,您显然访问了错误的索引。 NPE 是您尝试访问的索引包含空引用的指示符。因此,如果无法正确初始化数组的所有元素,我建议您调试访问函数 (current.children[(int) s.charAt(i) - 97])。这是你的两个选择。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2022-01-06
  • 2018-05-22
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多