我想知道为什么要使用priority_queue
创建最小堆,应该使用std::greater
?
std::priority_queue<T, std::vector<T>, std::greater<T> > min_heap;
对我来说,因为最小的值总是位于堆的顶部,所以使用的类应该是std::less
更新:另一方面,由于priority_queue
(最大堆)的默认行为是在顶部保存最大的值,因此在我看来,std::greater
应该用于最大堆创建,而不是用于最小堆创建
逻辑参数如下
-
std::priority_queue
是容器适配器;基于基本的内存考虑,对于序列容器(如std::vector
),后面是修改的首选位置(pop_back()
和push_back()
)。 -
priority_queue
原语基于std::make_heap
(构造函数),std::pop_heap
+container::pop_back
(priority_queue::pop
)和container::push_back
+std::push_heap
(priority_queue::push
) -
pop_heap
将获取底层存储的前面,并将其放在后面,然后恢复堆不变量。push_heap
则相反。 - 在
max_heap
上执行sort_heap
(最初将max放在前面)将重复地将前面弹出到后面,并根据less
(这是默认的比较运算符)对范围进行排序 - 因此,
max_heap
的首选实现是将最大元素w.r.t.less
放在前面,通过priority_queue::top
(底层container::front
)访问。 - 仍然可以争论
priority_queue
与std::less
比较器代表max_heap
是否直观。它可以通过反转比较器的参数来定义为min_heap
(但请参阅@ tc的评论)。对于c++ 98的绑定器,这是相当冗长的),在调用各种堆函数中无处不在。一个(对我来说)反直觉的结果是top()
不会给top优先级的元素
c++堆函数make_heap
、push_heap
和pop_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。