从 C++ priority_queue 中弹出元素的时间

Posted

技术标签:

【中文标题】从 C++ priority_queue 中弹出元素的时间【英文标题】:Time to pop element from a C++ priority_queue 【发布时间】:2014-04-07 09:24:50 【问题描述】:

我有以下问题:我正在实现一种算法,该算法本质上是通过时间执行扫描 (https://en.wikipedia.org/wiki/Sweep_line_algorithm) 以更新数据结构。对于相关的时间点,我会生成适当的事件并将其存储在std::priority_queue 中:在每个步骤中,我都会弹出具有最小时间值的事件,对其进行处理并在必要时将其他一些事件推送到队列中。不幸的是,我的代码运行得很慢。我用 gprof 看了一下,似乎算法在std::priority_queue::pop 中花费了大约 60% 的执行时间。有什么方法可以让操作更高效吗?

编辑:循环本质上是这样的:

typedef std::priority_queue<Event, vector<Event>, greater<Event> > EventQueue;

while(!events.empty())

  Event e = events.top();
  events.pop();

  const DirectedEdge &edge = e.current_edge->get_edge();

  if(e.type == Event::LEAVING)
  
    Event ee = e;

    ee.type = Event::ENTERING;

    ++ee.current_edge;

    if(!ee.current_edge)
    
      ee.path->set_arrival_time(ee.time);
    
    else
    
      ee.current_edge->set_departure_time(ee.time);
      ee.time += get_delay(ee.current_edge->get_edge());

      events.push(ee);
    
  
  else
   
    Event ee = e;
    ee.type = Event::LEAVING;

    const FlowFloat time = queues[edge.get_index()].insert_traveler(e.time, e.path);

    ee.time = time;

    events.push(ee);
  

【问题讨论】:

您需要展示代码的相关部分才能获得有用的答案。 如果将优先级队列实现为最小堆,则应该是最坏情况 log(n) 来弹出优先级队列的最小值。从根目录删除并向下冒泡。 那段时间实际上是在pop 还是在pop 以及从pop 调用的东西? pop 所做的主要事情是比较和交换 Event 对象并最终销毁一个对象,因此您应该检查这些操作的性能。 好吧,在 pop() 中,大约 50% 的时间用于调用 pop_heap() 并在其中调用 __adjust_heap 嗯,队列大小可能高达 10000。这可能是个问题吗? 【参考方案1】:

如果您使用的是符合 C++11 的编译器,请尝试将移动构造函数/操作符添加到您的 Event 类中,因为 priority_queue 对元素进行了大量操作,并且它是否可以移动而不是复制它会快得多。这当然取决于Event 的定义方式:如果它是 POD 类型,您将一无所获;如果移动操作符不做任何比复制更快的事情,也没有任何好处。

【讨论】:

以上是关于从 C++ priority_queue 中弹出元素的时间的主要内容,如果未能解决你的问题,请参考以下文章

C++ STL priority_queue容器适配器详解

为啥我不能从字符堆栈中弹出元素?

C++ 取消引用 std::priority_queue::top [重复]

错误:无法将“minHeap”从“std::priority_queue,std::greater >”转换为“std::priority_queue”

priority_queue C++

C++入门stack和queue适配器介绍+ priority_queue的模拟实现仿函数基本概念提及