0

学校の課題では、ノード要素の配列を昇順で返すメソッドを完了することになっています。ノードは二分探索木で組み立てられているので、それらを正しくソートするために、ジョブを実行するための再帰的なメソッドを作成するためのヒントを得ました。

問題は、これがテスト出力に従ってコレクション内のすべての要素を生成しないことです(java.lang.AssertionError:toArray()はコレクション内のすべての要素を返しません)。

配列を処理する他の方法を思い付くことができず、再帰が機能するかどうかもよくわかりません。どんな助けでも大歓迎です。以下は私のコードです:

public class BinarySearchTree<E extends Comparable<E>> implements
    IfiCollection<E> {

    Node root;
    Node current;
    int size = 0;
    int i = 0;

    public class Node {
    E obj;
    Node left, right;

    public Node(E e) {
        obj = e;
    }

    } // END class Node

    [...]

    public E[] toArray(E[] a) {

    Node n = root;

    a = sort(n, a);
    return a;

    }

    public E[] sort(Node n, E[] a) { //, int idx, E[] a) {

    if (n.left != null) {
        current = n.left;
        sort(current, a);
    }


    a[i] = current.obj;
    i++;

    if (n.right != null) {
        current = n.right;
        sort(current, a);
        }

    return a;

    } // END public Node sort

    [...]

} // END class BinarySearchTree

テスト出力:

java.lang.AssertionError:toArray()は、コレクション内のすべての要素を返しません。:TestPerson( "Bender")。compareTo(TestPerson( "Fry"))== 0 expected:trueが、inf1010.assignmentでwas:false .IfiCollectionTest.assertCompareToEquals(IfiCollectionTest.java:74)at inf1010.assignment.IfiCollectionTest.assertCompareToEquals(IfiCollectionTest.java:83)at inf1010.assignment.IfiCollectionTest.assertCompareToEqualsNoOrder(IfiCollectionTest.java:100)at inf1010. IfiCollectionTest.java:202)

protected void assertCompareToEquals(TestPerson actual,
        TestPerson expected, String msg) {
            assertTrue(actual.compareTo(expected) == 0, String.format( // l:74
            "%s: %s.compareTo(%s) == 0", msg, actual, expected));
}

    [...]

protected void assertCompareToEquals(TestPerson[] actual,
        TestPerson[] expected, String msg) {
    for (int i = 0; i < actual.length; i++) {
        TestPerson a = actual[i];
        TestPerson e = expected[i];
        assertCompareToEquals(a, e, msg); // l:83
    }
}

    [...]

protected void assertCompareToEqualsNoOrder(TestPerson[] actual,
        TestPerson[] expected, String msg) {
    assertEquals(actual.length, expected.length, msg);

    TestPerson[] actualElements = new TestPerson[actual.length];
    System.arraycopy(actual, 0, actualElements, 0, actual.length);

    TestPerson[] expectedElements = new TestPerson[expected.length];
    System.arraycopy(expected, 0, expectedElements, 0, expected.length);

    Arrays.sort(expectedElements);
    Arrays.sort(actualElements);

    assertCompareToEquals(actualElements, expectedElements, msg); // l:100
}

    [...]

@Test(dependsOnGroups = { "collection-core" },
    description="Tests if method toArray yields all the elements inserted in the collection in sorted order with smallest item first.")
public void toArray() {
    TestPerson[] actualElements = c.toArray(new TestPerson[c.size()]);

    for (int i = 0; i < actualElements.length; i++) {
        assertNotNull(actualElements[i],
                "toArray() - array element at index " + i + " is null");
    }

    TestPerson[] expectedElements = allElementsAsArray();
    assertCompareToEqualsNoOrder(actualElements, expectedElements, // l:202
            "toArray() does not return all the elements in the collection.");

    Arrays.sort(expectedElements);
    assertCompareToEquals(actualElements, expectedElements,
            "toArray() does not return the elements in sorted order with "
                    + "the smallest elements first.");


    TestPerson[] inArr = new TestPerson[NAMES.length + 1];
    inArr[NAMES.length] = new TestPerson("TEMP");
    actualElements = c.toArray(inArr);
    assertNull(actualElements[NAMES.length],
            "The the element in the array immediately following the "
            + "end of the list is not set to null");
}

テストコードをもっと投稿する必要があるかどうかわかりません。非常に広範で、1つの投稿には少なすぎるかもしれません。

4

4 に答える 4

1

わかりました。問題は「グローバル」変数の使用にあると思いますcurrent。それが設定されている方法は、あまり意味がありません。Node「current」はパラメータで提供されるものであるため、とにかくする必要はありません。

また、関数の名前を変更することを検討する必要があります。ここでは何もソートせず、ツリーの内容を収集するだけなので、などの名前のcollect方が適しています。

public E[] toArray(E[] a) {
  Node n = root;
  a = collect(n, a);
  return a;
}

public E[] collect(Node n, E[] a) {

  if (n.left != null) {
    // If there is a left (smaller) value, we go there first
    collect(n.left, a);
  }


  // Once we've got all left (smaller) values we can
  // collect the value of out current Node.
  a[i] = n.obj;
  i++;

  if (n.right != null) {
    // And if there is a right (larger) value we get it next
    collect(n.right, a);
  }

  return a;
}

(免責事項:私はこれをテストしていません)


グローバルインデックスなしの代替実装:

public E[] toArray(E[] a) {
  Node n = root;
  collect(n, a, 0);
  return a;
}

public int collect(Node n, E[] a, int i) {

  if (n.left != null) {
    // If there is a left (smaller) value, we go there first
    i = collect(n.left, a, i);
  }


  // Once we've got all left (smaller) values we can
  // collect the value of out current Node.
  a[i] = n.obj;
  i++;

  if (n.right != null) {
    // And if there is a right (larger) value we get it next
    i = collect(n.right, a, i);
  }

  return i;
}
于 2011-03-18T13:07:59.003 に答える
1

私はあなたがコードを持っているのを見ます

if (n.left != null) {
        current = n.left;
        sort(current, a);
  }

しかし、どの時点で現在のノードに電流を戻したかがわからないようです。

a[i] = current.obj;

正しい結果が得られます。それがおそらく、すべての結果が得られない理由です。いずれにせよ、(少なくともあなたが投稿したコードフラグメントからは)currentがクラス変数である必要があり、sortメソッドで宣言されているだけではない理由はわかりません。一般に、クラス変数が本当に必要ない場合は、クラス変数を使用しないでください。

編集: このように左の子でsortを呼び出した後、処理しているノードに現在を戻すことができます

current = n;
a[i] = current.obj;
i++;

または、currentをまったく使用しないでください。その場合、次のようなものになります。

if (n.left != null)
    sort(n.left, a);
a[i] = n.obj;
i++;
if (n.right != null)
    sort(n.right, a);
于 2011-03-18T12:57:38.433 に答える
0

http://cs.armstrong.edu/liang/intro8e/html/BinaryTree.html

探していることを実行する最も簡単な方法は、ツリーを順番にトラバースしてArrayListに追加することです。配列を取得するには、arrayListの.toArray()メソッドを呼び出すことができます。

配列リストを使用できず、inordertraversalとincrementの外側でインデックスと配列を宣言できない場合は、配列を宣言するためにツリー内にある要素の数を知る必要があります。

擬似コード:

variables:
arraysize = root.count()
E[] inOrderNodeArray = new E[arraysize]
int index = 0

inorder traversal:
void inorder(Node n) {
    if (n) {
        inorder(n.left)
        inOrderNodeArray[index] = n
        index++
        inorder(n.right)
    }
}
于 2011-03-18T13:01:55.267 に答える
0

混乱しているのは、二分探索木がどのように機能するかを確認すると、常にソートされているということだと思います。ルートノードから開始し、新しいノードを挿入すると、値に応じて適切な位置(つまり、左または右)に挿入されます。したがって、最初にsortを呼び出す必要はありません。それで、私はそこから始めて、二分探索木を読み上げました。たとえば、ウィキペディアにはまともな記事があります。

更新:私のコメントは無視してください。そうする必要もありません。8、3、7、9、12、2、10、1をこの順序でツリーに挿入するとします。最終的には次のようになります。

      8
     / \
    3   9
   / \   \
  2   7   12
 /       /
1       10

それらを順番に取得することを意味する場合は、ルートから開始し、左側にノードがある場合は左側に移動し、そうでない場合はそれ自体を返し、値がある場合は右側に移動します。遭遇するノードごとにこれを繰り返します。

于 2011-03-18T12:30:17.877 に答える