Dijkstra的如何使用优先级队列或最小堆?
Dijkstra's how could a priority queue or min-heap be used?
我一直在努力实现Dijkstra的算法;更具体地说,是优先级队列的部分。将顶点添加到数据结构中,并使用迭代器遍历所有顶点并找到最小距离;这很容易,但是n时间。
我想要的是:
- 能够将顶点插入数据结构
- 提取(返回并删除)距离最低的顶点 V[v]
我相信,为了使 Dijkstra 的算法正常工作,您应该能够在常量时间内插入顶点并在 log(n) 时间内提取它们;有人建议可以使用优先级队列和最小堆,但对我来说,我们可以保持队列或最小堆的顺序似乎并不现实,因为距离不断被修改。
那么我应该如何声明和使用优先级队列、最小堆或其他数据结构来做到这一点呢?
您可以使用一对将节点与值一起存储(第一个元素应该是值,以便优先级队列与此值进行比较)。维护一个布尔数组visit [ ]
,您将在其中指示您访问过或不是某个节点(最初都是假的)。
每次您访问优先级队列的前部元素时,请检查您是否访问过此节点,该节点检查是否visit[pq.front().second] == false
。检查其所有相邻边,并添加从此路径到达的节点。如果这是真的,那么你应该忽略它,因为你已经用更少的长度访问了它。您不会添加超过 E 边,因此时间复杂度保持不变。
您可以在此链接 http://community.topcoder.com/tc?module=Static&d1=tutorials&d2=standardTemplateLibrary2#priority 中了解有关此方法的更多信息。
这里基本上有三个选择:
- 使用树或其他一些 DS,允许您提取
O(logN)
中的任意数字。堆无法提供此行为。 - 维护一个额外的 DS(可能是基于哈希的)来映射
map:V->Node Reference
- 这将允许您在堆中有效地找到所需的节点,并删除一个您知道其位置在堆中O(logN)
可行的节点(问题是发现...... - "仍然插入",忽略堆已包含此节点的事实。这将导致您有一个更大的堆,大小
O(n^2)
最坏的情况(边缘数),但回想一下log(N^2)=2log(N)
O(logN)
相关文章:
- 使用2个键的cpp-stl::优先级队列排序不正确
- 使用"Task"函数指针队列定义作业管理器
- 在c++队列中使用pop和visit实现线程安全
- 使用MPI_Gather会导致无法附加到引导队列错误
- 避免使用 boost::进程间::消息队列创建文件
- 使用 <list> (错误 C2760) 打印队列的元素
- 使用 std::forward_list 返回错误的队列实现
- 了解使用堆栈实现队列的递归调用机制
- 使用堆的优先级队列,具有相同键的值不遵循 FIFO(先进先出)
- 是否可以使用简单队列创建优先级队列
- 将shared_ptr与FreeRTOS队列一起使用
- 如何检查队列是否使用 STL 排序
- 为什么在优先级队列中使用容器参数进行重载?
- 为什么优先级队列是使用堆实现的,而我们可以更有效地使用向量来实现它
- Win32 消息队列在使用 OpenGL 渲染时被淹没
- 使用boost.lockfree队列比使用静音速度慢
- 在 Folly 的无锁 SPSC 队列中使用 std::memory_order_consume
- 如何在优先级队列中使用自定义类
- 混淆了定义自定义优先级队列和使用C++中的make_heap等方法初始化堆之间的区别
- 与向量相比,C++STL队列内存使用情况