2013-03-11 94 views
0

這裏有兩個問題。當我嘗試使用「遞歸迭代器」(遞歸遍歷樹的迭代器,將元素放入隊列中,然後從隊列前端移除元素)來遍歷這個自制的二叉樹時。迭代器傾向於向後迭代(最大到最小)而不是inorder(從最小到最大)。另外,當我嘗試使用nextInt()Scanner讀取用戶輸入時,程序進入無限循環。當用戶輸入一個無效的號碼時,我試圖抓住InputMismatchException
在下面的代碼段中,當用戶沒有輸入數字以便程序正常繼續時,我正在捕獲InputMismatchException。
測試文件:從循環中的掃描儀讀取時,會進入無限循環

package assignments.unit9; 
import java.util.*; 
import static java.lang.System.*; 
import java.io.*; 
public class BinaryTreeTest 
{ 
    private static BinaryTree<Item> tree; 
    static Scanner user; 

    public static void main(String... args) 
    { 
     user = new Scanner(System.in); 
     int choice; 
     do 
     { 
      out.println("1. Read data from disk"); 
      out.println("2. Print the tree in order"); 
      out.println("3. Search the tree"); 
      out.println("4. Delete from the tree"); 
      out.println("5. Count the nodes in the tree"); 
      out.print("0. Quit\n>"); 
      try 
      { 
       choice = user.nextInt(); 
      } 
      catch(InputMismatchException e) 
      { 
       choice = -1; 
      } 
      switch(choice) 
      { 
       case 0: 
        exit(0); 
       case 1: 
        try 
        { 
         readFromDisk(); 
        } 
        catch(FileNotFoundException e) 
        { 
         err.println("Sorry, but the file could not be opened: " + e.getMessage()); 
        } 
        break; 
       case 2: 
        if(tree == null) 
        { 
         err.println("Must read file first"); 
         break; 
        } 
        printTree(); 
        break; 
       case 3: 
        if(tree == null) 
        { 
         err.println("Must read file first"); 
         break; 
        } 
        searchTree(); 
        break; 
       case 4: 
        if(tree == null) 
        { 
         err.println("Must read file first"); 
         break; 
        } 
//     deleteFromTree(); 
        break; 
       case 5: 
        if(tree == null) 
        { 
         err.println("Must read file first"); 
         break; 
        } 
        countNodes(); 
        break; 
       default: 
        err.println("Invalid choice. The available choices are:"); 
        break; 
      } 
     } 
     while(choice != 0); 
    } 

    public static void readFromDisk() throws FileNotFoundException 
    { 
     Scanner file = new Scanner(new File("file20.txt")); 
     tree = new BinaryTree<Item>(); 
     if(file.hasNextInt()) 
      file.nextInt(); //skip the first integer 
     while(file.hasNextInt()) 
     { 
      tree.add(new Item(file.nextInt(), file.nextInt())); 
     } 
    } 

    public static void printTree() 
    { 
     tree.inorder(); 
    } 

    public static void searchTree() 
    { 
     out.println("Enter ID value to search for (-1 to return)"); 
     int search; 
     Item searched; 
     while((search = user.nextInt()) != -1) 
     { 
      out.println(searched = tree.find(new Item(search, 0))); 
      if(searched == null) 
       out.println("\b\b\b\b\bNo such part in stock"); 
     } 
    } 

    public static void countNodes() 
    { 
     out.println(tree.countNodes()); 
    } 
} 

這裏,在二叉樹類,我嘗試遞歸遍歷(參見迭代器()和asQueue()):

package assignments.unit9; 
import java.util.*; 
public class BinaryTree<E extends Comparable<E>> implements Iterable<E> 
{ 
    private TreeNode<E> root; 

    public void add(E value) 
    { 
     if(root == null) 
     { 
      root = new TreeNode<E>(value); 
     } 
     else 
     { 
      TreeNode<E> temp = root, upFrom = null; 
      boolean goesOnLeft = false; 
      while(true) 
      { 
       if(temp == null) 
       { 
        if(goesOnLeft) 
         upFrom.setLeft(new TreeNode<E>(value)); 
        else 
         upFrom.setRight(new TreeNode<E>(value)); 
        break; 
       } 
       else if(temp.getValue().compareTo(value) < 0) //goes on left 
       { 
        upFrom = temp; 
        temp = upFrom.getLeft(); 
        goesOnLeft = true; 
        continue; 
       } 
       else //goes on right 
       { 
        upFrom = temp; 
        temp = upFrom.getRight(); 
        goesOnLeft = false; 
        continue; 
       } 
      } 
     } 
    } 

    public void inorder() 
    { 
     try 
     { 
      inorder(root); 
     } 
     catch(StackOverflowError e) 
     { 
      System.err.println("Increase stack size to print remaining elements"); 
     } 
    } 

    private void inorder(TreeNode<E> t) 
    { 
     if(t == null) 
      return; 
     inorder(t.getLeft()); 
     System.out.println(t.getValue()); 
     inorder(t.getRight()); 
    } 

    private ArrayDeque<E> asQueue(TreeNode<E> t, ArrayDeque<E> toAdd) 
    { 
     try 
     { 
      if(toAdd == null) 
       toAdd = new ArrayDeque&lt;E>(); 
      if(t == null) 
       return toAdd; 
      asQueue(t.getLeft(), toAdd); 
      toAdd.addLast(t.getValue()); 
      asQueue(t.getRight(), toAdd); 
      ret: 
      return toAdd; 
     } 
     catch(StackOverflowError e) 
     { 
      throw new InternalError(); 
     } 
    } 

    public Iterator<E> iterator() 
    { 
     return new Iterator<E>() 
     { 
      private ArrayDeque<E> d = asQueue(root, null); 

      public E next() 
      { 
       return d.pop(); 
      } 

      public boolean hasNext() 
      { 
       return !d.isEmpty(); 
      } 

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

    public int countNodes() 
    { 
     int toReturn = 0; 
     for(E elem : this) 
      ++toReturn; 
     return toReturn; 
    } 

    public E find(E toFind) 
    { 
     for(E elem : this) 
     { 
      if(elem.equals(toFind)) 
       return elem; 
     } 
     return null; 
    } 
} 

樹節點類:

package assignments.unit9; 
import java.util.Objects; 
public class TreeNode<T> 
{ 
    private T value; 
    private TreeNode<T> left, right; 

    /** 
    * Constructs a new TreeNode value with the left and right pointers {@code null}. 
    * 
    * @param value the item to be referenced 
    * 
    * @throws NullPointerException if {@code value} is {@code null}. 
    */ 
    public TreeNode(T value) 
    { 
     this.value = Objects.requireNonNull(value); 
    } 

    /** 
    * Constructs a new TreeNode value with the specified left and right pointers. 
    * 
    * @param value the item to be referenced 
    * @param left the TreeNode value to the left. 
    * @param right the TreeNode value to the right. 
    * 
    * @throws NullPointerException if {@code value} is {@code null}. 
    */ 
    public TreeNode(T value, TreeNode<T> left, TreeNode<T> right) 
    { 
     this.value = Objects.requireNonNull(value); 
     this.left = left; 
     this.right = right; 
    } 

    public T getValue() 
    { 
     return value; 
    } 

    public TreeNode<T> getLeft() 
    { 
     return left; 
    } 

    public TreeNode<T> getRight() 
    { 
     return right; 
    } 

    public void setValue(T value) 
    { 
     this.value = Objects.requireNonNull(value); 
    } 

    public void setLeft(TreeNode<T> left) 
    { 
     this.left = left; 
    } 

    public void setRight(TreeNode<T> right) 
    { 
     this.right = right; 
    } 
} 

數據類型(Item):

package assignments.unit9; 
import java.util.*; 
public class Item implements Comparable<Item> 
{ 

    private int myID; 
    private int myInv; 

    //Comparators 
    public static class IDComparator implements Comparator<Item> 
    { 
     public int compare(Item i1, Item i2) 
     { 
      return i1.getID() - i2.getID(); 
     } 

     @Override 
     public boolean equals(Object obj) 
     { 
      return obj instanceof IDComparator; 
     } 
    } 

    public static class InvComparator implements Comparator<Item> 
    { 
     public int compare(Item i1, Item i2) 
     { 
      return i1.getInv() - i2.getInv(); 
     } 

     @Override 
     public boolean equals(Object obj) 
     { 
      return obj instanceof InvComparator; 
     } 
    } 

    public Item(int id, int inv) 
    { 
     myID = id; 
     myInv = inv; 
    } 

    public int getID() 
    { 
     return myID; 
    } 
    public int getInv() 
    { 
     return myInv; 
    } 
    public int compareTo(Item i) 
    { 
     if(i == null) 
      throw new NullPointerException(); 
     return this.myID - i.myID; 
    } 

    @Override 
    public boolean equals(Object otherObject) 
    { 
     Item i; 
     try 
     { 
      i = (Item) otherObject; 
      return myID == i.myID; 
     } 
     catch(ClassCastException ex) 
     { 
      return false; 
     } 
    } 
    public String toString() 
    { 
     return "ID: " + myID + "\tInventory number: " + myInv + "\n"; 
    } 

    @Override 
    public int hashCode() 
    { 
     return Objects.hash(myID, myInv); 
    } 
} 

這裏是輸入文件。很抱歉,如果這是一個很大:

20 
     196  60 
    18618  64 
     2370  65 
    18410  56 
    18465  27 
    19967  45 
    17911  96 
     184  14 
    18871  69 
    14088  92 
    18061   3 
     206  31 
    13066   8 
    12705  14 
    15917  51 
    15814  60 
    15320  82 
     8303  90 
     7282  73 
    12328  63 
+0

當您輸入'0'作爲輸入時,您的程序是否退出? – 2013-03-11 18:09:33

回答

0

好的,問題解決了。事情是,我輸入<當我需要一個>,所以我最後的較大的值在左邊,較小的值在右邊,所以我的inorder遍歷是倒退。其次,造成捕InputMismatchException無限循環是在Scanner類錯誤:

  1. 程序啓動,啓動它調用in.nextInt()在 的try塊循環。
  2. 當用戶輸入一個非數字,則掃描 拋出InputMismatchException,其轉向流向 catch塊,它設置choice爲-1這導致無效 文本塊被示出。
  3. 但是,什麼是奇怪的是,在未來的 迭代,當nextInt()被調用時,它會立即拋出一個異常 不但得不到輸入,可如果打印 語句添加到catch塊中可以看出。 謝謝大家誰幫助我。
1

您的打印輸出功能,打印以相反的順序節點,因爲這就是你將它們存儲的方式;你的二叉樹在左邊有較大的值,而不是右邊,因爲你在'add'函數中有一個「>」而不是「<」。改變這一點,他們出來增加而不是減少。

我還沒有看到你得到一個無限循環的條件,我沒有自己得到一個。將程序放入調試器並跟蹤它的發生位置,直到找出結果。我真的認爲我已經在這個問題上做了足夠的工作(我沒有Java 7並且必須回填到Java 6來運行它),而且我正在繼續。

+0

謝謝,這有幫助。當用戶在選擇菜單中輸入不是數字的東西時,我會遇到無限循環。 – gparyani 2013-03-12 17:07:39