C++ std::priority_队列和make_堆API设计
我正在阅读priority_queue(基本上是make_heap上的包装器)的文档,它发现您可以使用compare函数对其进行定制 从文档()中: 可以提供用户提供的比较来更改顺序,例如。 使用std::greater将导致最小的元素显示为 顶部() 在Wikipedia和其他CS文本中,堆的定义如下: 在计算机科学中,堆是一种专门的基于树的数据结构 它满足heap属性:如果A是B的父节点,那么 节点A的键(值)相对于节点B的键进行排序 在堆中应用相同的顺序。堆可以是 进一步分类为“最大堆”或“最小堆”在一个最大值中 堆中,父节点的键始终大于或等于 子节点和最高键位于根节点中。 但是在std::priority_队列实现中,提供std::greater将导致创建一个MinHeap(顶部最小的元素)。如果(父-比较器-子)为真,我会期望最大堆,因为定义了堆排序(在我读过的所有文献中) 我发现这种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的键进行排序 在堆中应用相同的顺序。堆可以是 进一步分类为“最大堆”或
有这样定义的理由吗?这是一件让你头脑清醒的事情-提供
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()
-sstd::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方法不定义父子关系?我可以看到代码在做什么,但我不明白为什么选择这个路线和设计。重复的?