【问题标题】:Boost: Priority Queue which supports finding an element in O(log n) timeBoost:支持在 O(log n) 时间内查找元素的优先级队列
【发布时间】:2014-06-25 17:48:07
【问题描述】:

我很好奇 Boost 是否提供优先队列实现,它还支持在 O(log n) 时间内找到一个元素?

我可以通过使用 Boost Fibonacci Heap 来实现此功能,并将句柄与其索引一起存储在 std::map 中,并在堆插入时更新此信息,但我希望有一个已经提供此功能的堆版本.

注意:我删除了以前版本的问题,因为它太模棱两可了。

【问题讨论】:

  • 简单的set/map有什么问题?
  • A multiset 是一个优先级队列,支持在对数时间内查找内容。
  • 我认为键顺序或“自然”顺序与此处的优先级不一致是隐含的。 @tmyklebu 有道理
  • @sehe 您可以使用(multi)set<pair<priority, item> >multimap<priority, item>,或者如果可以使用自定义比较器从(multi)set<item> 项目轻松计算优先级。
  • @Csq AFAIK,地图在足够的时间内不支持优先队列操作。

标签: c++ boost


【解决方案1】:

如果您不介意在空间和插入时间上有(相当大的?)开销,您可以在此处使用多索引容器。

作为一个想法,这是一个使用 Boost Multi-Index 在 Boost Asio 之上实现 Active Object 模式的优先级队列的示例:

需要注意的是,Multi-Index 可以让你在同一个容器上指定任意数量的二级/辅助索引

【讨论】:

    【解决方案2】:

    你可以使用

    • (multi)set<pair<priority, item> >
    • multimap<priority, item>
    • (multi)set<item> 如果可以从项目中轻松计算优先级,则使用自定义比较器。

    存储元素。

    如果您需要对顶部元素进行O(1) 访问,您可以使用由上述类似集合结构支持的自己的容器,并将迭代器存储到第一个元素并在需要时对其进行更新。

    我不确定此解决方案在性能方面是否优于其他方法,但可以快速实施和测量。集合上的大多数操作都是O(n*log(n)),就像在优先级队列上一样,但总的来说,set 应该更慢,因为它分散在内存中。

    【讨论】:

      【解决方案3】:

      在不牺牲优先级队列操作的渐近性能的情况下,在小于线性的时间内找到优先级队列中的元素的唯一方法是在每次优先级队列操作时跟踪每个元素的位置。

      我发现唯一提供必要功能的库是libpqueue,现在可以在这里找到:https://github.com/vy/libpqueue

      它使用用户定义的回调函数cmppri()getpri()setpri()getpos()setpos(),在每次队列更新时由库调用。

      预期的使用模式是定义一个包装数据结构,如:

      typedef struct {
          pqueue_pri_t pri;
          void *data;
          size_t pos;
      } node_t;
      

      以及访问器函数,例如:

      static size_t get_pos(void *a) {
          return ((node_t *) a)->pos;
      }
      
      static void set_pos(void *a, size_t pos) {
          ((node_t *) a)->pos = pos;
      }
      

      这允许人们在O(1) 时间内找到节点的位置,但代价是创建包装器结构和回调调用的开销。如果您需要按名称(而不是通过 node_t 指针)查找元素,您可以轻松使用 std::unordered_map 或类似的后端。

      libpqueue 是 Apache 许可下的独立纯 C。

      【讨论】:

        猜你喜欢
        • 2022-08-24
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2020-01-29
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2016-12-14
        相关资源
        最近更新 更多