Boost:优先级队列,支持在O(log n)时间内找到元素

Boost: Priority Queue which supports finding an element in O(log n) time

本文关键字:时间 元素 log 队列 优先级 支持 Boost      更新时间:2023-10-16

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

我可以通过使用Boost斐波那契堆实现此功能,并将句柄与其索引一起存储在std::map中,并在堆插入时更新此信息,但我希望堆版本已经提供了此功能。

注:我删除了上一版的问题,因为它太模棱两可了。

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

为一个想法,这里有一个例子,使用Boost多索引做一个优先级队列实现活动对象模式在Boost Asio之上:

  • boost::asio和Active Object

应该注意的是,Multi-Index允许你在同一个容器上指定任意数量的辅助索引

可以使用

  • (multi)set<pair<priority, item> >
  • multimap<priority, item>
  • (multi)set<item>与自定义比较器,如果优先级可以很容易地从项目计算。

存储元素。

如果您需要O(1)访问顶部元素,您可以使用自己的容器,该容器由上面描述的类似set的结构支持,并存储第一个元素的迭代器,并在需要时更新它。

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

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

我发现唯一提供必要功能的库是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许可下的独立plain C。

相关文章: