【问题标题】:Java - Deleting word in trie (pseudo code please)Java - 在 trie 中删除单词(请使用伪代码)
【发布时间】:2014-04-22 17:46:04
【问题描述】:

我一直在努力计划如何从 trie 中删除单词。我有一个实现,它在节点上使用一维数组,该数组保存一个单词的下一个字符。我了解如何删除整个单词,但不考虑包含要删除的较小单词的较大单词,因此尝试从下面的 trie 中删除“bat”、“battle”、“as”和“any”(*表示词尾)并离开“battery”、“battlefield”、“ask”和“anywho”:

    root 
    / \
   a   b-a-t*-t-e-r-y*
  / \         |
 n   s*-k*    l-e*-f-i-e-l-d*
 |
 y*-w-h-o*

以下是我目前实现的 trie:

public class TrieNode {

    protected char letter = ' ';
    protected TrieNode parentNode = null;
    protected boolean fullWord = false;
    protected TrieNode[] children = new TrieNode[26];

    public TrieNode(char letter, TrieNode parentNode){
        this.letter = letter;
        this.parentNode = parentNode;
    }

    public boolean hasChildren(){
        int index = 0;

        while(index < children.length){
            if(children[index] != null) {
                return true;
            }
            index++;
        }
        return false;
    }

    public TrieNode nodeForLetter(char ch) {
        return children[ch - 97];
    }

    public boolean isEndOfWord() {
        return fullWord;
    }
}

public class Trie implements Iterable<String> {

    private int numOfNodes;
    private int numOfWords;
    private TrieNode root = new TrieNode(' ', null);

    public Trie() {
    }

    public void addWord(String s) {
        if (hasWord(s)) return;

        int index = 0;
        TrieNode iterator = root;

        while(index < s.length()){
            if(iterator.children[s.charAt(index) - 97] == null){
                iterator.children[s.charAt(index) - 97] = new TrieNode(s.charAt(index), iterator);
                numOfNodes++;
            }

            iterator = iterator.children[s.charAt(index) - 97];

            index++;

            if(index == s.length()){
                iterator.fullWord = true;
                numOfWords++;
            }
        }
    }

    // Issues on this one 
    public void deleteWord(String s) {
        if(s.length() == 0) return; 
        // make method to check for empty trie
        else if(!(hasWord(s))) return;
        else {
            TrieNode iterator = root;
            int index = 0;

            while(index < s.length()){
                if(iterator.children[index] != null){
                    /* What would (in pseudo code) need to be put here to account for this */
                }
            }
        }
    }

    public boolean hasWord(String s) {
        TrieNode current = root;

        while(current != null){
            for (int i = 0; i < s.length(); i++) {
                if(current.letter == ' ') return false; // error here probably
                else current = current.children[i];
            }
            if (current.fullWord == true) return true;
            else return false;
        }
        return false;
    }

    public Iterator<String> iterator() {
        return new TrieIterator();  // has basic iterator functions
    }
}

有什么想法吗?

【问题讨论】:

  • 所以如果我理解正确的话,如果我说删除“bat”我只想删除“bat”而不是“battery”或“combat”或“bats”?
  • Robert Sedgewick 在他的书中给出了一个简单的实现。我建议阅读该章节并查看his code
  • 您的实现方法使这过于复杂。如果您使用 Map&lt;Character, Node&gt; 而不是固定数组,则问题会容易得多(并且不限于 US_ASCII)。也就是说,如果您要删除的单词有孩子,您只需检查是否有孩子并翻转fullword 指示符。
  • @MarshallTigerus 没错。
  • @BrianRoach 我想保留数组实现。

标签: java trie


【解决方案1】:
public class TrieNode {

// a letter=='*' means end of word
// a letter=='\0x' means root node
protected char letter = ' ';
protected TrieNode[] children = new TrieNode[26];

public TrieNode(char letter){
    this.letter = letter;
}

public boolean hasChildren(){
    int index = 0;

    while(index < children.length){
        if(children[index] != null) {
            return true;
        }
        index++;
    }
    return false;
}

// don't understand the purpose of this 
public TrieNode nodeForLetter(char ch) {
    return children[ch - 97];
}

public boolean isEndOfWord() {
    return letter == '*';
}

public void deleteWord( String wordToBeDeleted )
{
     // append an asterisk will delete the end of 
     // the word without any special programming
     realDeleteWord( wordToBeDeleted + "*" ); 
}  // deleteWord

// this function will return true if this 
// object has to be deleted 
private boolean realDeleteWord( String wordToBeDeleted )
{
    if( wordToBeDeleted.isEmpty() ) 
        return; // simplest case 
    else
    {
       // split the word in the first character and the rest of 
       // string 
       char firstChar = wordToBeDeleted.charAt(0);
       String restOfWord = substr( wordToBeDeleted, 1, rest_of_string );

       // first you have to treat the rest of the word
       realDeleteWord( restOfWord )

       // next you have to treat the first char 
       // if I don't have any children, I have to delete myself
       if( ! hasChildren() && firstChar == letter ) 
       {
           // PENDING: THIS VERY OBJECT HAS TO BE DELETED, 
           // HOW TO IMPLEMENT THIS? RETURN TRUE TO INFORM THE PARENT?
           return true; 
       }
       else
       {
          // DO NOTHING: either there are children or 
          // this character is not the same as the one 
          // given as parameter
       } // hasChildren()...
    } 
} // realDeleteWord

}

Mmmmm...编程课的典型练习,是这样吗?请记住,递归是神圣的,迭代是人类的。

【讨论】:

  • 在这种情况下使用迭代器是目的,而不是递归。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2019-08-05
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多