这个问题在这里已有答案:
这里有两个问题。当我尝试使用“递归迭代器”遍历这个本地二叉树时(迭代遍历树的迭代器,将元素放入队列,然后从队列前面删除元素)。迭代器倾向于向后迭代(从最大到最小)而不是顺序(从最小到最大)。此外,当我尝试使用Scanner
从nextInt()
读取用户输入时,程序进入无限循环。当用户输入无效数字时,我正试图抓住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());
}
}
在BinaryTree类中,我尝试以递归方式遍历它(请参阅iterator()和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<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;
}
}
TreeNode类:
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;
}
}
数据类型(项目):
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
您的打印输出功能以相反的顺序打印节点,因为这是您存储它们的方式;你的二叉树在左边而不是在右边有较大的值,因为你的'add'函数中有一个“>”而不是“<”。改变它,它们出现增加而不是减少。
我仍然没有看到你无限循环的条件,我自己也没有。将程序放入调试器并跟踪它的运行情况,直到找到它为止。老实说,我认为我已经在这个问题上做得不够了(我没有Java 7并且不得不将它回填到Java 6来运行它),而且我还在继续。
好的,问题解决了。问题是,当我需要一个<
时,我输入了一个>
,所以我最后得到的是左边较大的值和右边较小的值,所以我的inorder
遍历是向后的。其次,捕捉InputMismatchException
引起的无限循环是Scanner
类中的一个错误:
in.nextInt()
块中的try
。InputMismatchException
,它会将流量转移到catch
块,这会将choice
设置为-1,从而导致显示无效的文本块。nextInt()
时,它会立即抛出异常而不是获取输入,如果将一个print语句添加到catch块中就可以看到。谢谢所有帮助过我的人。