wei*_*yin 7 java queue collections performance
假设我有一个java PriorityQueue(java实现为堆),我根据某些条件迭代删除元素:
PriorityQueue q = new PriorityQueue();
...
Iterator it = q.iterator();
while(it.hasNext()){
if( someCriterion(it.next()) )
it.remove();
}
Run Code Online (Sandbox Code Playgroud)
每个remove()操作需要多长时间?我不确定它是O(log(n))还是O(1).
Mic*_*ers 10
如果你正在使用Sun实现,那就是来自Javadocs:O(log(n)).
实现注意事项:此实现提供了O(日志(n))的时间和入队方法dequeing( ,,
offer和); 和 方法的线性时间; 和恒定时间检索方法(,,和).pollremove()addremove(Object)contains(Object)peekelementsize
其他实现可能具有不同的复杂性
编辑: Javadocs没有涵盖使用迭代器删除元素的性能,所以我不得不查找源代码.这一切都与Sun的实现有关,可能在Apple的版本,GNU Classpath等方面有所不同.Sun的源代码可在此处获得 ; 它也包含在JDK中,因此您可能已经安装了它.
在PriorityQueue's迭代器中,默认情况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.
*/
Run Code Online (Sandbox Code Playgroud)
当返回非null元素时removeAt(),迭代器将其添加到特殊队列以供以后使用:当迭代器耗尽队列中的元素时,它将遍历此特殊队列.在remove()迭代的第二阶段调用时PriorityQueue.removeEq(lastRetElt),迭代器调用,其中lastRetElt是从特殊队列返回的最后一个元素.removeEq被迫使用线性搜索来找到要删除的正确元素,这就是它O(n).但它可以使用==而不是检查元素.equals(),因此它的常数因子低于PriorityQueue.remove(Object).
因此,换句话说,使用迭代器进行删除在技术上是合理的O(n),但实际上它应该比它快得多remove(Object).
| 归档时间: |
|
| 查看次数: |
6216 次 |
| 最近记录: |