我有一个将元素插入优先级队列的方法。我想知道它有性能时间。
我相信如果插入的元素可以放在队列的底部,它可以是O(1)。但是,如果要插入的元素是新的最小值并且一直渗透到根目录,它将在O(log N)时间运行。 这种推理是否正确?
以下是方法插入方法:
/**
* Insert into the priority queue, maintaining heap order.
* Duplicates are allowed.
* @param x the item to insert.
*/
public void insert( AnyType x )
{
if( currentSize == array.length - 1 )
enlargeArray( array.length * 2 + 1 );
// Percolate up
int hole = ++currentSize;
for( array[ 0 ] = x; x.compareTo( array[ hole / 2 ] ) < 0; hole /= 2 )
array[ hole ] = array[ hole / 2 ];
array[ hole ] = x;
}
答案 0 :(得分:0)
我会说“不”回答你的问题“这个推理是否正确?”通常,O()
表示法被视为算法的最坏情况复杂度的指示。有时它可用于平均情况复杂性,但很少用于最佳情况复杂性。 (有关您可以使用它的示例,请参阅here。)您认为在最佳情况下算法为O(1)
,但并非平均或最差O(1)
- 情况。
暂且不关心enlargeArray()
函数的复杂性(虽然它的摊销时间不是,但这可能会超过O(log N)
,但另一方面却不是“{1}}的一部分。”算法正确“无论如何,因为你总是可以预先分配数组”足够大“),我会说你的插入算法是O(log N)
,因为这是平均和最差情况的复杂性。
答案 1 :(得分:0)
Luiggi和mkrakhin都是正确的:如果你需要放大数组,那么的enlargeArray调用可以是O(n)
,但是既然你要保持数组的大小加倍,那么从长远来看它只会发生对数所以整个事情将分摊为O(log N)的次数。
但是,我认为你问的真正问题是,如果新元素是最小的,那么这个算法是O(1),答案是“是,只要你不需要调用enlargeArray” 。看到这种方式的方法是注意你将完全通过你的for循环0次,所以唯一的“完成的工作”将是:
int hole = ++currentSize;
array[0] = x;
array[hole] = x;
注意:我认为这似乎也表明了这种情况下的错误(你想在交换时把相同的元素放在数组的开头和结尾)。