堆(优先级队列)的比较运算与快速排序默认cmp函数的区别

在写快排的cmp函数的时候,return left>right 就是从大到小,return left<right 就是从小到大。堆的比较运算在建堆时是如何应用的,为什么左大于右就会建立小顶堆,右大于左反而建立大顶堆?

(优先级队列的定义正好反过来了。估计是底层实现上优先队列队首指向后面,队尾指向最前面的缘故)

答:这个问题主要涉及到堆排序的过程,比较操作在建堆过程中的应用

​ 在快速排序中,我们确实可以通过更改比较函数cmp(return left>right 代表降序排序,return left<right 代表升序排序)来改变排序的方向。例如,sort函数里面

//从大到小排序需要加的参数 
sort(a.begin(),a.end(),greater<int>());

但在堆排序中,情况稍有不同。

​ 在建堆过程中,我们需要维护堆的性质。当我们说 "左大于右就会建立小顶堆,右大于左反而建立大顶堆"时,实际上我们是在描述父节点和子节点之间的比较操作

假设我们有两个元素 left 和 right,其中 left 是父节点,right 是其中一个子节点:

  • 在建立小顶堆的过程中,我们需要保证父节点的值小于或等于子节点的值。如果父节点的值大于子节点的值(即 left > right我们就需要交换这两个元素,使得父节点的值小于或等于子节点的值,从而维持堆的性质。
//小顶堆,较小的元素放在堆顶部
 priority_queue<int, vector<int>, greater<int>> min_heap;
  • 在建立大顶堆的过程中,我们需要保证父节点的值大于或等于子节点的值。如果父节点的值小于子节点的值(即 left < right我们就需要交换这两个元素,使得父节点的值大于或等于子节点的值,从而维持堆的性质。
//大顶堆,较大的元素放在堆顶
priority_queue<int, vector<int>, less<int>> max_heap;

所以,在堆排序中,我们是通过比较和可能的交换来维持堆的性质,而不是像快速排序那样直接通过比较函数来改变排序的方向。这就是为什么在建堆过程中,“左大于右就会建立小顶堆,右大于左反而建立大顶堆”。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
C++ 中使用 `std::priority_queue` 实现优先级队列时,可以传入一个比较函数作为第三个参数来实现自定义排序。如果要对 `pair` 进行排序,可以按照以下步骤进行: 1. 定义一个比较函数比较函数的形式应该为 `bool cmp(const pair<int, int>& a, const pair<int, int>& b)`,其中 `pair<int, int>` 可以根据具体需求进行修改,比如 `pair<string, int>` 等。这个比较函数应该返回 `true` 或 `false`,表示 `a` 是否应该排在 `b` 前面。 2. 在定义 `priority_queue` 时,将比较函数作为第三个参数传入即可。比如 `priority_queue<pair<int, int>, vector<pair<int, int>>, decltype(cmp)> q(cmp);`,其中 `vector<pair<int, int>>` 表示底层容器使用的是 `vector`,`decltype(cmp)` 表示比较函数的类型。 下面是一个完整的例子,假设我们要将 `pair<int, int>` 按照第一个元素从小到大排序,如果第一个元素相等,则按照第二个元素从大到小排序: ```c++ #include <iostream> #include <queue> #include <vector> using namespace std; bool cmp(const pair<int, int>& a, const pair<int, int>& b) { if (a.first == b.first) { return a.second > b.second; } return a.first < b.first; } int main() { priority_queue<pair<int, int>, vector<pair<int, int>>, decltype(cmp)> q(cmp); q.push(make_pair(1, 2)); q.push(make_pair(3, 4)); q.push(make_pair(1, 3)); q.push(make_pair(2, 1)); while (!q.empty()) { pair<int, int> p = q.top(); cout << "(" << p.first << ", " << p.second << ")" << endl; q.pop(); } return 0; } ``` 输出结果为: ``` (1, 3) (1, 2) (2, 1) (3, 4) ```

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值