【问题标题】:Program throwing an exception after I check for the exception检查异常后程序抛出异常
【发布时间】:2016-07-21 14:53:41
【问题描述】:

我一定错过了一些非常简单的东西,因为这让我大吃一惊!

我正在尝试使用 CompleteBinaryTree(使用数组实现)来实现堆。这个 CompleteBinaryTree 是一个 Position<T> 数组,其中每个 Position 包含一个元素。我正在为Heap编写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;
        }
    }

第一个元素被很好地添加到堆中,但是当我尝试添加第二个元素时,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() 而引发异常?

编辑

这里是 CompleteBinaryTree toString(),它是由 Heap 返回的 toString():

public String toString() {
    StringBuffer buf = new StringBuffer();

    for (int i = 1; i < last; i++) {
        buf.append(" ").append(array[i]);
    }

    return buf.toString();      
}

【问题讨论】:

  • root() 可能是在扔。
  • 但是在抛出异常之前,如果entry是根,则方法返回,但是由于entry是根,所以抛出异常?
  • 你调试了吗? if (p == root()) 或 if (isEmpty()) 是否引发异常,最好将 throw new InvalidPositionException(); 移动到新行

标签: java arrays exception heap binary-tree


【解决方案1】:

当我第一次检查 p 是否为根时,我如何因为 p == root() 而引发异常?

但您不检查每个tree.parent() 参数以查看它是否为root。您只检查传递给该方法的第一次调用的参数。每次执行while 循环的主体时,它会将entry 设置为一个新值,并且当循环循环时,您将该新的未经检查的值传递给tree.parent()。实际上,entry 的每个新值都比前一个值更接近根,因为整个重点是从子树向上移动到父树,即向根移动。有时这个过程很可能会到达根节点,这更有可能是树中已经存在的元素越少。

解决此问题的一种方法是将根检查移至while 条件:

while (!entry.equals(tree.root())
        && entry.element().compareTo(tree.parent(entry).element()) < 0) {
    // ...
}

当然,在这种情况下,您不需要在循环外执行当前的一次性检查。

【讨论】:

  • 啊,是的,我从来没有想过。这一切都说得通,而且现在一切似乎都在正常运转。谢谢
  • 但是,似乎没有对堆进行排序。当我将元素添加到堆中然后打印堆的状态时,它的排序方式与我将元素插入其中的方式相同。此外,无论我将什么元素添加到堆中 - 如果我在每次插入后打印根的值,它始终是我插入的第一个元素的值(这对我来说毫无意义,因为它在抛出异常之前新插入的元素被交换到根位置)。请参阅我的原始帖子,我将在其中添加 'toString()' 方法
  • @KOB,那个额外的问题不是这个问题的主题,但我仍然观察到,虽然你的 add() 方法从叶子到根遍历树,但它似乎没有做任何重新排序的事情任何节点。特别是,entry = parent 之类的代码不会这样做——它只是更改了 entry 引用的节点局部变量。有可能你也想交换Positions 的内容,但这是我的推测。
  • 你解释得很好。我将其更改为交换值,现在一切正常。谢谢
猜你喜欢
  • 1970-01-01
  • 2015-03-10
  • 1970-01-01
  • 1970-01-01
  • 2011-12-12
  • 2013-05-24
  • 2013-08-23
  • 2011-06-01
  • 1970-01-01
相关资源
最近更新 更多