🌏博客主页: 主页
🔖系列专栏: C++
❤️感谢大家点赞👍收藏⭐评论✍️
😍期待与大家一起进步!
补充知识:仿函数
C++仿函数(function object)是一种可以像函数一样调用的对象。仿函数通常是一个类,它重载了函数调用运算符operator(),使得对象可以被调用。
仿函数就是基于函数模板生成的一种特定类型的函数对象。
仿函数是模板函数,其速度比一般函数要慢,
仿函数在一定程度上使代码更通用,本质上简化了代码
一、优先级队列:
1.引入
优先级队列(Priority Queue)在底层实现上使用了一种称为堆(Heap)的数据结构,通常使用数组(比如C++中的std::vector)来表示。堆是一种完全二叉树数据结构,具有以下特点:
- 堆是一个完全二叉树,也就是说除了最底层,其他层都必须是完全填满的,最底层的节点依次从左到右填充。
2.堆中的每个节点的值都大于等于(或小于等于)其子节点的值,这就是所谓的堆序性质。
2.介绍
- 优先队列是一种容器适配器,根据严格的弱排序标准,它的第一个元素总是它所包含的元素中最大的。
- 此上下文类似于堆,在堆中可以随时插入元素,并且只能检索最大堆元素(优先队列中位于顶部的元素)。
- 优先队列被实现为容器适配器,容器适配器即将特定容器类封装作为其底层容器类
- 底层容器可以是任何标准容器类模板,也可以是其他特定设计的容器类。容器应该可以通过随机访问迭
代器访问,并支持以下操作:
empty():检测容器是否为空
size():返回容器中有效元素个数
front():返回容器中第一个元素的引用
push_back():在容器尾部插入元素
pop_back():删除容器尾部元素- 标准容器类vector和deque满足这些需求。默认情况下,如果没有为特定的priority_queue类实例化指定容器类,则使用vector。
虽然底层实现中使用了vector,但优先级队列仍然保持了队列的特性,即根据优先级出队元素
二、priority_queue的模拟实现
1.大体框架
namespace simulation {
template<class T, class Container = vector<T>, class Compare = less<T>>
//Compare这里传的是仿函数,默认为系统里自带的less仿函数,也可以自己添加
//用于比较大小,Container为底层实现容器,默认为vector
class priority_queue {
private://私有成员函数
void AdjustDown(int parent) {
}
void AdjustUp(int child) {
}
public://公有成员函数
void pop() { }
void push(const T & x) {}
const T& top() { }
bool empty() {}
size_t size() {}
priority_queue(){}
private:
Container _con;//成员变量
};
2.私有成员函数:
1.向下调整(AdjustDown)
图中是在建小堆,但我们代码以大堆为例,除了大于小于的方向不同,但逻辑是一样的
void AdjustDown(int parent) {
//向下调整条件:
// 左右子树都是大堆/小堆
int child = parent * 2 + 1;
Compare com;//仿函数的实例化
while (child < _con.size()) {
if (child + 1 < _con.size() && com(_con[child], _con[child + 1])) {
++child;//选出两个孩子中最大的那一个
}
if (com(_con[parent], _con[child])) {
//最大的那一个去与父母比较
swap(_con[parent], _con[child]);
parent = child;
child = parent * 2 + 1;
}
else {
break;
}
}
}
2.向上调整(AdjustUp)
void AdjustUp(int child) {
//向上调整条件:
// 除了child这个位置前面的数据构成堆
int parent = (child - 1) / 2;
Compare com;
while (child > 0) {
if (com(_con[parent], _con[child])) {
swap(_con[parent], _con[child]);
child = parent;
//接着向上
parent = (child - 1) / 2;
}
else {
break;
}
}
}
3.公有成员函数
1大小(size).
2是否为空(empty).
3.移除堆顶的元素(pop)
文章来源:https://www.toymoban.com/news/detail-615990.html
void pop() {
swap(_con[0], _con[_con.size() - 1]);
_con.pop_back();
AdjustDown(0);
}
4.元素插入(push)
文章来源地址https://www.toymoban.com/news/detail-615990.html
void push(const T& x) {
_con.push_back(x);
//新元素向上调整
AdjustUp(_con.size() - 1);
}
5.堆顶的元素(top)
const T& top() {
return _con[0];
}
6.构造函数
1.默认无参构造
priority_queue() {
//内容可以什么都不写,因为初始化会去内置类型不用管,自定义类型会去调用其
//默认构造函数,这里会直接调用成员变量_con的默认构造
//当你写了迭代器构造后,这个无参构造你必须要有,因为当你写了一个构造函数
//以后,编译器就不会自己再生成默认构造函数
}
2.迭代器构造
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--) {
AdjustDown(i);
}
}
到了这里,关于【C++】优先级队列的基本概念以及其模拟实现的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!