【C++】STL-stack_queue

目录

1、stack和queue的使用

1.1 最小栈

1.2 栈的弹出和压入序列

1.3 二叉树的层序遍历

2、stack和queue的模拟实现

2.1 适配器

2.2 deque

2.2.1 deque的成员变量

2.2.2 deque的迭代器

2.2.3 deque尾插元素

2.2.4 deque头插元素

2.2.5 下标访问

2.2.6 deque的不足


1、stack和queue的使用

stack的使用和queue的使用与前面的vector和list类似,并且可以通过看文档来了解,这里主要通过几道题来加深对这两个容器的理解

1.1 最小栈

这道题可以定义两个栈,一个用来存放放入的元素,一个用来储存最小值

注意:最小栈是相对当前位置而言的

不能用一个min来记录最小值,因为删除元素后min无法更新,且这道题的最小值是相对当前位置

class MinStack {
public:MinStack() {//不需要初始化,因为成员变量是自定义类型,会去调用自己的构造函数}void push(int val) {st.push(val);if(minst.empty() || minst.top() >= val)minst.push(val);}void pop() {int x = st.top();st.pop();if(x == minst.top())minst.pop();}int top() {return st.top();}int getMin() {return minst.top();}stack<int> st;stack<int> minst;
};

1.2 栈的弹出和压入序列

这道题是思路是,创建一个栈,首先将pushV中的第一个数据放入栈中,用popi来记录popV的下标,初始时popi=0,比较栈顶的数据和popV[popi]是否相同,若相同,则弹出栈顶数据,并且popi++,然后继续比较现在栈顶的数据是否与popV[popi]是否相同,直到不相同再出循环或者栈中已经没有元素了再出循环:若不相同,则继续将pushV中的数据往栈中插入。若已经把pushV中的数据全部放入栈中了,并且循环判断后栈为空,说明是可以的,否则就是不可以的

bool IsPopOrder(vector<int>& pushV, vector<int>& popV) {size_t popi = 0;stack<int> st;for(auto e : pushV){st.push(e);// 栈顶数据与出栈序列比较while(!st.empty() && st.top() == popV[popi]){popi++;st.pop();}}return st.empty();}

1.3 二叉树的层序遍历

与之前的层序遍历类似,都是利用队列,父亲结点出队列时就把左右孩子结点带入队列中。这道题的难处是要将每一层的结点放进一个数组中,然后所有层的结点组成一个二维数组,所以要如何区分队列中的结点是那一层的呢?

此时可以借助一个levelSize,levelSize表示每一层数据的个数,入队列还是父亲结点带入左右孩子结点,出队列时,需要用levelSize控制一层一层出,当levelSize==0时,说明当前层出完了,并且此时队列中的就都是下一层的结点,所以levelSize=q.size()

class Solution {
public:vector<vector<int>> levelOrder(TreeNode* root) {vector<vector<int>> vv;if(root == nullptr) return vv;queue<TreeNode*> q;q.push(root);int levelSize = 1;// 记录每层的数据个数int i = 0;while(!q.empty()){vector<int> v;while(levelSize){TreeNode* node = q.front();q.pop();levelSize--;v.push_back(node->val);if(node->left) q.push(node->left);if(node->right) q.push(node->right);}vv.push_back(v);levelSize = q.size();}return vv;}
};

2、stack和queue的模拟实现

vector和list称为容器,而stack和queue称为容器适配器

2.1 适配器

通过观察stack和queue、vector和list会发现,前两者的第二个模板参数和后两者的第二个模板参数不同。前两者的是适配器,后两者的是空间配置器。空间配置器是用来让容器开启空间的,而适配器是这个容器底层是通过什么实现的

适配器 -- 转换 -- 对其他容器封装一下

所以,stack的模拟实现底层可以使用vector或者list

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

模板参数和函数参数的区别是,模板参数用的是尖括号,函数参数用的是圆括号,模板参数传的是类型,函数参数传的是对象,所以模板参数也是可以给缺省值的

在上面这一个栈的模板中,底层默认是用vector实现的,也可以在创建的时候传入一个其他的容器来让底层变成其他容器,如list

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

适配器模式是一种设计模式,前面的vector、list是迭代器模式,同样也是一种设计模式

适配器通过一直接口来实现另一种接口,增强了代码的可维护性。当适配器不同时,实际上底层结构已经天差地别,但是使用起来完全是一样的,也具有很强的封装性

适配器选用vector和list各有优势和劣势

vector的优势是下标访问效率低

vector的劣势是扩容、头部插入删除效率低

list的优势是按需申请释放空间任意位置插入删除效率高

list的劣势是下标访问效率低

所以STL中的stack和queue的默认适配器是deque,是vector和list的结合体

2.2 deque

deque叫做双端队列,是一个容器,类似于vector和list的结合体,既可下标访问,又可头插头删

deque底层是通过一个中控数组,也就是一个指针数组来控制一个一个的buff数组

接下来,通过部分的STL源码来大概了解一下deque的底层结构

2.2.1 deque的成员变量

deque的成员函数主要就是由两个迭代器以及一个中控数组组成的

start指向的是deque中第一个buff

finish指向的是deque中最后一个buff

2.2.2 deque的迭代器

deque的迭代器是由4个成员变量组成的

node是指向这个迭代器指向的那个buff,因为buff是数组,node指向数组,所以是二级指针

first是指向这个迭代器的node指向的那个buff数组的第一个位置

last是指向这个迭代器的node指向的那个buff数组的最后一个位置的下一个位置

cur指向当前位置,在deque的成员变量start中就是第一个元素,在deque的成员变量finish中就是最后一个元素

这里面的map是T**

begin返回的是start,end返回的是finish

迭代器++是让迭代器中的cur向后走,如果cur == last,说明当前buff走完了,则让node向后移动一位

it != end 迭代器的比较是用cur来比较的

2.2.3 deque尾插元素

若最后一个buff数组没满,则在其后面插入数据,并让finish的cur向后移动

若最后一个buff数组满了,则再开一个buff数组,并且finish后移

2.2.4 deque头插元素

若第一个buff数组是满的,则头插元素会在第一个buff前面再开一个buff数组,并且start前移一位,并且这个buff数组是从后向前添加元素的

2.2.5 下标访问

以头插元素中的图为例,假设要访问下标为4的元素,易知一个buff数组能存放8个元素,第一个buff数组中有效元素个数是2,所以用8-2=6,再用6+4=10,实际需要从第一个buff数组的第一个元素开始算,直到下标为10的元素,即2

2.2.6 deque的不足

1、deque的下标访问效率不如vector

2、deque在中间插入效率不如list

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

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

相关文章

golang结合neo4j实现权限功能设计

neo4j 是非关系型数据库之图形数据库&#xff0c;这里不再赘述。 传统关系数据库基于rbac实现权限, user ---- role ------permission,加上中间表共5张表。 如果再添上部门的概念&#xff1a;用户属于部门&#xff0c;部门拥有 角色&#xff0c;则又多了一层&#xff1a; user-…

数据加密解密和哈希的解析

[S1301]数据的加解密 对提供的原始数据&#xff08;字符串或者二进制数组&#xff09;进行加密是数据保护框架体提供的基本功能&#xff0c;接下来我们利用一个简单的控制台程序来演示一下加解密如何实现。数据的加解密均由IDataProtector对象来完成&#xff0c;而该对象由IDa…

Elasticsearch:Runtime fields - 运行时字段(一)

运行时字段&#xff08;runtime fields&#xff09;是在查询时计算的字段。运行时字段使你能够&#xff1a; 向现有文档添加字段而无需重新索引数据开始处理数据而无需了解其结构在查询时覆盖索引字段返回的值定义用于特定用途的字段而无需修改底层架构 你可以像访问其他任何…

bash条件判断基础adsawq1`1nn

判断的作用 判断后续操作的提前条件是否满足如果满足执行一种命令不满足则执行另一种指令 条件测试类型&#xff1a; 整型测试字符测试文字测试 整数测试&#xff1a;比较两个整数谁大谁小&#xff0c;是否相等&#xff1b; 二元测试&#xff1a; num1 操作符 num2 -eq: 等于…

uniapp封装虚拟列表滚动组件

uniapp封装虚拟列表滚动组件 这里用到一个列表&#xff0c;然后数据可能有很多很多…&#xff0c;一次性全部渲染到dom上会卡顿&#xff0c;很废性能&#xff0c;于是用了这个虚拟列表就变丝滑很多很多。 组件mosoweInventedList 代码&#xff1a; <!-- 虚拟滚动列表组件&a…

代码随想录Day67(图论 part04)

110.字符串接龙 题目&#xff1a;110. 字符串接龙 (kamacoder.com) 思路&#xff1a;没有思路 答案 import java.util.*;public class Main {public static void main(String[] args) {Scanner scanner new Scanner(System.in);int n scanner.nextInt();String beginStr sc…

华为手机怎么打印文件?

关于华为手机打印的问题&#xff0c;如果您有打印机&#xff0c;并且已经成功和华为手机相连&#xff0c;在解决上就要容易很多。 具体操作如下&#xff1a; 选择文件 文件来源&#xff1a;华为手机上的文件可以来自多个应用&#xff0c;如图库、备忘录、文件管理等&#xf…

20240628模拟赛总结

cf好了 让我们开始 T1 Two Regular Polygons 判断能不能构造出题中要求的正多边形 关键是n%m0 Two Regular Polygons #include<bits/stdc.h> using namespace std; int t; int n,m; int main() {cin>>t;for(int i1;i<t;i){cin>>n>>m;if(n%m0)co…

MySQL——事务ACID原则、脏读、不可重复读、幻读

什么是事务 要么都成功&#xff0c;要么都失败 一一一一一一一 1. SQL执行&#xff1a;A给B转账 A 1000 ---->200 B 200 2. SQL执行&#xff1a;B收到A的钱 A 800 B 400 一一一一一一一 将一组SQL放在一个批次中去执行~ 事务原则&#xff1a;ACI…

学习笔记(linux高级编程)10

IPC 进程间通信 interprocess communicate 三大类&#xff1a; 1、古老的通信方式 无名管道 有名管道 信号 2、IPC对象通信 system v BSD suse fedora kernel.org 消息队列(用的相对少&#xff0c;这里不讨论) 共享内存 信号量集 3、socket通信 网络通信 特…

TF/IDF算法

第1关&#xff1a;去除停用词 任务描述 本关任务&#xff1a;根据本关所学有关停用词的知识&#xff0c;编写使用停用词表去除停用词的程序并通过测试用例。 相关知识 为了完成本关任务&#xff0c;你需要掌握&#xff1a; 停用词的意义&#xff1b; 去除停用词的步骤。 …

浅谈Web性能测试(原创)

一、性能测试不是什么高技术的活&#xff1a; 说到性能测试&#xff0c;很多工作时间较短的新同事或者应届生就很害怕。 为什么害怕&#xff0c;因为感觉无从下手&#xff0c;不知道该做什么、怎么做、做到什么程度&#xff1f; 一听性能测试首先想到的是各种专业的性能测试…

ThingsKit物联网平台功能解析

随着物联网技术的飞速发展&#xff0c;各种物联网平台应运而生&#xff0c;为设备管理和数据集成提供了强大的支持。ThingsKit物联网平台以其全面的功能和灵活的配置&#xff0c;成为行业中的一大亮点。本文将详细解析ThingsKit物联网平台的功能清单&#xff0c;带您深入了解该…

oracle数据库默认表空间详解

文章目录 oracle数据库默认表空间列表 oracle数据库默认表空间列表 系统表空间&#xff08;System Tablespace&#xff09; 系统表空间包含了系统级别的元数据&#xff0c;如数据字典、系统表和存储过程等。例如SYSTEM表空间用于保存数据库的数据字典、PL/SQL程序的源代码和解释…

【C语言】分支(选择)和循环语句

目录 简述选择语句简述if语句单if结构语法格式 if-else结构语法结构 语法结构 循环结构break和continuewhile循环语法结构 for循环语法结构 do while循环语法结构 简述 在c语言中分支和循环语句是极其重要的&#xff0c;就像生活中你难免要做一些判断和循环往复做一些事。 选…

SpringBoot 中的参数校验:构建健壮应用的基石

前言 在开发Web应用时&#xff0c;处理用户输入是不可避免的一环。然而&#xff0c;用户输入往往充满不确定性&#xff0c;可能是格式不正确、类型不匹配&#xff0c;甚至包含恶意内容。为了确保应用的稳定性和安全性&#xff0c;对输入参数进行有效校验显得尤为重要。Spring …

【触想智能】工业平板电脑在新能源领域上的应用分析

工业平板电脑是一种具有高性能和稳定性的计算机设备&#xff0c;适用于在恶劣环境下进行数据采集、运营管理和现场操作。 随着新能源技术的快速发展&#xff0c;工业平板电脑不断地得到应用&#xff0c;并且已成为新能源领域中的重要工具之一。本文将从四个方面探讨工业平板电脑…

WSO2 products 文件上传漏洞(CVE-2022-29464)

前言 CVE-2022-29464 是一个影响多个 WSO2 产品的严重远程代码执行&#xff08;RCE&#xff09;漏洞。这些产品包括 WSO2 API Manager、WSO2 Identity Server 和 WSO2 Enterprise Integrator 等。由于用户输入验证不当&#xff0c;该漏洞允许未经身份验证的攻击者在服务器上上…

代码随想录算法训练营第九天|151.翻转字符串里的单词、右旋字符串、28. 实现 strStr()、459.重复的子字符串

打卡Day9 1.151.翻转字符串里的单词2.右旋字符串3.28. 实现 strStr()4.459.重复的子字符串 1.151.翻转字符串里的单词 题目链接&#xff1a;翻转字符串里的单词 文档讲解&#xff1a; 代码随想录 思路&#xff1a;首先&#xff0c;移除多余的空格&#xff1b;然后&#xff0c…