简体   繁体   English

使用 `std::greater` 通过 `priority_queue` 创建最小堆的原因

[英]The reason of using `std::greater` for creating min heap via `priority_queue`

I am wondering why for creating a min heap using the priority_queue , the std::greater should be used?我想知道为什么使用priority_queue创建最小堆,应该使用std::greater

std::priority_queue<T, std::vector<T>, std::greater<T> > min_heap;

To me, since the smallest value is always located at the top of the heap, the employed class should be std::less对我来说,因为最小值总是位于堆的顶部,所以使用的类应该是std::less

Update: On the other hand, since the default behavior of priority_queue (max heap) is to hold the greatest value at the top, it looks to me that the std::greater should be used for the max heap creation and not for min heap creation更新:另一方面,由于priority_queue (最大堆)的默认行为是在顶部保存最大值,在我看来std::greater应该用于创建最大堆而不是最小堆创建

The logical argument is as follows逻辑论证如下

  1. std::priority_queue is a container adaptor; std::priority_queue是一个容器适配器; basic memory considerations make the back the preferred place for modifications (with pop_back() and push_back() ) for sequence containers such as std::vector .基本内存考虑使 back 成为对序列容器(如std::vector pop_back()进行修改(使用pop_back()push_back() )的首选位置。
  2. the priority_queue primitives are based on std::make_heap (constructor), std::pop_heap + container::pop_back ( priority_queue::pop ) and on container::push_back + std::push_heap ( priority_queue::push ) priority_queue原语基于std::make_heap (constructor)、 std::pop_heap + container::pop_back ( priority_queue::pop ) 和container::push_back + std::push_heap ( priority_queue::push )
  3. pop_heap will take the front of the underlying storage, and put it at the back , restoring the heap invariant afterwards. pop_heap会取底层存储的前面,放在后面,之后恢复堆不变性。 The reverse goes for push_heap . push_heap
  4. doing sort_heap on a max_heap (with the max at the front initially) will repeatedly pop the front to the back and sort the range according to less (which is the default comparison operator)sort_heap上的max_heap (具有最大在前面最初)将反复弹出前面到后面和排序根据范围less (即默认比较运算符)
  5. hence, the preferred implementation of a max_heap is to have the max element wrt less at the front, accessed through priority_queue::top (underlying container::front ).因此, max_heap的首选实现是让 max 元素在前面less ,通过priority_queue::top (底层container::front )访问。
  6. one can still debate whether it is intuitive that priority_queue with a std::less comparator is representing a max_heap .人们仍然可以争论,带有std::less比较器的priority_queue表示max_heap是否直观。 It could have been defined as a min_heap by reversing the comparator's arguments (but see the comment by @TC that with C++98 binders this is rather verbose) everywhere in the calls to the various heap functions.它可以通过在对各种堆函数的调用中的任何地方反转比较器的参数(但请参阅@TC 的评论,使用 C++98 绑定器,这相当冗长)来定义为min_heap The one (for me) counter-intuitive result would have been that top() would then not have given the element with top priority一个(对我来说)违反直觉的结果是top()不会给元素以最高优先级

The C++ heap functions make_heap , push_heap , and pop_heap operate on a max heap , meaning the top element is the maximum when using the default comparator. C++ 堆函数make_heappush_heappop_heap最大堆上运行,这意味着使用默认比较器时,顶部元素是最大值 So, to create a min-heap, you need to use greater<T> instead of less<T> .因此,要创建最小堆,您需要使用greater<T>而不是less<T>

I suspect that a max heap is used instead of a min heap is that it is easier to implement with the less operation.我怀疑使用最大堆而不是最小堆是因为使用less操作更容易实现。 In C++, less has the special privilege of being the sort of "default" comparator for all STL algorithms;在 C++ 中, less具有作为所有 STL 算法的“默认”比较器的特殊特权; if you only are going to implement one comparison operation (other than == ), it should be < .如果您只打算实现一个比较操作(除了== ),它应该是< This leads to the unfortunate quirk that priority_queue<T, C<T>, less<T>> means a max-queue and priority_queue<T, C<T>, greater<T>> means a min-queue.这导致了一个不幸的怪癖, priority_queue<T, C<T>, less<T>>意味着一个最大队列,而priority_queue<T, C<T>, greater<T>>意味着一个最小队列。

Also, certain algorithms like nth_element need a max-heap.此外,某些算法(如nth_element需要最大堆。

See http://en.cppreference.com/w/cpp/container/priority_queue .请参阅http://en.cppreference.com/w/cpp/container/priority_queue A priority_queue is designed to put the largest value at the top. priority_queue旨在将最大值放在顶部。 This happens if you use the default std::less comparator.如果您使用默认的std::less比较器,就会发生这种情况。 So if you want the reverse behavior, you need to use the reverse comparator, std::greater .因此,如果您想要反向行为,则需要使用反向比较器std::greater

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM