我必须错过非常简单的东西,因为这让我大吃一惊!
我正在尝试使用CompleteBinaryTree(使用数组实现)实现Heap。此CompleteBinaryTree是一个Position<T>
数组,其中每个Position
包含一个元素。我正在编写堆的add(T t)
方法,其中t
被插入到CompleteBinaryTree的下一个自由位置,然后执行一个upheap过程,直到订购了CompleteBinaryTree。这是方法:
private CompleteBinaryTree<T> tree = new CompleteBinaryTree<T>();
private Position<T> entry = null;
public void add(T t) {
entry = tree.add(t);
if (entry.equals(tree.root())) {
return;
}
//continue to swap inserted element with its parent
//while it is smaller than its parent
while (entry.element().compareTo(tree.parent(entry).element()) < 0) {
Position<T> parent = tree.parent(entry);
Position<T> temp = entry;
entry = parent;
parent = temp;
}
}
将第一个元素添加到Heap中,但是当我尝试添加第二个元素时,InvalidPositionException
行会引发while()
。这是从CompleteBinaryTree类中抛出异常的地方:
public Position<T> parent(Position<T> p) {
if (p == root()) throw new InvalidPositionException();
return array[((ArrayPosition) p).index/2];
}
以下是CompleteBinaryTree
使用的另外两种方法:
public Position<T> root() {
if (isEmpty()) throw new InvalidPositionException();
return array[1];
}
public Position<T> add(T t) {
if (last == array.length) {
// extend array
ArrayPosition[] temp = (ArrayPosition[]) new Object[array.length*2];
for (int i=1; i < array.length; i++) {
temp[i] = array[i];
}
array = temp;
}
array[last] = new ArrayPosition(last, t);
return array[last++];
}
当我第一次检查p是否为根时,我是如何因为p == root()
而抛出异常?
修改
这是FullBinaryTree toString()
,由堆toString()
返回:
public String toString() {
StringBuffer buf = new StringBuffer();
for (int i = 1; i < last; i++) {
buf.append(" ").append(array[i]);
}
return buf.toString();
}
答案 0 :(得分:2)
当我第一次检查p是否为root时,如何抛出异常,因为p == root()?
但是不检查每个tree.parent()
参数以查看它是否为root。您只检查传递给该方法的第一次调用的参数。每次执行while
循环的主体时,它都会将entry
设置为新值,当循环循环时,您将新的未选中循环值传递给tree.parent()
。实际上,entry
的每个新值都比前一个更接近根,因为整个点是将树从子向上移动到父,即向根移动。很可能有时这个程序会到达根目录,而且树中已经存在的元素越少,就越有可能。
解决此问题的一种方法是将根检查移至while
条件:
while (!entry.equals(tree.root())
&& entry.element().compareTo(tree.parent(entry).element()) < 0) {
// ...
}
在这种情况下,当然,您不需要在循环外执行的当前一次性检查。