0

ここに2つの問題があります。「再帰的イテレータ」(ツリーを再帰的にトラバースし、要素をキューに入れてから、キューの先頭から要素を削除するイテレータ)を使用して、この自家製のバイナリツリーをトラバースしようとすると。イテレータは、順序どおり(最小から最大)ではなく、逆方向(最大から最小)に反復する傾向があります。また、Scannerusingからユーザー入力を読み取ろうとする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&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;
    }
}

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
4

2 に答える 2

1

printout関数は、ノードを保存する方法であるため、ノードを逆の順序で印刷します。'add'関数に"<"ではなく">"があるため、バイナリツリーの値は右側ではなく左側に大きくなります。それを変えると、減少するのではなく増加するようになります。

無限ループが発生する条件はまだわかりませんし、自分でも取得できません。プログラムをデバッガーに入れて、理解するまでどこに行くのかを追跡します。私は正直に言って、この質問については十分に行ったと思います(Java 7を持っておらず、実行するためにJava 6に埋め戻す必要がありました)。次に進みます。

于 2013-03-12T11:07:35.137 に答える
0

さて、問題は解決しました。<問題は、必要なときにa>と入力したため、左側が大きい値、右側が小さい値になってしまうため、inorderトラバーサルが逆方向になりました。第二に、キャッチによって引き起こされた無限ループは、クラス InputMismatchExceptionのバグでした。Scanner

  1. プログラムが起動in.nextInt()し、tryブロックを呼び出すループが開始されます。
  2. ユーザーが非数値を入力すると、スキャナーはをスローします。これにより、InputMismatchExceptionフローが catchブロックに転送され、-1に設定choiceされて、無効なテキストブロックが表示されます。
  3. しかし、奇妙なことに、次の反復で、nextInt()が呼び出されると、入力を取得する代わりにすぐに例外がスローされます。これは、printステートメントがcatchブロックに追加された場合に表示されます。これについて私を助けてくれたすべての人に感謝します。
于 2013-03-13T01:37:14.097 に答える