一、优先级队列
1、 优先队列是一种容器适配器,根据严格的弱排序标准,它的第一个元素总是它所包含的元素中最大的。
2、 此上下文类似于堆,在堆中可以随时插入元素,并且只能检索最大堆元素(优先队列中位于顶部的元素)。
3、 优先队列被实现为容器适配器,容器适配器即将特定容器类封装作为其底层容器类,queue提供一组特定的成员函数来访问其元素。元素从特定容器的“尾部”弹出,其称为优先队列的顶部。
4、 底层容器可以是任何标准容器类模板,也可以是其他特定设计的容器类。容器应该可以通过随机访问迭代器访问,并支持以下操作:
empty() | 检测容器是否为空 |
---|---|
size() | 返回容器中有效元素个数 |
front() | 返回容器中第一个元素的引用 |
push_back() | 在容器尾部插入元素 |
pop_back() | 删除容器尾部元素 |
5、标准容器类 vector和deque(双端队列) 满足这些需求。默认情况下,如果没有为特定的priority_queue类实例化指定容器类,则使用vector。
6、需要支持随机访问迭代器,以便始终在内部保持 堆结构。容器适配器通过在需要时自动调用算法函数make_heap、push_heap和pop_heap来自动完成此操作。
二、优先级队列的使用
#include <iostream>
#include <functional>
#include <queue>
using namespace std;
//仿函数,函数对象
//struct Less
//{
// bool operator()(int left, int right)
// {
// return left < right;
// }
//};
template<class T>
struct Less
{
bool operator()(const T& left, const T& right)
{
return left < right;
}
};
int main()
{
//priority_queue<int> pq;//默认是传less比较生成大堆
priority_queue<int, vector<int>, greater<int>> pq;//也可传greater,此时生成的是小堆
pq.push(3);
pq.push(2);
pq.push(5);
pq.push(0);
pq.push(7);
pq.push(3);
while (pq.empty() != 1)
{
cout << pq.top() << " ";
pq.pop();
}
cout << endl;
int a = 1; int b = 2;
Less<int> less;//是一个对象,但是可以像使用一个函数一样使用它,称为仿函数
cout << less(a, b) << endl;
cout << less.operator()(a, b) << endl;
return 0;
}
三、优先级队列的模拟实现
#pragma once
#include <iostream>
#include <vector>
#include <deque>
using namespace std;
template<class T, class Container = vector<T>, class Compare = less<T>>
class PriorityQueue
{
public:
void Adjustdown(size_t parent)//向下调整算法
{
size_t child = parent * 2 + 1;
while (child < _con.Size())
{
if (_con[child] < _con[child + 1])
++child;
if (_con[parent] < _con[child])
{
swap(_con[parent], _con[child]);
parent = child;
child = parent * 2 + 1;
}
else
{
break;
}
}
}
void AdjustUp(size_t child)//向上调整算法
{
size_t parent = (child - 1) / 2;
while (child)
{
if (_con[parent] < _con[child])
{
swap(_con[parent], _con[child]);
child = parent;
parent = (child - 1) / 2;
}
else
{
break;
}
}
}
void Push(const T& x)//尾插
{
_con.push_back(x);
AdjustUp(_con.size() - 1);
}
void Pop()//头删
{
swap(_con[0], _con[_con.Size() - 1]);
_con.pop_back();
Adjustdown(0);
}
const T& Top()
{
return _con[0];
}
size_t Size() const
{
return _con.size();
}
bool Empty() const
{
return _con.empty();
}
private:
Container _con;
};
class Goods
{
public:
bool operator<(const Goods r) const
{
return _price < r._price;
}
public:
int _price;
int _sales_volume;
int _evaluation;
int _comprehensive;
};
struct GoodsPriceLess
{
bool operator()(const Goods& l, const Goods& r)
{
return l._price < r._price;
}
};
struct GoodsPriceGreater
{
bool operator()(const Goods& l, const Goods& r)
{
return l._price > r._price;
}
};
void TestPriorityQueue()
{
PriorityQueue<Goods, vector<Goods>, GoodsPriceLess> goodspq;
goodspq.Push(Goods{ 1, 2, 3, 4 });
goodspq.Push(Goods{ 4, 3, 2, 1 });
Goods top = goodspq.Top();
cout << top._price << endl;
cout << top._sales_volume << endl;
cout << top._evaluation << endl;
cout << top._comprehensive << endl;
}
注: 1、这里简单实现了优先队列的功能,底层容器用的是vector,在这里我没写优先级队列的构造函数以及析构函数,用了系统默认生成的即可。
2、测试函数中我给出了一个自定义类型,是为了测试一下自己写的仿函数,我们都知道显示生活中有很多时候我们比较时不仅仅只比较一方面,就像是一个商品我们可能会按价格比较,也可能按人气比较,或是按综合评价比较,这个时候我们用仿函数就比较方便了,我们只要按照需求写一个对应比较的仿函数就可以实现相关功能。