【问题标题】:Extracting last element of a priority_queue提取priority_queue的最后一个元素
【发布时间】:2016-05-31 10:19:09
【问题描述】:

我正在使用 std::priority_queue 编写一个算法来计算 3D 网格上数据集的距离函数。初始化队列后,我想将最后一个元素存储在一个单独的变量中,就像你对 std::queue.back() 所做的那样,但是,当然,这对于优先级队列是不可能的,所以我的解决方法如下:

CellQueue q; //this is the actual priority_queue

//...
//initialization
//...

Cell* last = 0;
CellQueue dummy(q);
while (!dummy.empty()) {
    last = dummy.top();
    dummy.pop();
}

当然有更好的方法来解决这个问题,所以如果有人能告诉我,我会很高兴的。

谢谢,

费德里科


编辑

@Sam @Dietmar 计算距离函数 (DF) 的算法以这种方式工作:使用至少包含数据集一个点的网格单元填充 priority_queue,然后按距离对它们进行排序 (在这一步为零)按递增顺序排列。然后,对于队列的每个元素,您访问邻居并为每个邻居计算相对于其父元素的距离。现在,出于效率原因,我只想在数据集周围的窄带上计算 DF。因此,为了在访问了第三环邻域后停止这个过程,我必须跟踪当前环的最后一个元素。

【问题讨论】:

  • 用所需功能扩展实现怎么样?
  • 这是XY problem。你想解决什么问题?不,不是将最后一个元素单独存储在优先级队列中,而是您要解决的真正问题是您认为将最后一个元素存储在优先级队列中是解决方案。
  • 获取优先级队列中最后一个元素的目的是什么?如果这实际上是您感兴趣的元素,您可能希望以相反的方式订购优先级队列,它将成为 top() 元素。
  • pop_back 从优先级队列中弹出最后一项。

标签: c++ queue priority-queue


【解决方案1】:

“显而易见”的方法是将最后一个(最小)元素的副本与priority_queue 一起存储。跟踪此问题的额外工作与添加到优先级队列中的元素数量成正比,而您的解决方法是调用时队列大小为 N log(N),因此请自行选择。

无论何时pop,根据定义,如果pop 导致队列为空,则只能删除最后一个值,因此您无需担心更新pop 上的任何内容。

每当您push 到优先级队列时,将推送的值与当前最小值进行比较,并在必要时替换它。 emplace 也是如此。

如果你想变得更漂亮,可以通过编写自己的容器适配器 priority_queue_that_additionally_accesses_the_min_value 来展示它。或者可能是一个较短的名称。

如果您需要访问实际元素,而不是其副本,那么您会遇到问题,priority_queue 本身会在您不查看时在内部移动内容,因此您不能只保留一个指向最小值的指针。将元素包装在智能指针中可能会解决这个问题,当然您需要为priority_queue 提供一个遵循智能指针的比较器。

最后,还有“双端优先级队列”之类的东西。这将使您能够有效地去除两端,而不是有效地从一端去除并检查两者。它不在标准 C++ 中,但要么查找必要的结构和算法并自己实现,要么搜索“双端优先级队列”或“最小/最大堆”的 C++ 实现。我自己从来没有使用过这个结构,所以我不会推荐一个具体的结构。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2020-05-01
    • 2012-04-02
    • 2010-11-30
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多