优先队列与堆排序
- 优先队列的第三个参数的实际含义,为什么
less
对应大顶堆,greater
对应小顶堆;
堆排序
堆排序:就是将容器里面的数据按照堆特征进行排序;
堆的本质是二叉树,堆排序就是将树的父结点与子结点进行比较、互换的结果;
大顶堆,父结点比子结点大,所以堆顶是最大的;
小顶堆,父结点比子结点小,所以堆顶是最小的;
void maxHeapify(vector<int>& nums, int start, int end) {
//保证堆顶的元素是最大的
int dad = start;
int son = dad * 2 + 1;
while (son <= end) {
if (son + 1 <= end && nums[son] < nums[son + 1]) {
son++;
}
if (nums[dad] > nums[son])
return;
else {
swap(nums[dad], nums[son]);
dad = son;
son = dad * 2 + 1;
}
}
}
void heapSort(vector<int>& nums) {
int len = nums.size();
for (int i = len / 2 - 1; i >= 0; --i)
maxHeapify(nums, i, len - 1);//从最后一个父子结点开始heapify
for (int i = len - 1; i > 0; --i) {
swap(nums[0], nums[i]);
maxHeapify(nums, 0, i - 1);
}
}
优先队列的实现
priority_queue传入的第三个参数是仿函数,是将新插入数据与父结点进行比较,
原本是:if (_con[child] > _con[parent])
使用仿函数:if (com(_con[child] , _con[parent]))
因此,不难理解 less < 对应大顶堆了,当父结点小于子结点的时候,会进行交换,从而将大的值转换到父结点,从而堆顶就是最大元素了;
这里记住,是将父结点与子结点进行比较,满足条件(置true才进行交换)就很容易记住哪个对应大顶堆,哪个对应小顶堆了
#pragma once
#include<iostream>
#include<vector>
using namespace std;
//大堆
template<class T,class Container = vector<T>,class Compare = less<T>>
class priority_queue
{
template<class T>
class less
{
public:
bool operator()(const T& l, const T& r)
{
return l < r;
}
};
template<class T>
class greater
{
public:
bool operator()(const T& l, const T& r)
{
return l > r;
}
};
public:
priority_queue()
{}
template<class InputIterator>
priority_queue(InputIterator first, InputIterator last)
{
while (first != last)
{
_con.push_back(*first);
++first;
}
//建堆
for (int i = (_con.size() - 1 - 1) / 2; i >= 0; i--)
{
adjust_down(i);
}
}
void adjust_up(size_t child)
{
Compare com;
size_t parent = (child - 1) / 2;
while (child > 0)
{
if (com(_con[child] , _con[parent]))
{
swap(_con[child], _con[parent]);
child = parent;
parent = (child - 1) / 2;
}
else
break;
}
}
void adjust_down(size_t parent)
{
Compare com;
size_t child = parent * 2 + 1;
while (child < _con.size())
{
if (child + 1 < _con.size() && com(_con[child] , _con[child + 1]))
++child;
if (com(_con[child] , _con[parent]))
{
swap(_con[child], _con[parent]);
parent = child;
child = 2 * parent + 1;
}
else
break;
}
}
void push(const T& x)
{
_con.push_back(x);
adjust_up(_con.size()-1);
}
void pop()
{
swap(_con[0], _con[_con.size() - 1]);
_con.pop_back();
adjust_down(0);
}
const T& top()
{
return _con[0];
}
bool empty() const
{
return _con.empty();
}
size_t size() const
{
return _con.size();
}
private:
Container _con;
};