在学校作业中,我应该完成一个应该返回数组的方法 节点元素按升序排列。节点在二叉搜索树中组装,因此为了正确排序,我得到了一个提示,以创建一个递归方法来完成这项工作。
问题是,根据测试输出,这甚至不会产生集合中的所有元素(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 expect:true但是:false at inf1010.assignment.IfiCollectionTest.assertCompareToEquals(IfiCollectionTest.java:74) at inf1010.assignment.IfiCollectionTest.assertCompareToEquals(IfiCollectionTest.java:83) at inf1010.assignment.IfiCollectionTest.assertCompareToEqualsNoOrder(IfiCollectionTest.java:100) 在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");
}
我不知道是否应该发布更多的测试代码,它是相当广泛的,对于一个帖子来说可能有点太多了?
答案 0 :(得分:1)
我看到你有代码
if (n.left != null) {
current = n.left;
sort(current, a);
}
但我似乎无法找到你在当前节点设置电流的时间点,以便在你做的时候
a[i] = current.obj;
你得到了正确的结果。这可能就是为什么你没有得到所有的结果。在任何情况下,我都没有看到(至少从您发布的代码片段中)为什么当前需要是一个类变量,而不仅仅是在sort方法中声明。一般来说,如果你真的不需要它们,你不应该使用类变量。
修改强> 您可以在对左侧子项调用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);
答案 1 :(得分: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;
}
答案 2 :(得分:0)
我认为你感到困惑的是,如果你看看二叉搜索树是如何工作的,那么它总是被排序。从根节点开始,然后在插入新节点时,根据值将其插入适当的位置(即向左或向右)。所以你不应该开始调用sort。所以我会从那里开始,阅读二进制搜索树。例如,wikipedia有一篇不错的文章。
更新:忽略我的评论你不应该这样做。假设您按顺序将8,3,7,9,12,2,10,1插入树中。它应该看起来像这样:
8
/ \
3 9
/ \ \
2 7 12
/ /
1 10
如果你看它意味着按顺序启动它们,从根开始,然后如果它左边有一个节点到左边,如果没有,则返回自己,如果它有一个,则向右移动值。为您遇到的每个节点重复此操作。
答案 3 :(得分:0)
http://cs.armstrong.edu/liang/intro8e/html/BinaryTree.html
执行所需操作的最简单方法是按顺序遍历树并附加到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)
}
}