std :: priority_queue和make_heap API设计

时间:2016-06-14 17:58:46

标签: c++ algorithm c++11 priority-queue

我正在阅读priority_queue的文档(基本上是make_heap的包装器),它发现你可以使用比较函数对它进行自定义。

从文档(http://en.cppreference.com/w/cpp/container/priority_queue):

  

可以提供用户提供的比较来更改排序,例如   使用std :: greater会导致最小元素显示为   顶部()。

在维基百科和其他CS文本中,堆定义如下:

  

在计算机科学中,堆是一种专门的基于树的数据结构   满足堆属性:如果A是B的父节点,那么   节点A的密钥(值)相对于节点B的密钥排序   在堆中应用相同的顺序。堆可以   进一步分类为“最大堆”或“最小堆”。 最多   堆,父节点的键总是大于或等于   子节点和最高键的位于根节点中。

但是在std :: priority_queue实现中,提供std :: greater会导致创建MinHeap(顶部的最小元素)。我会期望最大堆,因为定义了堆排序(在我读过的所有文献中)if(parent comparator children)是真的。

我发现这种API设计令人困惑。

有没有理由这样定义?

2 个答案:

答案 0 :(得分:3)

我发现它也令人困惑,但从一个不同的角度来看。假设您要按升序对序列进行排序。有几种方法可以做到:

  1. 将您的数据放入std::vectorstd::deque并使用 std::sort() 运行std::less
  2. 将您的数据放入std::list并使用 std::list::sort() 运行std::less
  3. 将数据插入使用 std::set 配置的std::less,最后会自动排序。
  4. 将您的数据放在std::vectorstd::deque中,然后使用 std::make_heap() 运行std::pop_heap()后跟std::less - 。< / LI>
  5. 使用 std::priority_queue(!!!)将您的数据推送到std::greater
  6. 正如我们所看到的,std::priority_queue从这种观点来看是一个明确的异常值。

    实际上,std::priority_queue在这方面的混淆行为背后的原因隐藏在第(4)项中,因为这是std::priority_queue下面的内容。 (4)也违背了我的直觉(尽管程度较小),因为在中间状态(虽然并非所有std::pop_heap都已执行),序列的已排序部分位于其上限,而不是下部范围。

    但它也解释了为什么为标准库选择了最大堆 - std::pop_heap将弹出元素放在该位置,从那里可以在恒定时间内删除它,无论使用何种容器类型。

答案 1 :(得分:2)

这可以解决问题 - 提供std::greater实际上会产生最小堆。

原因如下:从堆的角度来看,比较器在堆上定义小于的关系,即使它实际上正在做其他事情。当std::priority_queue需要插入元素时,它会调用比较器并为其提供两个元素。如果比较器返回true,则认为第一个元素小于第二个元素,并将第二个元素放在第一个元素中(因为std::priority_queue max heap 实现)。结果,你最终得到了最小堆。