如果您使用的是 Sun 实现,则它是O(log(n))
. 从Javadocs:
实现说明:此实现为入队和出队方法( offer
、poll
和)提供 O(log(n)) 时间;和
方法的线性时间;检索方法(、和)的固定时间。remove()
add
remove(Object)
contains(Object)
peek
element
size
其他实现可能具有不同的复杂性。
编辑: Javadocs 没有涵盖使用迭代器删除元素的性能,所以我不得不查找源代码。这都与 Sun 的实现相关,并且可能在 Apple 的版本、GNU Classpath 等方面有所不同。 Sun 的源代码可在此处获得;它也包含在 JDK 中,因此您可能已经安装了它。
在PriorityQueue
的迭代器中,默认情况remove()
是调用PriorityQueue.removeAt(lastRet)
,其中lastRet
是最后一次返回的索引next()
。removeAt()
似乎是O(log(n))
最坏的情况(它可能必须筛选队列,但不必迭代)。
但是,有时会发生不好的事情。从以下评论removeAt()
:
/**
* Removes the ith element from queue.
*
* Normally this method leaves the elements at up to i-1,
* inclusive, untouched. Under these circumstances, it returns
* null. Occasionally, in order to maintain the heap invariant,
* it must swap a later element of the list with one earlier than
* i. Under these circumstances, this method returns the element
* that was previously at the end of the list and is now at some
* position before i. This fact is used by iterator.remove so as to
* avoid missing traversing elements.
*/
当返回一个非空元素时removeAt()
,迭代器将它添加到一个特殊的队列中供以后使用:当迭代器用完队列中的元素时,它会遍历这个特殊的队列。当remove()
在迭代的第二阶段调用时,迭代器调用PriorityQueue.removeEq(lastRetElt)
,其中lastRetElt
是从特殊队列返回的最后一个元素。removeEq
被迫使用线性搜索来找到要删除的正确元素,这使得O(n)
. 但是它可以使用==
而不是检查元素.equals()
,因此它的常数因子低于PriorityQueue.remove(Object)
。
因此,换句话说,使用迭代器删除在技术上是O(n)
,但实际上它应该比remove(Object)
.