我使用priority_queue
来存储到目前为止在K最近邻居搜索中找到的K个最近点。当我发现一个点比队列顶部的点更近时,我想弹出顶部元素并推送新元素。
if(point < pq.top()){
pq.pop();
pq.push(point);
}
一般来说,首先弹出然后插入是否更有效,或者首先插入然后弹出更有效?
答案 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 足够小,那么标准的矢量支持优先级队列将是最有效的可想到的解决方案。诀窍是观察正在运行的程序的实际性能,以确定那些可能为您的工作带来最佳性能改进的“改进机会”。
是的,我是算法赛车爱好者...它表明了吗?干杯。基思。