【问题标题】:augmenting/index priority_queue in STLSTL 中的扩充/索引 priority_queue
【发布时间】:2013-11-14 23:24:04
【问题描述】:

我在我的图形应用程序中使用 STL priority_queue 作为数据结构。您可以放心地将其假设为 Prim 生成树算法的高级版本。 在算法中,我想有效地在优先级队列中找到一个节点(不仅仅是一个最小节点)。[这是需要的,因为节点的成本可能会改变并且需要在 priority_queue 中修复] 我所要做的就是增加priority_queue并根据我的节点键索引它。我找不到任何可以在 STL 中完成的方法。谁能更好地了解如何在 STL 中做到这一点?

【问题讨论】:

  • 您可以改用std::map...虽然速度较慢且内存碎片/使用量更大。我不认为你可以用priority_queue 做你想做的事。
  • @Dave Map 不是解决方案,我需要一直找到最小关键节点。地图不这样做。
  • 也有:myMap.begin() 就是这样一个节点。
  • @Igor 不,不是。我需要:1)找到最小加权节点(通常通过优先级队列完成)2)在节点的数据结构中找到通常通过 Map 完成的位置。
  • 如果权重是key,那么myMap.begin()指向权重最小的节点。如果权重不是关键,那么优先队列究竟有什么帮助?

标签: c++ c++11 stl


【解决方案1】:

std::priority_queue<T> 不支持高效的节点查找:它使用d-ary heap,通常使用d == 2。这种表示不会保留节点。如果您真的想将std::priority_queue<T> 与 Prim 算法一起使用,唯一的方法就是添加具有当前最短距离的节点,并可能多次添加每个节点。这会将 的大小变成O(E) 而不是O(N),但是,即对于具有许多边的图,它会导致更高的复杂度。

您可以使用std::map<...> 之类的东西,但这确实会遇到几乎相同的问题:您可以找到下一个节点以有效提取,也可以找到节点以有效更新。

“正确”的方法是使用基于节点的优先级队列,例如Fibanocci-heap:由于节点保持原位,您可以在插入节点时从堆中获取句柄并有效地更新a的距离节点通过句柄。使用堆树集中的几个顶部节点访问最近的节点是有效的。斐波那契堆的基本堆操作(push()top()pop())的整体性能比 d-ary 堆要慢,但单个节点的有效更新使其值得使用。我似乎记得 Prim 的算法实际上需要斐波那契堆来实现严格的复杂性限制。

我知道在Boost 有一个斐波那契堆的实现。斐波那契堆的有效实现并非完全微不足道,但它们比仅仅具有理论意义更有效。

【讨论】:

  • 在这种情况下,您是否求助于您自己的priority_queue实现,我可以想象编写一个具有索引/查找功能的优先级队列实现。
  • 你在 STL 中也找到了 union find 的任何实现。我在 boost disjoint_sets 中找到了一个,但在 STL 中没有。在我看来,STL 实现高级图算法的能力非常有限
  • 我们没有在我们的项目中使用 BOOST,因此修改 make 文件以支持与 boost 的链接是一项巨大的工作。 (而且我无法决定使用 BOOST)
  • @David:在很久以前,我通过提交三个包来帮助启动 Boost。我没有追求其中任何一个,但所有三个功能现在要么在 Boost 中,要么在标准中,或者即将进入标准。其中一个包是“一堆堆”,其中包括一个斐波那契堆。可能在 Internet 上流传,但我不知道在哪里:我会实现一个 Fibonacci 堆,但它有点不重要。一个更简单的替代方案可能是一个 d-ary heap,其中轨道是当前节点。
  • @David:关于图算法的支持,标准 C++ 库真的不需要任何东西。 C++ 社区中的图形算法似乎不太感兴趣,或者人们乐于使用 Boost Graph Library(这很好;不过我有偏见:在我的毕业论文中,我只描述了几个相同的概念几年前)。 Union-Find 是一种有趣的数据结构,最好将其实现为特殊的属性映射(有关属性映射的解释,请参见 BGL)。我可以想象BGL居然有这样一个属性图。
猜你喜欢
  • 2011-02-27
  • 1970-01-01
  • 1970-01-01
  • 2021-09-26
  • 2022-08-03
  • 2011-01-27
  • 1970-01-01
  • 2011-05-06
  • 1970-01-01
相关资源
最近更新 更多