dijkstra算法在基于堆的优先级队列中的查找时间
lookup time in heap based priority queue for dijkstra algorithm
我想使用priority_queue作为dikjstra算法的顶点容器,在调用extractMin
以获得顶点u
之后,我找到所有相邻的顶点v
,然后我可能会调用decreaseKey
用于v
,我知道decreaseKey
花费O(lgN)时间,然而,在调用decreaseKey
之前,我必须首先找到v
的位置。
我使用std::vector
和std::make_heap/std::push_heap/std::pop_heap
来维护优先级队列,使用这种数据结构,查找特定数据将花费O(N)时间,这将使O(lgN) decreaseKey
变得毫无意义。
那么,在dikjstra算法顶点容器的常用方法是什么,或者我应该在class Vertex
中添加一个成员来保持它在堆中的位置?
首先你不需要使用std::***_heap
函数;STL中已经有priority_queue
了
对于更新堆中已经存在的值,可以插入索引和距离的pair
s。并维护距离矢量,以验证距离是否仍然有效或已被更新;比如:
typedef struct {
size_t index; /* index of vertex and the distance at which */
int dist; /* the vertex was pushed to the heap */
} value_t;
/* `a` has less priority than `b` if it is further away */
const auto comp = [](const value_t & a, const value_t & b){
return b.dist < a.dist;
};
priority_queue<value_t, vector<value_t>, decltype(comp)> heap(comp);
/* the *most current* shortest distances for all nodes */
vector<int> dist(n, inf);
那么Dikjstra循环应该是这样的:
while(!heap.empty()) {
const auto top = heap.top();
heap.pop();
if(dist[top.index] < top.dist) {
/* the node has already been added at a */
/* shorter distance therefore skip it */
continue;
}
/* process the node & its neighbors */
/* push to the heap neighbors which get their `dist` deccreased */
}
确实,在堆中可能存在相同节点的多个副本(在不同的距离上,其中只有一个仍然有效);但是您可能会显示堆的大小是O(num. of edges)
,因此堆仍然会执行O(log num. of nodes)
。
相关文章:
- C++优先级队列,按对象的唯一指针的特定方法升序排列
- 按对象的特定方法按升序排列的C++优先级队列
- 使用2个键的cpp-stl::优先级队列排序不正确
- 为什么我需要C++中不同的排序格式来对这个USACO代码上的数组和优先级队列进行排序
- 打印优先级队列
- 带自定义比较器的最小优先级队列
- 优先级队列自定义比较器
- 排序数组优先级队列
- 更改运行时优先级队列的排序功能
- 优先级队列构造函数的工作
- 实现优先级队列
- 优先级队列功能比较
- 在C++中打印对的优先级队列的所有值时出现问题
- 使用堆的优先级队列,具有相同键的值不遵循 FIFO(先进先出)
- 为什么某些 STL 容器(堆栈、队列、优先级队列)不支持迭代器?
- 是否可以使用简单队列创建优先级队列
- 如何在 c++ 中创建对的优先级队列.这会弹出具有最小值的元素.默认的弹出最大值
- Cython中带有自定义比较器的优先级队列
- 优先级队列比较器[C++].
- asio::io_service 具有多个线程的优先级队列处理