C++ std::priority_队列和make_堆API设计

C++ std::priority_队列和make_堆API设计,c++,algorithm,c++11,priority-queue,C++,Algorithm,C++11,Priority Queue,我正在阅读priority_queue(基本上是make_heap上的包装器)的文档,它发现您可以使用compare函数对其进行定制 从文档()中: 可以提供用户提供的比较来更改顺序,例如。 使用std::greater将导致最小的元素显示为 顶部() 在Wikipedia和其他CS文本中,堆的定义如下: 在计算机科学中,堆是一种专门的基于树的数据结构 它满足heap属性:如果A是B的父节点,那么 节点A的键(值)相对于节点B的键进行排序 在堆中应用相同的顺序。堆可以是 进一步分类为“最大堆”或

我正在阅读priority_queue(基本上是make_heap上的包装器)的文档,它发现您可以使用compare函数对其进行定制

从文档()中:

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

在Wikipedia和其他CS文本中,堆的定义如下:

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

但是在std::priority_队列实现中,提供std::greater将导致创建一个MinHeap(顶部最小的元素)。如果(父-比较器-子)为真,我会期望最大堆,因为定义了堆排序(在我读过的所有文献中)

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


有这样定义的理由吗?

这是一件让你头脑清醒的事情-提供
std::greater
实际上会产生最小堆


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

我也感到困惑,但从另一个角度来看。假设您希望按升序对序列进行排序。有几种方法可以做到这一点:

  • 将数据放入
    std::vector
    std::deque
    中,然后使用
    std::less
    运行
    std::sort()
  • 将数据放入
    std::list
    并使用
    std::list::sort()运行
    std::less
  • 将您的数据插入配置有
    std::less
    std::set
    中,最后它会自动排序
  • 将数据放入
    std::vector
    std::deque
    中,然后运行
    std::make_heap()
    ,然后使用
    std::less
    运行
    std::pop_heap()
    -s
  • 使用
    std::greater
    (!!!)
    通过
    std::priority\u队列推送数据
  • 正如我们所看到的,
    std::priority_queue
    从这样的角度来看是一个明确的异常值

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


    但它也解释了为什么为标准库选择了最大堆-
    std::pop_heap
    将弹出的元素放置在可以在固定时间内从中移除的位置,而不管所使用的容器类型如何。

    我理解它是如何实现的,但为什么它是以这种方式定义的?为什么它不使用比较器来验证父/子关系,就像它几乎在任何地方都定义一样?为什么max_堆需要std::less而不是std::greater?它只需要切换if中2个元素的顺序,所有这些都可以工作——生成一个带有std::greater的maxHeap。我的第一个猜测是,这是一种优化,但我不确定这是它背后的真正原因。例如,std::sort API以另一种(直观的)方式工作,如果comparator为true,则一切保持不变…@AlexandruEne std::more是相反的顺序less。我假设C++在默认情况下实现了一个最大堆,因为它使堆排序稍微容易一些(将最大元素移动到数组的末尾,这是新打开的槽)。正如Sergey指出的,在这个问题中,我根据文献描述了我的期望,而不是实现,我试图理解“为什么选择这个实现”,因为在我看来,它导致了一个混乱的界面。这背后的原因是什么?为什么comparator方法不定义父子关系?我可以看到代码在做什么,但我不明白为什么选择这个路线和设计。重复的?