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