java - 重写迭代器?

时间:2014-04-23 22:17:06

标签: java iterator iteration trie

老实说,我已经花了几天时间看着这个并试图解决这个问题,但是已经很短了。目标是查看trie节点是否具有下一个节点,如果是这样的话。

它所在的地方:

public Iterator<String> iterator() {
    return new TrieIterator();
}

调用它来实现我自己的迭代器。我已经尝试在数组+ 1中使用一个位置来表示hasNext(),同时将事物与大小,数字或节点以及子项进行比较,并且做得很短。我最近的尝试是(下面)的,但是没有用。

hasNext() {
return this.children.hasChildren(); /* doesn't work */
} 

public class TrieIterator implements Iterator<String> {

    public TrieIterator(){
    }

    public boolean hasNext() {
        return false;
    }

    public String next() {

        return null;
    }

    public void remove() {
         throw new UnsupportedOperationException();
    }
}

这里也是trieNode类:

public class TrieNode {

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

    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 letter == '*';
    }
}

并添加和删除如下:

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

    int index = 0;
    TrieNode current = root;
    char[] letters = s.toCharArray();

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

        current = child;
        index++;

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

public void deleteWord(String s) {
    if(s.length() == 0) return;
    if(size() == 0) return;
    if(!hasWord(s)) return;

    TrieNode current = root;
    for (char ch : s.toCharArray()) {
        TrieNode child = current.children[s.charAt(ch) - 97];
        if(child.prefixes == 1){
            child = null;
            return;
        }
        else{
            child.prefixes--;
            current = child;
        }
    }
    current.fullWord = false;
}

public boolean hasWord(String s) {
    if(size() == 0) return false;

    char[] letters = s.toCharArray();
    int l = letters.length;
    TrieNode current = root;

    int i;
    for (i = 0; i < l; i++){
        if (current == null) return false;
        current = current.children[letters[i] - 97];
    }

    if (i == l && current == null) return false;
    if (current != null && !current.fullWord) return false;

    return true;
}

请不要改变特里的当前实施情况:)

1 个答案:

答案 0 :(得分:0)

您使用hasNext()实施this.children.hasChildren();的尝试不会奏效,因为childrenTrieNode的数组,所以它没有任何hasChildren() {1}}方法。

hasChildren()方法是TrieNode的方法,而不是children数组。

您需要跟踪当前节点,当前节点中的位置以及到目前为止看到的所有字符。如果有更多的单词,hasNext()应该返回true,这意味着如果节点是一个完整的单词,或者它是否有任何尚未访问过的完整单词的子节点。 (但是,我假设叶子节点总是满字,所以后一个测试可能只是节点有任何尚未访问过的子节点。)

您需要决定是否会在较长的单词之前返回较短的单词(一旦到达完整的单词节点,或者仅在访问其子单元后,您是从next()返回单词吗?)您将还需要维护一堆节点,以便在您下降到子节点后,可以返回到父节点中的先前位置。

这不是一项微不足道的任务。我建议从一个非常小的单词构建的Trie开始(例如&#34; a&#34;,&#34;&#34;和&#34; at&#34;)并完全获得在你移到三个字母或更多单词之前调试。

(如果你在迭代过程中修改了Trie,你也应该考虑你打算做什么。标准java.util类会在每次修改时更新一个计数器,并测试它没有&#39 ;在迭代器中进行了更改。如果有,则抛出ConcurrentModificationException。使用此策略的迭代器称为 fail-fast iterators 。)