双端队列(deque)与优先队列(priority_queue)

文章目录

  • 一.双端队列——deque
    • 1.deque的优点与缺点
    • 2.deque的原理
  • 二.优先队列——priority_queue
    • 1.什么是优先队列?
    • 2.优先队列的基本使用
    • 3.什么是仿函数?
    • 4.优先队列的模拟实现

一.双端队列——deque

在上一章stack、queue的模拟实现中,我们使用的是vector 来作为底层容器。但是,在标准库中,都是使用deque来作为底层容器的,那么deque究竟为何能受到青睐呢?

1.deque的优点与缺点

deque对标的是vectorlist,我们可以认为dequevectorlist的结合并且取其精华去其糟粕。

vector的优缺点

  1. 尾插尾删效率高,头插头删效率低
  2. 支持随机访问
  3. 扩容代价高

list的优缺点

  1. 头删头插效率高
  2. 尾插尾删效率高
  3. 不支持随机访问
  4. 不需要扩容

deque的优点

  1. 头删头插效率高
  2. 尾插尾删效率高
  3. 支持随机访问
  4. 扩容代价低(相比vector
  • deque看起来挺不错的,完美的继承了vectorlist的优点。但是,既然deque这么优秀,为什么我们又好像没怎么学习过它呢?答案是,它也有它的缺点。

deque的缺点

  1. 中间插入或删除效率低
  2. 没有vectorlist的优点那么极致

deque的产生就像是什么呢?就例如,我继承了爱因斯坦的高智商,又继承了泰森的力量,但是继承的过程有一些损耗,所以我既没有爱因斯坦极致的智商,又没有泰森极致的力量,我只是个普通人。所以我们说,deque相当于vectorlist的结合产品。

deque看似很中庸,实际用处不大,但是,作为stackqueue的底层容器却又刚好合适,因为栈和队列的性质完美的避开了deque的缺点,只用到了deque的优点——栈和队列只对头部或者尾部进行操作。

2.deque的原理

对于deque,我们只需要大致认识它的底层结构即可。

deque(双端队列):是一种双开口的“连续”空间的数据结构,双开口的含义是:可以在头尾两端进行插入和删除操作,且时间复杂度为O(1),与vector比较,头插效率高,不需要搬移元素;与list比较,空间利用率比较高。

在这里插入图片描述
deque并不是真正连续的空间,而是由一段段连续的小空间拼接而成的,实际deque类似于一个动态的二维数组,其底层结构如下图所示:

在这里插入图片描述

双端队列底层是一段假象的连续空间,实际是分段连续的,为了维护其“整体连续”以及随机访问的假象,落在了deque的迭代器身上,因此deque迭代器设计就比较复杂,如下图所示:

在这里插入图片描述
deque是如何借助其迭代器维护其假想连续的结构呢?

在这里插入图片描述

对于deque我们只需做到了解就可以。

二.优先队列——priority_queue

1.什么是优先队列?

priority_queuestackqueue相同,都是一种容器适配器。默认使用vector作为其底层存储数据的容器,在vector上又使用了堆算法将vector中元素构造成堆的结构,因此priority_queue就是堆。

优先级队列允许你以任意顺序插入元素,并且每次弹出的元素是当前优先级最高(及最大或最小)的元素。在priority_queue中,元素的插入顺序不影响元素的优先级,而是根据其优先级属性进行排序。

2.优先队列的基本使用

  • 包含头文件 < queue >
#include <queue>
  • 定义一个priority_queue对象
priority_queue<int> pq;
  • 向队列中插入一个元素
pq.push(1);
pq.push(5);
pq.push(2);
  • 从队列中弹出一个元素(该元素为队列内优先级最高的元素)
pq.pop();
  • 返回队列中优先级最高的元素(及堆顶的元素)
cout << pq.top() << endl;
  • 返回队列中的元素数量
cout << pq.size() << endl;
  • 判断队列是否为空
//empty()
if (pq.empty())
{cout << "Queue is empty" << endl;
}
else
{cout << "Queue is not empty" << endl;
}

特别注意

优先级队列默认是建大堆,也就是元素的值越大,优先级越高。我们可以通过一个传递模板参数来控制优先级的判别。所以,优先级队列在设计的时候用到了3个模板参数,而我们上一章所学习的stackqueue则是2个模板参数,如图:

在这里插入图片描述

在这里插入图片描述

在这里插入图片描述

	// 默认情况下,创建的是大堆,其底层按照小于号比较priority_queue<int> pq1;// 如果要创建小堆,将第三个模板参数换成greater比较方式// 记得包含greater算法的头文件——#include <functional>priority_queue<int, vector<int>, greater<int>> pq2;

第三个模板参数仅仅只有比较大小的作用,我们也可以自己实现这样一个模板类来传递。像图中Compare这样的类所创建的对象,我们通常称它为——仿函数。因为该类的对象可以像函数一样使用。

3.什么是仿函数?

仿函数(functor)是一种行为类似于函数的对象,它可以像函数一样被调用。在C++中,仿函数通常是一个类,它重载了函数调用运算符operator(),并且可以像函数一样使用。

仿函数可以被用来封装一些操作或算法,它们可以被传递给其他函数或算法作为参数,或者作为返回值返回给调用者。由于仿函数是一个对象,因此可以在调用它们的过程中保持状态信息,这使得它们可以非常灵活地实现不同的行为。

例如上述的优先级队列又或是库中的sort函数,sort()函数可以接受一个仿函数对象作为第三个参数,这个仿函数对象将被用来比较两个元素的大小关系,这样我们就可以灵活的运用sort函数排序数列为升序或者降序了。

关于仿函数,我们点到为止。

4.优先队列的模拟实现

关于堆的结构前面已经详细讲解过点我

#include <iostream>
#include <vector>
using namespace std;namespace dianxia
{// 小于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类template<class T, class Container = vector<T>,class Compare=less<T>>class priority_queue{// 比较的对象Compare com;// 向上调整void adjust_up(int child){size_t  parent = (child - 1) / 2;while (child > 0){if (com(_con[parent] ,_con[child])){swap(_con[parent], _con[child]);child = parent;parent = (child - 1) / 2;}else{break;}}}// 向下调整void adjust_down(int parent){int child = parent * 2 + 1;while (child < _con.size()){// 确保child是两个孩子中大/小的那一个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;}}}public:void push(const T& data){_con.push_back(data);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];}size_t size(){return _con.size();}bool empty(){return _con.empty();}private:Container _con;};
}

本文到此结束,码文不易,还请多多支持哦!!!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/6671.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

Mysql 数据库开发及企业级应用

文章目录 1、Mysql 数据库开发及企业级应用1.1、为什么要使用数据库1.1.1、数据库概念&#xff08;Database&#xff09;1.1.2、为什么需要数据库 1.2、程序员为什么要学习数据库1.3、数据库的选择1.3.1、主流数据库简介1.3.2、使用 MySQL 的优势1.3.3、版本选择 1.4、Windows …

【VUE】解决图片视频加载缓慢/首屏加载白屏的问题

1 问题描述 在 Vue3 项目中&#xff0c;有时候会出现图片视频加载缓慢、首屏加载白屏的问题 2 原因分析 通常是由以下原因导致的&#xff1a; 图片或视频格式不当&#xff1a;如果图片或视频格式选择不当&#xff0c;比如选择了无损压缩格式&#xff0c;可能会导致文件大小过大…

unity 控制text根据字数自动扩展大小,并扩展UI背景

需求&#xff1a;文字内容位置保持不变&#xff0c;向下增加&#xff0c;背景框随之同步扩展。 1.UGUI 九宫格 拉伸 对背景框图片资源处理&#xff0c;避免图片拉伸。 (10条消息) unity UGUI 九宫格 拉伸_unity九宫格拉伸_野区捕龙为宠的博客-CSDN博客 2.背景框添加组件 3.…

php裁剪图片,并给图片加上水印

本次以裁剪四个图片为例&#xff0c;图片如下 代码如下 public function cutImg($imgUrl){try{// 读取原始图片$src_img imagecreatefromjpeg($imgUrl);// 获取原始图片的宽度和高度$src_width imagesx($src_img);$src_height imagesy($src_img);// 计算每个部分的宽度和高…

【数字信号处理】带通采样定理及其MATLAB仿真

目录 一、带通采样定理1.1 内容1.2 公式推导 二、MATLAB信号仿真2.1 信号仿真实验2.2 MATLAB代码 三、总结参考 一、带通采样定理 按照奈奎斯特采样定理(低通采样)&#xff0c;采样频率 f s f_{s} fs​ 要大于等于信号中最高频率 f m a x f_{max} fmax​ 的2倍&#xff0c;才…

C++OpenCV(2):图像处理基础概念与操作

&#x1f506; 文章首发于我的个人博客&#xff1a;欢迎大佬们来逛逛 &#x1f506; OpenCV项目地址及源代码&#xff1a;点击这里 文章目录 图形读取与显示加载图片显示图片打印图片信息保存图片 色彩模型转换RGB颜色模型HSV颜色模型HLS模型LAB模型 图像像素读写操作像素算数运…

macOS 源码编译 qpress

╰─➤ git clone https://github.com/PierreLvx/qpress.git ╰─➤ cd qpress ╰─➤ make g -O3 -o qpress -x c quicklz.c -x c qpress.cpp aio.cpp utilities.cpp -lpthread -Wall -Wextra -Werror ╰─➤ sudo make install …

怎么快速定位bug?怎么编写测试用例?

目录 01定位问题的重要性 02问题定位技巧 03初次怎么写用例 作为一名测试人员如果连常见的系统问题都不知道如何分析&#xff0c;频繁将前端人员问题指派给后端人员&#xff0c;后端人员问题指派给前端人员&#xff0c;那么在团队里你在开发中的地位显而易见 &#xff0c;口碑…

垃圾回收标记阶段算法

1.标记阶段的目的 主要是在GC在前&#xff0c;判断出哪些是有用的对象&#xff0c;哪些是需要回收的对象&#xff0c;只有被标记为垃圾对象&#xff0c;GC才会对其进行垃圾回收。判断对象是否为垃圾对象的两种方式&#xff1a;引用计数算法和可达性分析算法。 2.引用计数算法…

如何搭建使用dubbo-Admin?

dubbo-Admin介绍 一款用于dubbo可视化界面操作的管理平台 dubbo-Admin特点 dubbo-Admin是dubbo的管理界面平台&#xff0c;且是一个前后端分离的项目&#xff0c;前端使用vue&#xff0c;后端使用springboot。 软件下载 dubbo-admin-0.5.0.zip 软件使用

会议OA项目之会议审批(亮点功能:将审批人签名转换为电子手写签名图片)

&#x1f973;&#x1f973;Welcome Huihuis Code World ! !&#x1f973;&#x1f973; 接下来看看由辉辉所写的关于OA项目的相关操作吧 目录 &#x1f973;&#x1f973;Welcome Huihuis Code World ! !&#x1f973;&#x1f973; 一.主要功能点介绍 二.效果展示 三.前端…

MongoDB 的日常使用

一、简介 1、 常见的数据库分类 RDBMS&#xff08;关系型数据库&#xff09;&#xff1a;常见的关系型数据库有 Oracle、DB2、Microsoft SQL Server、Microsoft Access、MySQL&#xff1b; NoSQL&#xff08;非关系型数据库&#xff09;&#xff1a;常见的非关系型数据库有 …

thinkphp实现无限分类(使用递归)

thinkphp实现无限分类&#xff08;使用递归&#xff09; 本文实例为大家分享了thinkphp实现无限分类的详细代码&#xff0c;希望对大家学习无限分类有所启发。 数据库&#xff1a;test 数据表&#xff1a;&#xff08;tp_category&#xff09;&#xff1a; Common/conf/conf…

在VSCode中实现Rust编程调试指南

在 VS Code 中调试 Rust&#xff1a;终极指南 在本教程中&#xff0c;您将学习如何使用 VS Code 调试 Rust。可用于使用 VS Code 调试 Rust 的操作。设置 VS Code 来调试 Rust Rust因其易用性、安全性和高性能而继续保持其作为最受欢迎的编程语言的地位。随着 Rust 的流行&…

elementui el-table折叠表格,点击主表数据展开从表明细

用element-ui 的el-table实现&#xff1a;主表table可实现展开行显示关联的明细表table的列表数据&#xff0c;效果图如下 <el-tableref"tableData"v-loading"listLoading":data"tableData"row-key"id"borderstripehighlight-curr…

自动驾驶感知系统-激光雷达

感知系统 现有的车载传感器主要包括超声波雷达、激光雷达、毫米波雷达、车载摄像头、红外探头等。主流的自动驾驶感知平台以雷达和车载摄像头为主&#xff0c;呈现多传感器融合发展趋势。基于测量能力和环境适应性&#xff0c;预计雷达和车载摄像头会保持其感知平台霸主地位&a…

在react中配置less

第一步&#xff1a;暴露出webpack配置文件 终端命令&#xff1a;npm run eject (此命令一旦运行不可逆) 第二步&#xff1a;安装less以及less-loader npm install less less-loader --save-dev 第三步&#xff1a;修改webpack的配置文件 运行完以上命令后&#xff0c;项目…

精通自动化,Pytest自动化测试框架-fixture用例的前后置(实现)

目录&#xff1a;导读 前言一、Python编程入门到精通二、接口自动化项目实战三、Web自动化项目实战四、App自动化项目实战五、一线大厂简历六、测试开发DevOps体系七、常用自动化测试工具八、JMeter性能测试九、总结&#xff08;尾部小惊喜&#xff09; 前言 测试用例实现前后…

crmeb部署

安装宝塔 教程 安装所需要的软件 php mysql5.7 redis fileinfo nginx 安装crmeb 重启mysql 前台http://192.168.216.128/ 后台http://192.168.216.128/admin admin admin888登录 访问前台

自动化运维工具--saltstack部署及使用

目录 一、saltstack简介 1、介绍 2、Salt的核心功能 3、saltstack通信机制 二、saltstack部署 1、部署环境 2、配置yum源 3、安装master与minion 4、连接认证master和minion 三、salt运行 1、执行格式 2、实操演示 一、saltstack简介 1、介绍 saltstack是一个配置管…