2013-10-19 5 views
1

이제는 아무리 많은 도움을받을 수 있을지 모르겠습니다. 코드를 꽤 많이 사용하기 때문에 도움이되지만 크게 도움이 될 것입니다.바이너리 트리를 반복하는 동안 NullPointerException이 발생했습니다.

public class BTree implements Iterable<String> { 
    /** Left child */ 
    BTree left; 
    /** Right Child */ 
    BTree right; 
    /** Comparator to use for sorting */ 
    Comparator<String> comp; 
    /** Parent node */ 
    BTree parent; 
    /** String stored in this leaf */ 
    String s; 
    /** # of iterators currently working on it */ 
    int active = 0; 
    /** Size of the BTree */ 
    int size; 

public void build(Iterable<String> iter, int numStrings) { 
     if (this.active > 0) { 
      throw new ConcurrentModificationException(); 
     } 
     else { 
      Iterator<String> itr = iter.iterator(); 
      while (numStrings != 0 && itr.hasNext()) { 
       String s = itr.next(); 
       if (!this.contains(s)) { 
        this.insert(s); 
        this.size++; 
        numStrings--; 
       } 
      } 
     } 
    } 

/** 
* Inserts the string into the given BTree 
* @param str - String to insert 
*/ 
private void insert(String str) { 
    if (this.s.equals("")) { 
     this.s = str; 
    } 
    else if (this.comp.compare(str, this.s) > 0) { 
     if (this.right == null) { 
      BTree bt = BTree.binTree(this.comp); 
      bt.s = str; 
      this.right = bt; 
      bt.parent = this; 
     } 
     else { 
      this.right.insert(str); 
     } 
    } 
    else if (this.comp.compare(str, this.s) < 0) { 
     if (this.left == null) { 
      BTree bt = BTree.binTree(this.comp); 
      bt.s = str; 
      this.left = bt; 
      bt.parent = this; 
     } 
     else { 
      this.left.insert(str); 
     } 
    } 
} 



    private class BTreeIterator implements Iterator<String> { 
      /** Current BTree being iterated over */ 
      BTree current; 
      /** How many next() calls have there been */ 
      int count; 
      /** Size of the BTree */ 
      int max; 
      /** Constructor for BTreeIterator 
      * @param current 
      */ 
      BTreeIterator(BTree current) { 
       this.current = current; 
       this.count = 0; 
       this.max = current.size; 
       active++; 
      } 

      /** Returns true if there is another string to iterate over 
      * @return boolean 
      */ 
      public boolean hasNext() { 
       if (this.count != this.max) { 
        return true; 
       } 
       else { 
        active--; 
        return false; 
       } 
      } 

      /** 
      * Returns the next string in the iterator 
      * @return String 
      */ 
      public String next() { 
       if (this.count == 0) { 
        this.count++; 
        current = this.current.getLeftMost(); 
        if (this.current.s.equals("")) { 
         throw new NoSuchElementException(); 
        } 
        return this.current.s; 
       } 
       else if (this.current.right != null) { 
        this.current = this.current.right.getLeftMost(); 
        this.count++; 
        return this.current.s; 
       } 
       else { 
        BTree tree = this.current; 
        while (tree.parent.right == tree) { 
         tree = tree.parent; 
        } 
        this.current = tree.parent; 
        this.count++; 
        return this.current.s; 
       } 
      } 

      /** Throws an exception since we aren't removing anything from the trees 
      */ 
      public void remove() { 
       throw new UnsupportedOperationException(); 
      } 

     } 
    } 

}

예외가 반복자의 다음() 메서드의 while (tree.parent.right == tree) 줄에서 발생됩니다 : 여기 내 관련 코드입니다. 재미있는 점은, 24000 단어의 파일을 통해 사전 식 및 역순 사전 식 비교를하는 비교기로 코드가 잘 작동한다는 것입니다.

class StringWithOutPrefixByLex implements Comparator<String> { 

/** 
* compares o1 and o2 
* @param o1 first String in comparison 
* @param o2 second String in comparison 
* @return a negative integer, zero, or a positive integer 
*   as the first argument is less than, equal to, or 
*   greater than the second. 
*/ 
public int compare(String o1, String o2) { 
    String s1, s2; 
    if(o1.length() > 4){ 
     s1 = o1.substring(3); 
    } 
    else { 
     s1 = o1; 
    } 
    if(o2.length() > 4){ 
     s2 = o2.substring(3); 
    } 
    else { 
     s2 = o2; 
    } 
    return s1.compareTo(s2); 
} 
} 

심지어 괴상, 그것은 199 개 단어까지 같은 파일이 비교기와 함께 잘 작동하지만 최대한 빨리 가지고 그것이 나누기 200 개 단어 구축 : 다음 비교기를 사용하는 경우에만 예외를 발생 .

편집 : 나는 예외 인해 null입니다 tree.parent.righttree.parent 동안 참조하려고 코드이다 것으로 확인하지만, 그렇게하려고 왜 내가 알아낼 수 없습니다. 지금까지 내가 말할 수있는 한, 내 코드는 null을 호출하려고해서는 안됩니다 tree.parent, 아래 내 의견에 설명했다.

+1

Comparator에 try & catch를 추가하고 catch에 'o1'과'o2'의 값을 출력하면 "corner case"를 찾을 수 있습니다. 유일한 점은'o1' 또는'o2'가'null '('s1'이 어떻게 든'null'이고 마지막 행에 NPE가있는 것 같음) 인 경우를 처리하지 않는다는 것입니다. – alfasin

답변

0

글쎄, 실제로 코드를 충분히 표시하지는 않지만, BTree의 루트 노드는 어떻습니까? 루트 노드에있는 BTree.parent의 값은 무엇입니까? null? ,

   while (tree.parent.right == tree) { 
        tree = tree.parent; 
       } 

이 ... 루트 노드에이를 것이라고 treetree.parent로 설정됩니다 : 루트 노드가 부모가 null 경우

후,이 while 루프, 가능성이 높습니다 null이고, 따라서 while 루프 테스트는 tree.parent.right이 널 포인터를 역 참조하려고 시도하기 때문에 실패합니다.

+0

루트 부모가 null이지만 코드가 그 지점에 도달해서는 안됩니다. 최상위 노드에 올바른 하위 노드가있는 경우 'else if (this.current.right! = null)'이이를 catch해야합니다. 그것이 올바른 아이를 가지지 않는다면, 반복 될 마지막 노드 여야하고, hasNext()는 거짓이어야하며, tree.parent를 호출하는 것을 멈추어야한다. – Kaptain

관련 문제