当前位置: 首页 > news >正文

C++——STL容器【priority_queue】模拟实现

在这里插入图片描述

本章代码:优先级队列模拟实现、priority_queue文档

文章目录

  • 🐈1. priority_queue介绍
  • 🦄2. priority_queue模拟实现
    • 🐧2.1 构造函数
    • 🐧2.2 建堆
      • 向下调整
      • 向上调整
    • 🐧2.3 仿函数
    • 🐧2.4 push & pop操作
    • 🐧2.5 top & empty & size

🐈1. priority_queue介绍

priority_queue在STL里面是队列的一种,叫做优先级队列,它的底层是基于实现的,默认的是大堆。

它的使用方法与queue类似,可理解为priority_queue是一个可以排序的队列

🦄2. priority_queue模拟实现

先查看文档,看看支持了哪些接口:

image-20230806212745863

🐧2.1 构造函数

priority_queue采用的vector作为容器适配器,那默认构造直接调用vector的就行,然后构造还支持迭代器初始化:

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--){AdjustDown(i);}}
}

🐧2.2 建堆

向下调整的时间复杂度是O(N),向上调整的时间复杂度是O(N*logN),所以采用向下调整建堆

详细讲解可查看:数据结构——二叉树(堆、堆排序、二叉树链式结构)

向下调整

//向下调整 默认大堆
void AdjustDown(int parent)
{int child = parent * 2 + 1;while (child < _con.size()){if (child + 1 < _con.size() && _con[child + 1] > _con[child]){child = child + 1;}if (_con[child] > _con[parent]){std::swap(_con[child], _con[parent]);parent = child;child = parent * 2 + 1;}else{break;}}
}

向上调整

//向上调整
void AdjustUp(int child)
{int parent = (child - 1) / 2;while (child > 0){if (_con[child] > _con[parent]){std::swap(_con[child], _con[parent]);child = parent;parent = (child - 1) / 2;}else{break;}}
}

🐧2.3 仿函数

STL的priority_queue默认是大堆,如果想要指定小堆,则需要在参数列表里面指定参数

std::priority_queue<int> maxHeap;  // 默认:大堆
std::priority_queue<int, std::vector<int>, std::greater<int>> minHeap;	//小堆

这里我们要实现,就要用到仿函数

仿函数是一个,它重载了函数调用运算符operator(),这使得这个类就可以想函数一样被调用

在这里我们就重载operator()来模拟比较函数

template<class T>
class Less
{
public:bool operator()(const T& x, const T& y){return x < y;}};template<class T>
class Greater
{
public:bool operator()(const T& x, const T& y){return x > y;}};

priority_queue不指定的情况下,默认是大堆,指定模板时将Less设为缺省参数即可

template<class T, class Container = vector<T>, class Compare = Less<T>>
class priority_queue

有了仿函数,我们的向下调整和向上调整在选择建大堆或者小堆的时候,调用这个仿函数即可:

//向下调整 默认大堆
void AdjustDown(int parent)
{Compare com;int child = parent * 2 + 1;while (child < _con.size()){//if (child + 1 < _con.size() && _con[child + 1] > _con[child])if (child + 1 < _con.size() && com(_con[child], _con[child + 1])){child = child + 1;}//if (_con[child] > _con[parent])if (com(_con[parent], _con[child])){std::swap(_con[child], _con[parent]);parent = child;child = parent * 2 + 1;}else{break;}}
}
//向上调整
void AdjustUp(int child)
{Compare com;int parent = (child - 1) / 2;while (child > 0){//if (_con[child] > _con[parent])if (com(_con[parent], _con[child])){std::swap(_con[child], _con[parent]);child = parent;parent = (child - 1) / 2;}else{break;}}
}

🐧2.4 push & pop操作

  • 插入操作即在队尾增加一个元素,然后向上调整,保证这还是一个堆

  • 删除操作还是模拟堆的操作,将首元素和最后一个元素交换,然后删除队尾元素

    这样保证了即使删除之后,下面的还是一个堆,接下来向下调整即可

void pop()
{std::swap(_con[0], _con[_con.size() - 1]);_con.pop_back();AdjustDown(0);
}
void push(const T& x)
{_con.push_back(x);AdjustUp(_con.size() - 1);
}

🐧2.5 top & empty & size

emptysize直接调用vector的接口即可;top查看队头元素,返回队头元素即可

const T& top() const
{return _con[0];
}
bool empty() const
{return _con.empty();
}
size_t size()
{return _con.size();
}

那本期的分享就到这咯,我们下期再见,如果还有下期的话

http://www.lryc.cn/news/112582.html

相关文章:

  • SpringBoot实现文件记录日志,日志文件自动归档和压缩
  • MySQL 窗口函数
  • 0140 数据链路层2
  • Python字典的应用场景
  • 关于外贸跟进客户过程中需要注意的地方
  • AI绘画:两组赛博咒语和ComfyUI使用方法
  • Nacos源码 (2) 核心模块
  • MySQL之深入InnoDB存储引擎——Buffer Pool
  • 网络安全(秋招)如何拿到offer?(含面试题)
  • 笙默考试管理系统-MyExamTest----classranking(2)
  • 基于python的一个元素多种定位方式
  • Fastdfs集群搭建
  • 【深度学习】Vision Transformer论文,ViT的一些见解《 一幅图像抵得上16x16个词:用于大规模图像识别的Transformer模型》
  • 在centos7上使用非编译方式安装ffmpeg
  • 【微信小程序】导出Excel文件
  • 接口测试—知识速查(Postman)
  • 机器学习深度学习——序列模型(NLP启动!)
  • 小白到运维工程师自学之路 第六十四集 (dockerfile构建tomcat、mysql、lnmp、redis镜像)
  • 超低功耗水表电器表LCD驱动显示芯片,高抗干扰性能提供LQFP48、LQFP64的封装
  • SpringBoot3---核心特性---2、Web开发III(模板引擎、国际化、错误处理)
  • MemFire教程|FastAPI+MemFire Cloud+LangChain开发ChatGPT应用-Part2
  • C# File.Exists与Directory.Exists用法
  • (深度学习,自监督、半监督、无监督!!!)神经网络修改网络结构如何下手???
  • Codejock Task Panel ActiveX Crack
  • LeetCode 热题 100 JavaScript--141. 环形链表
  • 文字转语音
  • 让ELK在同一个docker网络下通过名字直接访问
  • EventBus 开源库学习(一)
  • 车载以太网SOME/IP的个人总结
  • vue2.29-Vue3跟vue2的区别