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



我想知道为什么要使用priority_queue创建最小堆,应该使用std::greater ?

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

对我来说,因为最小的值总是位于堆的顶部,所以使用的类应该是std::less

更新:另一方面,由于priority_queue(最大堆)的默认行为是在顶部保存最大的值,因此在我看来,std::greater应该用于最大堆创建,而不是用于最小堆创建

逻辑参数如下

  1. std::priority_queue是容器适配器;基于基本的内存考虑,对于序列容器(如std::vector),后面是修改的首选位置(pop_back()push_back())。
  2. priority_queue原语基于std::make_heap(构造函数),std::pop_heap + container::pop_back (priority_queue::pop)和container::push_back + std::push_heap (priority_queue::push)
  3. pop_heap将获取底层存储的前面,并将其放在后面,然后恢复堆不变量。push_heap则相反。
  4. max_heap上执行sort_heap(最初将max放在前面)将重复地将前面弹出到后面,并根据less(这是默认的比较运算符)对范围进行排序
  5. 因此,max_heap的首选实现是将最大元素w.r.t. less放在前面,通过priority_queue::top(底层container::front)访问。
  6. 仍然可以争论priority_queuestd::less比较器代表max_heap是否直观。它可以通过反转比较器的参数来定义为min_heap(但请参阅@ tc的评论)。对于c++ 98的绑定器,这是相当冗长的),在调用各种堆函数中无处不在。一个(对我来说)反直觉的结果是top()不会给top优先级的元素

c++堆函数make_heappush_heappop_heap在最大堆上操作,这意味着当使用默认比较器时,顶部元素是最大值。因此,要创建最小堆,您需要使用greater<T>而不是less<T>

我怀疑使用最大堆而不是最小堆是因为使用less操作更容易实现。在c++中,less具有作为所有STL算法的"默认"比较器的特权;如果您只打算实现一个比较操作(而不是==),则应该是<。这就导致了priority_queue<T, C<T>, less<T>>表示最大队列,而priority_queue<T, C<T>, greater<T>>表示最小队列。

同样,某些算法,如nth_element,需要一个max-heap。

这是一个将优先级队列转换为排序序列的过程。

我们如何做到这一点?

假设我们现在有一个最大堆,我们执行下面的过程:

HEAP-SORT(A)
    for i = A.heap_size downto 2
        exchange A[1] with A[A.heap_size]
        A.heapsize -= 1
        max_heapify(A)

当我们完成这个过程,我们得到一个递增顺序的序列。

我们注意到,每次比较两个元素时,总是把较大的元素放回数组中,这意味着较小的元素在较大的元素的左边。

这与将less操作符传递给std::sort算法以获得递增顺序序列的想法相匹配。

priority_queue是一种数据结构,它以具有最高优先级的元素始终位于队列顶部的方式存储元素。缺省情况下,元素的优先级由其值决定。但是,可以使用函子来改变确定元素优先级的方式。

函子是一个小的函数对象,可以用来执行特定的任务。在本例中,greater<int>函子用于比较两个整数,如果第一个整数大于第二个整数,则返回true。

当对priority_queue使用greater<int>函子时,具有最低值的元素将被认为具有最高优先级。这是因为当将具有最低值的元素与任何其他元素进行比较时,greater<int>函子总是返回true。

最新更新