【C++进阶(六)】STL大法--栈和队列深度剖析优先级队列适配器原理

news2024/12/28 19:24:11

💓博主CSDN主页:杭电码农-NEO💓

⏩专栏分类:C++从入门到精通⏪

🚚代码仓库:NEO的学习日记🚚

🌹关注我🫵带你学习C++
  🔝🔝


在这里插入图片描述

栈和队列

  • 1. 前言
  • 2. 栈和队列的接口函数熟悉
  • 3. 适配器介绍
  • 4. 栈和队列的模拟实现
  • 5. deque的简单介绍
  • 6. 优先级队列深度剖析
  • 7. 优先级队列的模拟实现
  • 8. 总结以及拓展

1. 前言

和C语言学习期间的学习顺序一样
顺序表,链表过了就是栈和队列
但是栈和队列非常特殊,它的内部结构
并不是靠自己实现的,而是一种适配器模式

本章重点:

本篇文章着重讲解适配器原理
和栈,队列的接口函数熟悉以及模拟实现
适配器里有一个特殊容器:deque
最后讲解优先级队列相关知识和实现

在这里插入图片描述

在这里插入图片描述


2. 栈和队列的接口函数熟悉

栈的接口函数熟悉:

在这里插入图片描述

由于栈结构只能支持栈顶插入,栈顶pop
所以它的接口很少,这里就不多介绍了!

队列的接口函数熟悉:

在这里插入图片描述

队列只比栈多了一个接口:back
队列的front相当于栈的top

在了解了接口函数后,可以尝试做几个题巩固

  1. 最小栈
  2. 栈的压入,弹出序列
  3. 逆波兰表达式求值
  4. 用两个栈实现队列

3. 适配器介绍

先看栈和队列的类模板:

在这里插入图片描述

我们发现第二个模板参数是:Container
并且它还有缺省值为 deque<T>

这里就直接引出一个概念: 适配器

适配器是一种设计模式(设计模式是一套被反复使用的、多数人知晓的、经过分类编目的、代码设计经验的总结),该种模式是将一个类的接口转换成客户希望的另外一个接口。

一个比较经典的例子就是插头的适配器:

在这里插入图片描述

那么在数据结构栈中,这种适配器是什么呢?

很显然,在C语言阶段实现栈时,我们
使用的底层是顺序表来实现,也就是
把顺序表做了一层封装和限制,让它
的功能变得和栈一样,C++这里也是一样!

我们在实现栈时不用再去写一个顺序表
而是直接调用库中的vector!


4. 栈和队列的模拟实现

栈的模拟实现要复用其他数据结构
所以在定义模板时要定义两个!

template<class T, class Container = deque<T>>
class Stack
{
	//......
private:
	Container _con;
}

我们和库中的缺省值保持一致,使用deque
这个容器我们后面会有所解释!

这样使用栈非常的方便!因为此时的栈
就像"富二代"一样,不用写构造和析构函数
因为默认生成的构造或析构会去调用
内嵌类型的构造或析构帮助我们完成任务!

在此之后,只需要实现一些接口函数即可!

void push(const T& val)
{
	_con.push_back(val);
}

void pop()
{
	_con.pop_back();
}

T& top()//可读可写
{
	return _con.back();
}

const T& top() const
{
	return _con.back();
}

bool empty() const
{
	return _con.empty();
}

size_t size() const
{
	return _con.size();
}

注:函数中的push_back或back等
函数接口是调用适配器中的!如vector中的

栈的结构实现完成,队列就交给你们了!


5. deque的简单介绍

deque也是一个STL库中的容器
先来看看它的介绍:

在这里插入图片描述

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

在这里插入图片描述

接下来看看它的接口函数:

在这里插入图片描述

deque既有头插头删也有尾插尾删
这是意料之中,它也支持方括号[]
其实对于deque的了解到这里就差不多了
下面的内容属于拓展了解,有兴趣的可以看看

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

在这里插入图片描述
deque扩容是直接另外开辟一份空间
再让中控数组指向新开辟的空间
再将原先空间的内容拷贝至新空间

注意它有一个中控数组的概念!


6. 优先级队列深度剖析

优先级队列的英文是: priority_queue
它也是一个容量适配器,文档的大致翻译:

在这里插入图片描述
在这里插入图片描述

优先级队列默认是大堆!

在这里插入图片描述

并且它的底层适配器默认是vector

优先级队列默认有三个类模板,然而第三个
模板就是决定此优先级队列是大堆还是小堆
它叫仿函数,我们先不管它,下一篇文章回讲解
我们需要了解的是,默认的less是大堆
我们显示传参greater时是小堆!

优先级队列的接口函数熟悉:

在这里插入图片描述

注:如果你想使用小堆,就要将前两个
模板参数实例化后才能实例化第三个
当less变成greater时,就是小堆


7. 优先级队列的模拟实现

在学习仿函数之前,先实现无仿函数版本:

基本结构和框架:

template<class T, class Container = vector<T>>
class Priority_queue
{
public:
	//成员函数
private:
	Container _con;//此容器可能是vector可能是deque
};

由于优先级队列是"富二代",所以
构造,析构和拷贝构造都可以忽略不写

优先级队列的插入和删除操作:

由于优先级队列实际上就是个堆
所以在插入,删除之后.都需要做一件事
那就是向上调整或向下调整!所以插入和
删除的关键其实就在于向上/下调整!

向上调整:

void AdjustUp(int* a, int child)
{
	int parent = (child - 1) / 2;
	while (child > 0)
	{
		if (a[child] > a[parent])
		{
			swap(&a[child], &a[parent]);
			child = parent;
			parent = (child - 1) / 2;
		}
		else
		{
			break;
		}
	}
}

向下调整:

void AdjustDown(int* a, int n, int parent)
{
	int child = parent * 2 + 1;
	while (child < n)
	{
		if (a[child+1] < a[child] && child + 1 < n)
		{
			child++;
		}
		if (a[child] < a[parent])
		{
			swap(&a[child], &a[parent]);
			parent = child;
			child = parent * 2 + 1;
		}
		else
		{
			break;
		}
	}
}

这两个操作在学习堆时就已经实现过了,老朋友了

详情可看: 堆以及topk问题

优先级队列的插入和删除

void push(const T& val)//堆的插入
{
	_con.push_back(val);
	adjust_up(_con.size() - 1);
}

void pop()//堆的删除
{
	std::swap(_con[0], _con[_con.size() - 1]);
	_con.pop_back();
	adjust_down(0);
}

插入和删除可谓是和堆的做法一模一样
其他的函数接口也是如此,这里就不多解读
我把优先级队列模拟实现的所有代码分享出来:

优先级队列模拟实现全部代码


8. 总结以及拓展

其实我们可以感受到,有了前面STL
容器的学习,现在学习栈和队列要轻松许多
不仅是模拟实现上可以复用以前的容器
连使用方法和函数接口都和之前一样
这就是C++STL的魅力所在!

拓展阅读:
对于deque我们还有很多未知的地方
比如它的扩容是怎样完成的?是否是缩容?
deque是如何支持随机访问的?deque的缺陷?

有兴趣的老铁可以阅读下面这篇文章:

deque深度剖析


🔎 下期预告:模板进阶以及仿函数 🔍

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

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

相关文章

django 实现:闭包表—树状结构

闭包表—树状结构数据的数据库表设计 闭包表模型 闭包表&#xff08;Closure Table&#xff09;是一种通过空间换时间的模型&#xff0c;它是用一个专门的关系表&#xff08;其实这也是我们推荐的归一化方式&#xff09;来记录树上节点之间的层级关系以及距离。 场景 我们 …

百度交易中台之内容分润结算系统架构浅析

作者 | 交易中台团队 导读 随着公司内容生态的蓬勃发展&#xff0c;内容产出方和流量提供方最关注的“收益结算”的工作&#xff0c;也就成为重中之重。本文基于内容分润结算业务为入口&#xff0c;介绍了实现过程中的重难点&#xff0c;比如千万级和百万级数据量下的技术选型和…

使用 AI 编程助手 CodeWhisperer,开发如有神助

前段时间体验了chatGPT&#xff0c;听说它可以写代码&#xff0c;结果发现更多的只是一个对答写小作文的百度助手&#xff0c;虽然也能写代码&#xff0c;但不是我想要的&#xff0c;可以在 idea 中可以快速生成代码块的。一个偶然的机会&#xff0c;从微信群里了解到&#xff…

科技云报道:大模型的阴面:无法忽视的安全隐忧

科技云报道原创。 在AI大模型的身上&#xff0c;竟也出现了“to be or not to be”问题。 争议是伴随着大模型的能力惊艳四座而来的&#xff0c;争议的核心问题在于安全。安全有两个方面&#xff0c;一个是大模型带来的对人类伦理的思考&#xff0c;一个是大模型本身带来的隐…

Unity实现设计模式——解释器模式

Unity实现设计模式——解释器模式 解释器模式&#xff08;Interpreter Pattern&#xff09;是一种按照规定语法进行解析的模式&#xff0c;现实项目中用得较少。 给定一门语言&#xff0c;定义它的文法的一种表示&#xff0c;并定义一个解释器&#xff0c;该解释器使用该表示来…

在windows的ubuntu LTS中安装及使用EZ-InSAR进行InSAR数据处理

EZ-InSAR&#xff08;曾被称为MIESAR&#xff0c;即Matlab界面用于易于使用的合成孔径雷达干涉测量&#xff09;是一个用MATLAB编写的工具箱&#xff0c;用于通过易于使用的图形用户界面&#xff08;GUI&#xff09;进行干涉合成孔径雷达&#xff08;InSAR&#xff09;数据处理…

网络基础(了解网络知识的前提)

前言 在正式学习网络之前&#xff0c;我们需要了解的一些关于计算机网络的基本知识&#xff0c;本文主要阐述这些基本知识&#xff0c;带着大家一步一步迈进互联网网络的世界&#xff1b; 一、局域网与广域网的概念 在正式了解这些概念的前提是我们要搞懂网络出现的意义&#x…

Linux高级应用——web网站服务

作者简介&#xff1a;一名云计算网络运维人员、每天分享网络与运维的技术与干货。 公众号&#xff1a;网络豆云计算学堂 座右铭&#xff1a;低头赶路&#xff0c;敬事如仪 个人主页&#xff1a; 网络豆的主页​​​​​ 目录 前言 一.Apache 1.Apache介绍 2.Apache的特…

【AI绘画】Stable Diffusion WebUI

&#x1f49d;&#x1f49d;&#x1f49d;欢迎来到我的博客&#xff0c;很高兴能够在这里和您见面&#xff01;希望您在这里可以感受到一份轻松愉快的氛围&#xff0c;不仅可以获得有趣的内容和知识&#xff0c;也可以畅所欲言、分享您的想法和见解。 推荐:kuan 的首页,持续学…

gitee 远程仓库操作基础(一)

git remote add <远程仓库名> <仓库远程地址> :给远程仓库取个别名,简化一大堆字符串操作 git remote add origin xxx.git :取个Origin名字 git remote -v :查看本地存在的远程仓库 git pull <远程仓库名><远程分支名>:<本地分支名> 相同可取消…

【SpringBoot实践】事务和事务传播机制失效原因正确使用事务的建议

文章目录 1.概述2.事务与事务传播2.1 声明式事务说明2.2.声明式事务失效原因2.3.事务的传播机制2.4.事务传播失效原因 3.事务使用建议4.总结 1.概述 我们在开发工作中经常会使用到事务&#xff0c;来保证数据库做增、删、改操作时的数据一致性&#xff0c;在使用Spring来处理事…

【c语言】通讯录【动态版本:有排序和文件操作】

目录 一、通讯录定义 二、通讯录的实现 1、test.c中菜单的实现 2、通讯录的创建逻辑 3、初始化 4、检查容量和添加 5、查找 6、删除功能 7、修改功能 8、打印 9、查找并打印 10、qsort排序 11、摧毁 12、保存数据到文件 13、从文件中读数据 完整代码&#xff1a; 一、通讯录定…

Windows上安装 Go 环境

一、下载go环境 下载go环境&#xff1a;Go下载官网链接找到自己想下载的版本&#xff0c;点击下载&#xff0c;比如我这是windows64位的&#xff0c;我就直接点击最新的。 二、安装go环境 双击下载的.msi文件 next next 他默认的是c盘&#xff0c;你自己可以改&#xff0c;然…

Android 导入ncnn-android-yolov8-seg : 实现人体识别和人像分割

1. 前言 上篇文章我们在Android中使用OpenCV实现了人脸识别&#xff0c;这篇文章我们使用OpenCVYOLOv8NCNN 来实现人像分割的功能。 首先来看下效果&#xff0c;这里会识别出人体&#xff0c;并会用蓝色的框框出来&#xff0c;并会有标签标注识别出的物体是什么&#xff0c;概…

Python爬虫实战案例——第六例

文章中所有内容仅供学习交流使用&#xff0c;不用于其他任何目的&#xff01;严禁将文中内容用于任何商业与非法用途&#xff0c;由此产生的一切后果与作者无关。若有侵权&#xff0c;请联系删除。 目标&#xff1a;去哪儿网指定城市人气值最高的15个景点评论数据采集 地址&a…

趣解设计模式之《小王的披萨店》

〇、小故事 小王看到最近越来越多的人喜欢吃披萨了&#xff0c;所以&#xff0c;他决定自己也开一个披萨店。最初开的时候&#xff0c;他只提供了一种口味的披萨&#xff0c;因为这样先试试水&#xff0c;看看生意如何&#xff0c;如果生意不好&#xff0c;也可以快速止损。 没…

一道签到题目 签到.zip

一道签到题目 https://www.xuenixiang.com/ctfexercise-competition-589.html 下载附件&#xff1a;签到.zip双击打开zip包。 进行base64转换 在线 Unicode 编码转换 | 菜鸟工具 (runoob.com) 获得压缩包密码&#xff1a;haishi 文字倒序工具,在线文字倒序 (qqxiuzi.cn)

一招根治Windows自带杀毒软件 Microsoft Defender

以毒攻毒&#xff1a;用腾讯电脑管家的文件粉碎机将Microsoft Defender 文件粉碎&#xff0c;再卸载腾讯电脑管家。 整个世界都安静了。 开机任务管理器就能看到 Microsoft Defender 又瞎忙起来了 打开文件位置&#xff1a; 记录下此时该文件的路径&#xff08;保存在记事本里…

使用SPY++查看窗口信息去排查客户端UI软件问题

目录 1、使用SPY查看窗口的信息 2、使用SPY查看某些软件UI窗口用什么UI组件实现的 2.1、查看海康视频监控客户端安装包程序 2.2、查看华为协同办公软件WeLink 2.3、查看字节协同办公软件飞书 2.4、查看最新版本的Chrome浏览器 2.5、查看小鱼易连视频会议客户端软件 2.6…

cad图纸如何防止盗图(一个的制造设计型企业如何保护设计图纸文件)

在现代企业中&#xff0c;设计图纸是公司的重要知识产权&#xff0c;关系到公司的核心竞争力。然而&#xff0c;随着技术的发展&#xff0c;员工获取和传播设计图纸的途径越来越多样化&#xff0c;如何有效地防止员工复制设计图纸成为了企业管理的一大挑战。本文将从技术、管理…