C++初阶(stack+queue)

news/2024/5/22 0:28:23/文章来源:https://blog.csdn.net/jh035/article/details/128030196
  • stack是一种容器适配器,专门用在具有后进先出 (last-in first-out)操作的上下文环境中,其删除只能从容器的一端进行元素的插入与提取操作。
  • stack是作为容器适配器被实现的,容器适配器即是对特定类封装作为其底层的容器,并提供一组特定的成员函数来访问其元素,将特定类作为其底层的,元素特定容器的尾部(即栈顶)被压入和弹出。
  • stack的底层容器可以是任何标准容器,这些容器需要满足push_back,pop_back,back和empty几个接口的操作。
  • 标准容器vector、deque、list均符合这些需求,默认情况下,如果没有为stack指定特定的底层容器,默认情况下使用deque。

stack常用的接口

//构造函数
stack<T> stkT;//stack采用模板类实现,stack对象的默认构造形式
stack(const stack &stk);//拷贝构造函数
//赋值操作
stack&operator=(const stack &stk)//重载等号操作符
//数据存取操作
push(elem);//向栈顶添加元素
pop();//从栈顶移除一个元素
top();//返回栈顶元素
//容量大小操作
empty();//判断堆栈是否为空
size();//返回堆栈的大小

queue

queue介绍

queue是一种先进后出的数据结构(队列),它有两个出口,queue容器允许从一端新增元素,另一端移除元素

概述

  • 数据结构:连续的存储空间,有两个口,一个是进入数据,一个是出数据,有先进先出的特性
  • 迭代器:没有迭代器
  • 常用API
    • 构造函数
    • 存取、插入和删除
    • 赋值
    • 大小操作

总结:

  • 队列是一种容器适配器,专门用于在FIFO上下文(先进先出)中操作,其中从容器一端插入元素,另一端提取元素。
  • 队列作为容器适配器实现,容器适配器即将特定容器类封装作为其底层容器类,queue提供一组特定的成员函数来访问其元素。元素从队尾入队列,从队头出队列。
  • 和stack一样,它的底层容器可以是任何标准容器,但这些容器必满足push_back,pop_back,back和empty几个接口的操作。
  • 标准容器类deque和list满足了这些要求。默认情况下,如果没有为queue实例化指定容器类,则使用标准容器deque。

queue常用的接口

//构造函数
queue<T> queT;//queue采用模板类实现,queue对象的默认构造函数
queue(const queue &que);//拷贝构造函数
//存取、插入和删除操作
push(elem);//往队尾添加元素
pop();//从对头移除第一个元素
back();//返回最后一个元素
front();//返回第一个元素
//赋值操作
queue&operator=(const queue &que);//重载等号操作符
//容量大小操作
empty();//判断队列是否为空
size();//返回队列的大小

容器适配器

适配器: 一种设计模式,该种模式是将一个类的接口转换成客户希望的另外一个接口。

可以看出的是,这两个容器相比我们之间见过的容器多了一个模板参数,也就是容器类的模板参数,他们在STL中并没有将其划分在容器的行列,而是将其称为容器适配器,它们的底层是其他容器,对其他容器的接口进行了包装,它们的默认是使用deque(双端队列)

deque

vector容器时单向开口的连续内存空间,deque则是一种双向开口的连续线性空间。双开口的含义是:可以在头尾两端进行插入和删除操作,且时间复杂度为O(1),与vector比较,头插效率高,不需要搬移元素;与list比较,空间利用率比较高。

deque底层结构
它并不是一段连续的空间,而是由多个连续的小空间拼接而成,相当于一个动态的二维数组。

Deque容器是连续的空间,至少逻辑上看来如此,连续现行空间总是令我们联想到 array和vector,array无法成长,vector虽可成长,却只能向尾端成长,而且其成长其实 是一个假象,事实上(1)申请更大空间(2)原数据复制新空间(3)释放原空间三步骤,如果不是vector每次配置新的空间时都留有余裕,其成长假象所带来的代价是非常昂贵的。Deque是由一段一段的定量的连续空间构成。一旦有必要在前端或者尾端增加新的空间,便配置一段连续定量的空间,串接在deque的头端或者尾端。Deque最大的工作就是维护这些分段连续的内存空间的整体性的假象并提供随机存取的接口,避开了重新配置空间,复制,释放的轮回,代价就是复杂的迭代器架构。 既然deque是分段连续内存空间,那么就必须有中央控制,维持整体连续的假象数据结构的设计及迭代器的前进后退操作颇为繁琐。Deque代码的实现远比vector或list都多得多。

Deque采取一块所谓的map作为主控,这里所谓的map是一小块连续的内存空间,其中每一个元素(此时成为一个结点)都是一个指针,指向另一段连续的内存空间,称作缓冲区,缓冲区才是deque的存储空间的主体。

deque的迭代器:

deque的优点:

  • 相比于vector,deque可以进行头插和头删,且时间复杂度是O(1),扩容是也不需要大量挪动数据,因此效率是比vector高的。
  • 相比于list,deque底层是连续的空间,空间利用率高,,也支持随机访问,但没有vector那么高。
  • 总的来说,deque是一种同时具有vector和list两个容器的优点的容器,有一种替代二者的作用,但不是完全替代。

deque的缺点:

  • 不适合遍历,因为在遍历是,deque的迭代器要频繁地去检测是否运动到其某段小空间的边界,所以导致效率低下。
  • deque的随机访问的效率是比vector低很多的,实际中,线性结构大多数先考虑vector和list。

deque可以作为stack和queue底层默认容器的原因:

  1. stack和queue并不需要随机访问,也就是说没有触及到deque的缺点,只是对头和尾进行操作。
  2. 在stack增容时,deque的效率比vector高,queue增容时,deque效率不仅高,而且内存使用率也高。

stack和queue的模拟实现

template<class T, class Container = deque<T>>
class stack
{
public:void push(const T& x){_con.push_back(x);}void pop(){_con.pop_back();}T top(){return _con.back();}size_t size(){return _con.size();}bool empty(){return _con.empty();}
private:Container _con;
};template<class T, class Container = deque<T>>
class queue
{
public:void push(const T& x){_con.push_back(x);}void pop(){_con.pop_front();}T& front(){return _con.front();}T& back(){return _con.back();}size_t size(){return _con.size();}bool empty(){return _con.empty();}
private:Container _con;
};

priority_queue(优先级队列)

template <typename T, typename Container=std::vector<T>, typename Compare=std::less<T>> 
class priority_queue

priority_queue 实例默认有一个 vector 容器。函数对象类型 less 是一个默认的排序断言,定义在头文件 function 中,决定了容器中最大的元素会排在队列前面。fonction 中定义了 greater,用来作为模板的最后一个参数对元素排序,最小元素会排在队列前面。当然,如果指定模板的最后一个参数,就必须提供另外的两个模板类型参数。

总结几点

  • 优先级队列也是一种容器适配器,它的第一个元素总是最大的。
  • 类似于堆,且默认是大堆,在堆中可以插入元素,并且只能检索最大元素。
  • 底层容器可以任何标准容器类模板,也可以是其他特定容器类封装作为器底层容器类,需要支持push_back,pop_back,front和empty几个接口的操作。

priority_queue常用的接口

push(const T& obj);//将obj的副本放到容器的适当位置,这通常会包含一个排序操作。
push(T&& obj);//将obj放到容器的适当位置,这通常会包含一个排序操作。
emplace(T constructor a rgs...);//通过调用传入参数的构造函数,在序列的适当位置构造一个T对象。为了维持优先顺序,通常需要一个排序操作。
top();//返回优先级队列中第一个元素的引用。
pop();//移除第一个元素。
size();//返回队列中元素的个数。
empty();//如果队列为空的话,返回true。
swap(priority_queue<T>& other);//和参数的元素进行交换,所包含对象的类型必须相同。
void test_priority_queue()
{priority_queue<int, vector<int>> pq;pq.push(5);pq.push(7);pq.push(4);pq.push(2);pq.push(6);while (!pq.empty()){cout << pq.top() << " ";pq.pop();}cout << endl;
}

priority_queue的模拟实现

priority_queue的框架

其中模板中有三个参数,最后一个参数是仿函数,也就是指明优先级队列是按照升序还是降序来存数据的

template<class T, class Container = vector<T>, class Compare = less<T>>// 默认是小于
class priority_queue
{
public:
private:Container _con;Compare _com;
};

仿函数

仿函数(functor),就是使一个类的使用看上去像一个函数。其实现就是类中实现一个operator(),这个类就有了类似函数的行为,就是一个仿函数类了。

// 仿函数  就是一个类重载了一个(),operator(),可以像函数一样使用
template<class T>
struct greater
{bool operator()(const T& a, const T& b){return a > b;}
};
template<class T>
struct less
{bool operator()(const T& a, const T& b){return a < b;}
};

可以看出,仿函数就是用一个类封装一个成员函数operator(),使得这个类的对象可以像函数一样去调用。

实例演示:

template<class T>
struct IsEqual
{bool operator()(const T& a, const T& b){return a == b;}
};
void test()
{IsEqual<int> ie;cout << ie(2, 3) << endl;// 该类实例化出的对象可以具有函数行为
}

堆的向上调整和向下调整的实现

向上调整: 从最后一个数往上调整

void AdjustUp(int child)
{int parent = (child - 1) / 2;while (child > 0){if (_con[child] > _con[parent])//<  建小堆  > 建大堆{swap(_con[child], _con[parent]);child = parent;parent = (child - 1) / 2;}else{break;}}
}

向下调整: 从第一个往下调整

void AdjustDown(int parent)
{int child = parent * 2 + 1;while (child < (int)size()){			if (child + 1 < (int)size() && _con[child + 1] > _con[child]) {++child;}if (_con[child] >  _con[parent])// 建小堆{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 (_com(_con[parent], _con[child]))// _con[child] > _con[parent]{swap(_con[child], _con[parent]);child = parent;parent = (child - 1) / 2;}else{break;}}
}
void AdjustDown(int parent)
{int child = parent * 2 + 1;while (child < (int)size()){			if (child + 1 < (int)size() && _com(_con[child], _con[child + 1]))// _con[child + 1] > _con[child]{++child;}if (_com(_con[parent], _con[child]))// _con[child] >  _con[parent]{swap(_con[child], _con[parent]);parent = child;child = parent * 2 + 1;}else{break;}}
}

priority_queue的插入和删除

push 先在队尾插入数据,然后用向上调整算法使得堆是大堆或小堆

void push(const T& x)
{_con.push_back(x);AdjustUp((int)size() - 1);
}

pop 先将堆顶的元素和队尾的元素交换,再删去队尾元素(而不是直接删去堆顶元素,这样会破坏堆的结构,然后又要建堆),然后再使用向下调整算法使得堆是大堆或小堆

void pop()
{assert(!empty());swap(_con[0], _con[(int)size() - 1]);_con.pop_back();AdjustDown(0);
}

priority_queue的存取与大小

 

//top 返回堆顶元素 T& top() { assert(!empty()); return _con[0]; } //size 返回优先级队列元素个数 size_t size() { return _con.size(); } //empty 判断优先级队列是否为空 bool empty() { return size() == 0;

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

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

相关文章

精华推荐 | 【深入浅出RocketMQ原理及实战】「性能原理挖掘系列」透彻剖析贯穿RocketMQ的系统服务底层原理以及高性能存储设计挖掘深入

设计背景 消息中间件的本身定义来考虑&#xff0c;应该尽量减少对于外部第三方中间件的依赖。一般来说依赖的外部系统越多&#xff0c;也会使得本身的设计越复杂&#xff0c;采用文件系统作为消息存储的方式。 RocketMQ存储机制 消息中间件的存储一般都是利用磁盘&#xff0…

餐饮+KTV融合消费模式,会受消费者喜欢吗?

这个五一&#xff0c;我们雨科网门店系统的客户&#xff0c;大侠火锅店终于是将KTV搬到了自己的门店里&#xff0c;运用门店小程序功能及纸质代金券及礼品的噱头吸引客户进店&#xff0c;只需消费并和任意一人合唱一首歌即可领取&#xff0c;消费者在等餐或放松的时候一键点歌演…

OneAuth 2022.11.23版本更新内容

2022.11.23版本更新内容&#xff1a; 新增IdP飞书 云目录增加对Group的支持GWA浏览器插件适配性优化自定义授权服务器优化&#xff0c;适应RBAC、ABAC等多种场景授权IdP 北森优化&#xff0c;适配自定义的属性租户的部分试用功能需要联系后台开通其他一些Bug的修复 标题新增 …

PDF预览完整解决方案及各种兼容(VUE版)

PDF预览完整解决方案及各种兼容&#xff08;VUE版&#xff09; PDF预览完整解决方案及各种兼容&#xff08;VUE版&#xff09; - 掘金 前端学习使者正在上传…重新上传取消 2021年11月12日 16:57 阅读 2547 一、利用iframe 就一行代码就够了&#xff0c;只能满足最基本的…

ThinkPHP5目录结构

文章目录一、TP5的框架的下载1、[采用fastAdmin安装](https://www.fastadmin.net/download.html)2、Composer安装2.1 Composer提供的服务3、Git安装二、使用Composer安装后目录结构2.1 补充获取 Git 仓库git的工作机制一、TP5的框架的下载 1、采用fastAdmin安装 FastAdmin是一…

运营版uniapp多商户商城小程序+H5+APP+商家入驻短视频社区种草直播阶梯拼团

运营版uniapp多商户商城小程序H5APP商家入驻短视频社区种草直播阶梯拼团 前后端全套源码&#xff0c; 支持二次开发&#xff0c;代码无加密&#xff01; 独立商家后台 用于店铺商品管理订单管理发货管理等 多类经营模式 多商家B2B2C、自营B2C运营模式 私有化部署 前端Uni…

JVM类加载(类加载过程、双亲委派模型)

系列文章目录 JVM的内存区域划分_crazy_xieyi的博客-CSDN博客 文章目录 一、类加载过程二、关于类加载的典型试题三、双亲委派模型一、类加载过程 对于一个类来说&#xff0c;它的生命周期是这样的&#xff1a;1.加载 “加载”&#xff08;Loading&#xff09;阶段是整个“类加…

spring 如何解决循环依赖

什么是循环依赖 A 类中有一个属性 B &#xff0c;也就是说 A 依赖 B&#xff0c;同时 B 类中有一个属性 A, 也就是说 B 依赖 A. 他们之间的依赖关系形成了环。就是我们说的循环依赖&#xff0c;如下图&#xff1a; 循环依赖示例 public class CircularDependenciesDemo {publ…

SSM基于上述环境实现简单CUDA操作

目录 1. 结构 2. 环境&#xff1a; 3. controller 4. mapper 5. service 6. serviceImpl 7. mapper.xml 8. emplist.html 9. update 1. 结构 2. 环境&#xff1a; SSM整合 Spring SprintMVC Mybatishttps://blog.csdn.net/qq_41950447/article/details/128033971 3.…

Android -- 每日一问:Activity的启动模式(launchMode)有哪些,有什么区别?

经典回答 这应该是一道很虐人的面试题&#xff0c;很多人都答不上来&#xff0c;很多人根本就没有用过。当我发现在被我面试的人中有80%的比例对它不了解时&#xff0c;我找过一些同事讨论是否还有在面试中考查这个问题的必要&#xff0c;得到的回答是“程序员何苦为难程序员”…

2020-RKT

2020-RKT&#xff1a;Relation-Aware Self-Attention for Knowledge Tracing 有代码&#xff1a;https://github.com/shalini1194/RKT 摘要 学生在解决练习的过程中获得技能&#xff0c;每一次这样的互动都对学生解决未来练习的能力有明显的影响。 这种影响表现为:1)互动中涉…

电脑c盘满了怎么清理,快速清理,用这5招

​新买的电脑没用多久&#xff0c;突然发现系统提示磁盘空间不足。点击一看&#xff0c;电脑c盘空间已经爆满变红。当出现这种情况时&#xff0c;很多电脑的运行速度会大大降低&#xff0c;甚至导致部分应用无法正常运行。那么电脑c盘满了怎么清理&#xff1f;如何释放电脑c盘空…

C语言:关键字----switch、case、default(开关语句)

C语言&#xff1a;基础开发----目录 C语言&#xff1a;关键字—32个(分类说明) 有32个关键字详细说明&#xff0c;还有跳转链接&#xff01; 一、开关语句----介绍 开关语句&#xff0c;包括以下四种关键字&#xff1a; switch&#xff1a;开关语句case&#xff1a; 开关语句…

【vim】系统剪切板、vim寄存器之间的复制粘贴操作命令?系统剪切板中的内容复制粘贴到命令行?vim文本中复制粘贴到命令行

一、系统剪切板和文本内容的复制粘贴 1.1 从系统剪切板复制粘贴到文本中 需要操作3次&#xff1a; 分别是英文双引号、一个加号或梅花号&#xff0c;最后是一个p 也即"p 或者直接使用组合键【Shift insert】 1.2 从文本复制粘贴到系统剪切板 也需要操作3次&#xff…

java EE初阶 — 计算机工作原理

文章目录1.操作系统2.操作系统的定位3.进程3.1 进程的基本了解3.2 操作系统内核是如何管理软件资源的3.3 PCB里描述了进程的哪些特征3.3.1 三个较为简单的特征3.3.2 进程的调度属性4.内存管理1.操作系统 操作系统是一个搞管理的软件。 对上要给软件提供稳定的运行环境。对下要…

基于JAVA的鲜花店商城平台【数据库设计、源码、开题报告】

数据库脚本下载地址&#xff1a; https://download.csdn.net/download/itrjxxs_com/86427660 摘要 在互联网不断发展的时代之下&#xff0c;鲜花软件可以为鲜花企业带来更多的发展机会&#xff0c;让企业可以挖掘到更多的潜在用户&#xff0c;同时结合企业的优势就能够为用户…

Swin Transformer目标检测实验——环境配置的步骤和避坑

Swin Transformer1. 网上基础教程&#xff08;带视频讲解&#xff09;2. 配置虚拟环境时遇到的一些问题&#xff08;按操作顺序排列&#xff09;1. 网上基础教程&#xff08;带视频讲解&#xff09; 大家是不是都从b站来的呀&#xff0c;先给你们基础环境的配置和搭配的视频教…

黑马点评--Redis消息队列

Redis消息队列 Redis消息队列实现异步秒杀 消息队列&#xff08;Message Queue&#xff09;&#xff0c;字面意思就是存放消息的队列。最简单的消息队列模型包括3个角色&#xff1a; 消息队列&#xff1a;存储和管理消息&#xff0c;也被称为消息代理&#xff08;Message Br…

【附源码】计算机毕业设计JAVA疫情下的居民管理系统

【附源码】计算机毕业设计JAVA疫情下的居民管理系统 目运行 环境项配置&#xff1a; Jdk1.8 Tomcat8.5 Mysql HBuilderX&#xff08;Webstorm也行&#xff09; Eclispe&#xff08;IntelliJ IDEA,Eclispe,MyEclispe,Sts都支持&#xff09;。 项目技术&#xff1a; JAVA…

蒙泰转债上市价格预测

蒙泰转债基本信息转债名称&#xff1a;蒙泰转债&#xff0c;评级&#xff1a;A&#xff0c;发行规模&#xff1a;3.0亿元。正股名称&#xff1a;蒙泰高新&#xff0c;今日收盘价&#xff1a;31.3&#xff0c;转股价格&#xff1a;26.15。当前转股价值 转债面值 / 转股价格 * 正…