【问题标题】:Does PriorityQueue's remove method rearrange the heap?PriorityQueue 的 remove 方法是否重新排列堆?
【发布时间】:2013-10-08 02:41:36
【问题描述】:

当在 java 中对 PriorityQueue 对象调用 remove 方法时,会移除堆的头部。要将新的最小元素放在头部,是否对堆的其余部分进行了排序操作?比如调用remove时是否调用了compareTo方法?

抱歉,如果这是在文档中,我在任何地方都找不到。提前致谢。

【问题讨论】:

  • 我刚刚检查了文档,并没有对此进行任何指定。我很想知道答案!
  • 谢谢,很高兴知道我没有遗漏任何太明显的东西!

标签: java sorting queue compare heap


【解决方案1】:

PriorityQueue 实现为一个平衡的二进制堆,实现为一个数组。当一个元素被移除时,堆必须重新排序以保持堆的顺序。

证明在 cmets

/**
 * Priority queue represented as a balanced binary heap: the two
 * children of queue[n] are queue[2*n+1] and queue[2*(n+1)].  The
 * priority queue is ordered by comparator, or by the elements'
 * natural ordering, if comparator is null: For each node n in the
 * heap and each descendant d of n, n <= d.  The element with the
 * lowest value is in queue[0], assuming the queue is nonempty.
 */
private transient Object[] queue;

也在类 javadoc 中

实施说明:此实施提供O(log(n)) 时间 入队和出队方法(offer、poll、remove() 和 add); remove(Object) 和 contains(Object) 方法的线性时间;和 检索方法(peek、元素和大小)的恒定时间。

例如,对于remove(),您删除了堆的根。你取最后一个元素,即。二叉树最后一层最右边的叶子,并将其作为根并向下筛选,直到找到它的位置(基于Comparator)。这至少需要O(log n) 时间。

【讨论】:

  • 虽然我同意这是需要发生的,但文档中是否有任何内容证明这是实际发生的?跨度>
  • @templatetypedef 当它声明它被实现为一个堆时,重新排序必然需要发生。否则,它不是堆。您可以浏览其余的源代码以了解实现细节。
  • @templatetypedef,goo.gl/cCKOt3remove(Object o)的源代码,它实际上调用了indexOf(o)removeAt(i),其中前者进行O(n)搜索,后者进行O (log(n)) 筛选操作。
  • @lcn- remove 的特定实现不一定保证所需行为的任​​何内容,但感谢您的链接!
【解决方案2】:

这取决于。如果您是removeing 数组中支持PriorityQueue 的最后一个元素,则不会进行任何处理。如果您 remove 任何其他元素,它将重新排序其元素(siftUpsiftDown):

public boolean remove(Object o) {
    int i = indexOf(o);
    if (i == -1)
        return false;
    else {
        removeAt(i);
        return true;
    }
}

private E removeAt(int i) {
    assert i >= 0 && i < size;
    modCount++;
    int s = --size;
    if (s == i) // removed last element
        queue[i] = null;
    else {
        E moved = (E) queue[s];
        queue[s] = null;
        siftDown(i, moved);
        if (queue[i] == moved) {
            siftUp(i, moved);
            if (queue[i] != moved)
                return moved;
        }
    }
    return null;
}

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2010-10-17
    • 1970-01-01
    • 2011-05-04
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-12-02
    • 2023-02-10
    相关资源
    最近更新 更多