2011-03-18 7 views
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 ("벤더")의 모든 요소를 ​​반환하지 않습니다은 compareTo (TestPerson 다음은 내 코드입니다 inf1010.assignment.IfiCollectionTest.assertCompareToEquals에서 거짓 inf1010.assignment.IfiCollectionTest.assertCompareToEquals에서 (IfiCollectionTest.java:74) (IfiCollectionTest.java:83) 에서 : ("튀김")) == 0 예상 : 사실 만했다 inf1010.assignment.IfiCollectionTest.assertCompareToEqualsNoOrder (IfiCollectionTest.java:100) at inf1010.assignment. IfiCollectionTest.toArray (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

귀하의 소스는 완전하지 않습니다. '현재'와'나는'선언 된 곳은 어디입니까? – RoToRa

+0

테스트 한 입력 내용과 출력 내용을 게시하십시오. –

답변

1

좋아, 나는 문제가 "글로벌"변수 current의 사용이라고 생각합니다. 그것이 설정된 방식은별로 의미가 없습니다. "현재"인 Node이 매개 변수에 제공된 값이기 때문에 어쨌든 필요하지 않습니다.

또한 함수 이름을 변경해야합니다. 여기서는 아무것도 분류하지 않고 나무의 내용 만 수집하므로 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; 
} 
+0

예, 당연히 현재 노드가 분명히 중복되었습니다 :)이 문제를 해결하기 위해 한 걸음 더 가까이있는 것처럼 보입니다. 이제 ArrayIndexOutOfBoundsException이 생깁니다. 내가 함께 일할 수있다;) –

+1

@Askel 당신이 그걸로 아무것도하지 않을 때 나는 collect 메소드에서 a를 리턴 할 때 그 점을 보지 못한다. 간단한 예 ... 왼쪽 노드 하나가있는 루트 ... collect (n, a) -> collect (n.left, a) -> a [0] = n.left.obj -> i ++ -> 스택에 대한 호출을 먼저 수집하려면 -> a [1] = n.obj -> return a ... toArray가 배열을 반환하므로 연결 메서드가 무효화됩니다. – DTing

+0

@kriegar : 좋은 지적입니다.나는 이것을 고려하여 대신 인덱스를 반환하도록 했으므로 "글로벌" "i"를 제거 할 수있었습니다. – RoToRa

0

나는 바이너리 검색 트리가 어떻게 작동 하는지를 체크하면, 항상 그것이 정렬된다는 것을 혼란스럽게 생각한다. 루트 노드에서 시작한 다음 새 노드를 삽입 할 때 값에 따라 적절한 위치 (즉, 왼쪽 또는 오른쪽)에 삽입합니다. 따라서 먼저 정렬을 호출해서는 안됩니다. 그래서 거기에서 시작해서 이진 검색 트리를 읽었습니다. 예를 들어 wikipedia에 괜찮은 기사가 있습니다.

업데이트 : 내 의견을 무시하면 안됩니다. 8, 3, 7, 9, 12, 2, 10, 1을 순서대로 트리에 삽입한다고 가정 해보십시오. 그것은이처럼 보이는 결국해야합니다 : 그것은이있는 경우없는 경우

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

당신이 순서를 얻을 루트에서 시작하는 것을 의미 그것을 보면, 다음 왼쪽에 노드가 왼쪽에 도착, 자신을 반환하고 값이 있으면 오른쪽으로 이동하십시오. 발생하는 각 노드에 대해이를 반복합니다.

+0

그 점을 이해합니다. 그리고 요소를 올바르게 추가했는지 확신합니다. 적어도 add() - 메소드는 테스트를 통과했다. 그러나 여전히 요소를 포함하는 노드를 배열에 올바르게 추가하려면 알고리즘을 필요로합니다 (최소에서 최대). –

+0

@Aksel 당신이 제안하는 것은 숫자를 두 번 정렬하는 것과 같습니다. 이진 검색 트리에 트리에있는 최소값 (매번 맨 왼쪽)을 반환하고 트리에서 제거하는 메서드를 작성하지 마십시오. 비어있을 때까지 값을 배열로 만듭니다. –

+0

아마 좋은 생각 일 것입니다.하지만 선생님에게서 재귀 적 방법 팁을 얻었습니다. 그리고 그것을 얻지 못한다고 저를 괴롭 힙니다. 그리고 [wikipedia article] (http://en.wikipedia.org/wiki/Binary_search_tree#Traversal)에서 내가 성취하고자하는 fassion에서 나무의 요소를 순서대로 검색하는 방법이 설명되어 있다고 언급했습니다. –

1

난 당신이 코드

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

을 가지고 있지만 난 당신이

a[i] = current.obj; 

을 할 때 얻을 수 있도록 현재 노드에서 다시 현재 설정 값하는 찾을 수 없습니다 참조 올바른 결과. 그것이 아마도 모든 결과를 얻지 못하는 이유 일 것입니다. 어쨌든 현재 (왜 당신이 게시 한 코드 조각에서) 현재는 클래스 변수가되어야하고 sort 메소드에서 선언 된 것이 아닌지를 알지 못합니다. 일반적으로 클래스 변수를 필요로하지 않는다면 클래스 변수를 사용해서는 안됩니다.

편집 : 당신도 당신이

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

또는 전혀 현재 사용하는 경우에 당신이 가진 것처럼 왼쪽 아이 종류를 호출 한 후 처리하는 노드로 전류를 설정할 수 있습니다

if (n.left != null) 
    sort(n.left, a); 
a[i] = n.obj; 
i++; 
if (n.right != null) 
    sort(n.right, a); 
+0

현재 노드에서 현재 백을 설정하는 방법을 자세히 설명해 주시겠습니까? –

0

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

뭐 가장 쉬운 방법 같은 당신이 찾고있는 것은 inorder 트리를 횡단하여 ArrayList에 추가하는 것입니다. 배열을 얻으려면 arrayList의 .toArray() 메서드를 호출하면됩니다.

arraylist를 사용할 수없고 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) 
    } 
} 
관련 문제