常量大小优先级队列 - 先插入或先删除?

时间:2011-05-01 01:39:35

标签: c++ priority-queue

我使用priority_queue来存储到目前为止在K最近邻居搜索中找到的K个最近点。当我发现一个点比队列顶部的点更近时,我想弹出顶部元素并推送新元素。

if(point < pq.top()){
    pq.pop();
    pq.push(point);
}

一般来说,首先弹出然后插入是否更有效,或者首先插入然后弹出更有效?

2 个答案:

答案 0 :(得分:6)

如果您使用std::priority_queue作为优先级队列类,则默认情况下标准容器类std::vector用于其基础容器类。

通常,push首先pop首先效率低于priority_queue

原因

vector::push_back中推送一个元素将调用priority_queue,如果它超过当前容量,它可能会重新分配底层缓冲区。

原因二

  

priority_queue ::弹出

     

从中弹出元素时   pop_heap,它称之为   保持堆的pop_back算法   priority_queues的属性,然后   调用成员函数push_back   底层容器对象的   删除元素。

     

priority_queue ::推

     

将元素推送到   priority_queue,它调用成员   底层函数push_heap   容器对象,然后调用   保持堆的push算法   priority_queues的属性。

假设优先级队列中现在有 N 个元素。

如果您先push_heap,则会调用算法pop两次,分别调整 N + 1 N + 1 元素

如果先push_heap,则会调用算法{{1}}两次,分别调整 N N 元素。

<强>除了

如果您正在实施自己的优先级队列,这可能会节省性能。既然您已经使用top检查了值,我想知道您是否可以直接将元素与顶部交换而不调用push / pop,从而绕过堆调整算法。虽然可能不实用。

答案 1 :(得分:1)

@NullSet,

你正在实施一个K最近邻搜索,所以我假设表现是一个很大的问题

如果是这样,只需一个使用标准队列的提示,看看你是否可以用数组来支持它(我在这里超出了自己的深度)......我在猜这个固定大小的随机访问结构将比向量更有效。

然后,如果你的队列仍然是一个经过验证的性能瓶颈,我会看看基于btree(甚至是rbtree)的自我实现的优先级队列接口。

你走多远取决于你的最大 K 。如果 K 足够小,那么标准的矢量支持优先级队列将是最有效的可想到的解决方案。诀窍是观察正在运行的程序的实际性能,以确定那些可能为您的工作带来最佳性能改进的“改进机会”。

是的,我是算法赛车爱好者...它表明了吗?

干杯。基思。