You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

关于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并非只有两个参数的版本,它提供了重载实现,第三个参数用来自定义堆的排序规则,具体说明如下:

  1. 两个核心重载版本

    • 基础版本(你认知的默认版本):
      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 );
      
      这个版本允许你传入自定义的比较函数/函数对象,以此改变堆的性质。
  2. std::greater<>{} 的作用
    代码里的std::greater<>{} 是标准库提供的函数对象,逻辑是判断第一个参数是否大于第二个参数(即返回a > b的布尔值)。当把它传给std::make_heap时,堆的排序规则会被反转:原本的最大堆变成最小堆,堆顶元素是序列中的最小值。

    这正好匹配代码的需求——要提取前K小的元素,用最小堆的话,每次弹出堆顶就是当前最小的元素,循环K次就能得到目标结果。

  3. 注意事项
    使用带比较函数的make_heap后,后续操作堆的函数(比如代码里的std::pop_heap)必须传入相同的比较函数,否则会破坏堆的结构,导致行为异常。

内容的提问来源于stack exchange,提问作者Yves Schilli

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.24 17:37:03