关于std::make_heap中std::greater<>{}参数及函数重载的疑问
关于std::make_heap第三个参数的疑问解答
问题描述
以下是一段最小堆实现的代码:
// min heap solution // extract k smallest data from a min-heap of all n data points class K_Smallest_MinHeap { public: K_Smallest_MinHeap(std::size_t n, std::size_t k): N(n), K(k), count(0) { } void add(int value){ values.push_back(value); } std::vector<int> get(){ std::make_heap(values.begin(), values.end(), std::greater<>{}); std::vector<int> result; for (std::size_t i = 0; i < K; ++i){ std::pop_heap(values.begin(), values.end(), std::greater<>{}); result.push_back(values.back()); values.pop_back(); } return result; } private: std::size_t N; std::size_t K; std::size_t count; std::vector<int> values; };我对上述代码中
std::make_heap()里的std::greater<>{}参数存在疑惑。我原本以为std::make_heap仅接受begin和end两个迭代器参数,即函数签名为void make_heap( RandomIt first, RandomIt last );,恳请各位帮忙解答!
解答
std::make_heap并非只有两个参数的版本,它提供了重载实现,第三个参数用来自定义堆的排序规则,具体说明如下:
两个核心重载版本
- 基础版本(你认知的默认版本):
这个版本默认使用template< class RandomIt > void make_heap( RandomIt first, RandomIt last );std::less<T>作为比较逻辑,会构建出一个最大堆——堆顶元素是序列中的最大值。 - 带比较函数的重载版本:
这个版本允许你传入自定义的比较函数/函数对象,以此改变堆的性质。template< class RandomIt, class Compare > void make_heap( RandomIt first, RandomIt last, Compare comp );
- 基础版本(你认知的默认版本):
std::greater<>{}的作用
代码里的std::greater<>{}是标准库提供的函数对象,逻辑是判断第一个参数是否大于第二个参数(即返回a > b的布尔值)。当把它传给std::make_heap时,堆的排序规则会被反转:原本的最大堆变成最小堆,堆顶元素是序列中的最小值。这正好匹配代码的需求——要提取前K小的元素,用最小堆的话,每次弹出堆顶就是当前最小的元素,循环K次就能得到目标结果。
注意事项
使用带比较函数的make_heap后,后续操作堆的函数(比如代码里的std::pop_heap)必须传入相同的比较函数,否则会破坏堆的结构,导致行为异常。
内容的提问来源于stack exchange,提问作者Yves Schilli
相关产品推荐
相关产品推荐

