使用std::less 排序的std::heap 可以轻松提取最大 元素,而不是最小元素。但是如果你使用std::greater,那么你可以有效地提取最小元素。
std::pop_heap,使用std::greater,会将最小元素放在序列的后面,并将堆的大小减一。然后,您可以读取 back() 并使用新元素写入 back()。
std::push_heap,使用std::greater,将在序列的后面插入元素,将堆的大小增加一。
在代码中:
#include <algorithm>
#include <vector>
#include <iostream>
int
main()
{
std::vector<int> v{5, 4, 6, 9, 0, 1, 2, 3};
std::make_heap(v.begin(), v.end(), std::greater<int>{});
int i;
while (std::cin >> i)
{
// pop minimum, and place at back()
std::pop_heap(v.begin(), v.end(), std::greater<int>{});
// write min out
std::cout << "min = " << v.back() << '\n';
// push a new element into the heap
v.back() = i;
std::push_heap(v.begin(), v.end(), std::greater<int>{});
}
}
使用vector 这一切都非常有效,因为提取和插入实际上是在vector 的后面。而且因为我们使用的是greater,我们实际上每次都提取最小元素(这有点不直观)。
如果需要,可以将上述逻辑封装在std::priority_queue<T, std::vector<T>, std::greater<T>> 中,它简单地适应vector 并公开push、pop 和top 成员函数,而不是vector 的push_back, pop_back 和 back。此适配器将在适当的位置简单地调用make_heap、push_heap 和pop_heap。
更新
TemplateRex 正确指出在 C++14 中greater<> 可以用来代替greater<int>。例如:
std::make_heap(v.begin(), v.end(), std::greater<>{});
这会创建一个异构函子,它可以接受任何两个参数,而不仅仅是int:
template <>
struct greater<void>
{
template <class T1, class T2>
auto operator()(T1&& t, T2&& u) const
{ return std::forward<T1>(t) > std::forward<T2>(u); }
typedef void is_transparent;
};
有了这个新功能,只需更改vector 即可更改类型(嗯,还有i 的类型),示例的其余部分将自动适应类型的更改。