【C++初阶】stack和queue的常见使用操作

news2024/11/27 16:39:42

在这里插入图片描述

👦个人主页:@Weraphael
✍🏻作者简介:目前学习C++和算法
✈️专栏:C++航路
🐋 希望大家多多支持,咱一起进步!😁
如果文章对你有帮助的话
欢迎 评论💬 点赞👍🏻 收藏 📂 加关注✨


目录

  • 一、stack
    • 1.1 stack的基本概念
    • 1.2 stack的常见操作
      • 1.2.1 常见构造函数
      • 1.2.2 push
      • 1.2.3 pop
      • 1.2.4 empty
      • 1.2.5 top
      • 1.2.6 size
      • 1.2.7 栈的遍历
  • 二、有关栈的力扣经典题
    • 2.1 最小栈
    • 2.2 栈的压入、弹出序列
    • 2.3 逆波兰表达式求值
    • 2.4 用栈实现队列
  • 三、queue
    • 3.1 queue的基本概念
    • 3.2 queue的常见操作
      • 3.2.1 构造函数
      • 3.2.2 empty
      • 3.2.3 size
      • 3.2.4 front
      • 3.2.5 back
      • 3.2.6 push
      • 3.2.7 pop
      • 3.2.8 赋值操作
  • 四、有关队列的力扣经典题
    • 4.1 二叉树的层序遍历
    • 4.2 用队列实现栈

一、stack

1.1 stack的基本概念

在这里插入图片描述

  • stack是一种容器适配器(通过容器转化出来的),是一种先进后出(First in Last Out,简称FILO),它只有一个出口。
  • 容器适配器是一种特殊的容器,它们通过某种方式改变了底层容器的接口或行为。常见的容器适配器还有队列queue和优先队列priority_queue
  • 注意:容器适配器通常会限制对底层容器的访问方式,只有栈顶的元素才能被使用,因此不能有遍历的行为(底层没有设计迭代器)。例如栈和队列都是限制在一端插入或删除元素,优先队列则通过堆来维护元素的有序性。

在这里插入图片描述

1.2 stack的常见操作

在这里插入图片描述

1.2.1 常见构造函数

  • 无参的默认构造(构造空的栈)
// T可以是任意类型
stack<T> _st;
  • 拷贝构造
// _st已知
stack<T> _st(s);

1.2.2 push

功能:将元素val压入stack

1.2.3 pop

功能:stack中尾部的元素弹出

1.2.4 empty

功能:判断stack是否为空,如果为空则返回真,反之。

1.2.5 top

功能:返回栈顶元素

1.2.6 size

功能:返回stack中元素的个数

在这里插入图片描述

1.2.7 栈的遍历

既然栈不支持迭代器,只能打印栈顶的元素,然后出栈。重复以上操作直到栈为空

【代码示例】

#include <iostream>
#include <stack>
using namespace std;

int main()
{
    stack<int> _st;
    _st.push(1);
    _st.push(2);
    _st.push(3);
    _st.push(4);

    while (!_st.empty())
    {
        cout << _st.top() << ' ';
        _st.pop();
    }
    cout << endl;

    return 0;
}

【输出结果】

在这里插入图片描述

二、有关栈的力扣经典题

2.1 最小栈

题目链接:点击跳转

【题目描述】

在这里插入图片描述

【思路】

可以定义两个栈,一个栈_st可以用于出栈和入栈操作,另一个栈_min_st用于更新当前_st出栈和入栈的最小值。

对于入栈接口:_st正常入栈。如果_min_st为空,则入栈的值val_st一样;如果不为空,则要比较_min_st当前栈顶的元素是否大于或者等于_st的栈顶元素,如果大于或等于则要入栈。

对于出栈接口:首先要分析_st的栈顶元素是否等于_min_st的栈顶元素,如果相等则要出栈,而_st无论如何都要出栈。

最后,_min_st的栈顶元素则是最小元素的栈。

在这里插入图片描述

【代码实现】

class MinStack {
public:
    MinStack() 
    {}
    // 自定义类型会调用默认构造函数
    // 因此可以不用写
    
    void push(int val) 
    {
        _st.push(val);
        if (min_st.empty() || val <= min_st.top())
        {
            min_st.push(val);
        }
    }
    
    void pop() 
    {
        if (_st.top() == min_st.top())
        {
            min_st.pop();
        }
        _st.pop();
    }
    
    int top() 
    {
        return _st.top();
    }
    
    int getMin() 
    {
        return min_st.top();
    }

private:
    stack<int> _st; 
    stack<int> min_st;
};

2.2 栈的压入、弹出序列

题目链接:点击跳转

【题目描述】

在这里插入图片描述

【思路】

这题直接模拟就行了。

首先定义一个栈_st,并且分别定义变量ij来遍历pushV数组和popV数组,接下来让pushV里的元素一个一个入栈(i++),然后再判定栈顶元素是否等于popV下标为j的元素,如果相等则要出栈。最后如果栈为空,说明栈popV是是pushV弹出的顺序。

要注意pushV可能为空

【代码实现】

class Solution {
public:
    bool IsPopOrder(vector<int>& pushV, vector<int>& popV) 
    {
        stack<int> _st;
        int i = 0; // 遍历pushV
        int j = 0; // 遍历popV
        while (i < pushV.size())
        {
            // 入栈
            _st.push(pushV[i]);
            i++;

            while (!_st.empty() && _st.top() == popV[j])
            {
                _st.pop();
                j++;
            }
        }
        // 如果栈为空,说明匹配
        return _st.empty();
    }
};

2.3 逆波兰表达式求值

题目链接:点击跳转

【题目描述】

在这里插入图片描述

【思路】

首先来解释什么是逆波兰表达式求值,逆波兰表达式求值又称后缀表达式,而我们常见的是中缀表达式,例如2 + 1 * 3化成后缀表达式2 1 3 * +

因此我们的思路是:
设计一个栈_st,如果遇到操作数,则将操作数入栈;如果遇到运算符(本题的操作符只有+ - * /),则将两个操作数出栈,但是要注意操作数的顺序,先出栈的是右操作数,出栈后的下一个栈顶元素则是左操作数,对于加法和乘法来说操作数的顺序是无关紧要的,但是对于减法和除法,操作数就要有讲究了。

最后计算出的值继续入栈,直到遍历完毕之后,栈内只有一个元素,则该元素(也就是栈顶)为逆波兰表达式的值。

注意要将string类字符串转化成整型计算,string转化成整型有个函数:atoi

【代码实现】

class Solution {
public:
    int evalRPN(vector<string>& tokens) 
    {
        stack<int> _st;
       
        for (auto& x : tokens)
        {
            if (x != "+" && x != "-" && x != "*" && x != "/")
            {
            	// 如果不为操作符就入栈
                _st.push(stoi(x));
            }
            else
            {
                int right = _st.top();
                _st.pop();
                int left = _st.top();
                _st.pop();
				
				// 计算
                switch(x[0])
                {
                case '+':
                    _st.push(left + right);
                    break;
                case '-':
                    _st.push(left - right);
                    break;
                case '*':
                    _st.push(left * right);
                    break;
                case '/':
                    _st.push(left / right);
                    break;
                }
            }
        }
        return _st.top();
    }
};

2.4 用栈实现队列

题目链接:点击跳转

【题目描述】

在这里插入图片描述

【思路】

举一组数据:1、2、3、4。如果是出栈的话,第一个出的数据是4,而现在要用栈来模拟队列,第一个出的数据必须是1。所以一开先将4个数据全部入栈(push),然后一个个出栈到另一个栈(pop)中,这样1就在栈顶了,对于栈的性质,靠近栈顶的元素先出,这样就能实现栈模拟队列了。

【动图展示】

在这里插入图片描述

【代码实现】

class MyQueue {
public:
    MyQueue() {}
    
    void push(int x) 
    {
        _st.push(x);
    }
    
    int pop() 
    {
        if (_queue.empty())
        {
            while (!_st.empty())
            {
                int val = _st.top();
                _st.pop();
                _queue.push(val);
            }
        }
        int front_val = _queue.top();
        _queue.pop();
        return front_val;
    }
    
    int peek() 
    {
        if (_queue.empty())
        {
            while (!_st.empty())
            {
                int val = _st.top();
                _st.pop();
                _queue.push(val);
            }
        }
        return _queue.top();
    }
    
    bool empty() 
    {
        return _queue.empty() && _st.empty();
    }
    
private:
    stack<int> _st;
    stack<int> _queue;
};

三、queue

3.1 queue的基本概念

  • queue是一种容器适配器,也是一种先进先出(First in First Out,简称FIFO)的数据结构, 其中从容器一端插入元素,另一端提取元素
  • 容器适配器通常会限制对底层容器的访问方式,因此不能遍历,但队列中只有

在这里插入图片描述

3.2 queue的常见操作

3.2.1 构造函数

  • 默认构造
// T可以是任意类型
queue<T> q;
  • 拷贝构造
//q已知
queue<T> qq(q);

3.2.2 empty

功能:检测队列是否为空,是返回true,否则返回false

3.2.3 size

功能:返回队列中有效元素的个数

3.2.4 front

功能:返回队头元素

3.2.5 back

功能:返回队尾元素

3.2.6 push

功能:在队尾将元素val入队列

3.2.7 pop

功能:将队头元素出队列

3.2.8 赋值操作

#include <iostream>
#include <queue>
using namespace std;

int main()
{
	queue<int> q;
	// 插入
	q.push(10);
	q.push(20);
	q.push(30);
	q.push(40);


	queue<int> qq;
	//赋值运算符
	qq = q;

	cout << "元素个数:" << qq.size() << endl;
	cout << "队头元素" << qq.front() << endl;
	cout << "队尾元素" << qq.back() << endl;

	// 遍历
	while (!qq.empty())
	{
		cout << qq.front() << ' ';
		qq.pop();
	}
	cout << endl;
	return 0;
}

【输出结果】

在这里插入图片描述

四、有关队列的力扣经典题

4.1 二叉树的层序遍历

链接:点击跳转

【题目描述】

在这里插入图片描述

【思路】

在这里插入图片描述

【代码实现】

class Solution {
public:
    vector<vector<int>> levelOrder(TreeNode* root) 
    {
        queue<TreeNode*>q;
        vector<vector<int>> vv;
        int levelSize;

        // 如果根节点不为空,则入队列
        if (root)
        {
            q.push(root);
            // 并且根节点的root一定为1
            levelSize = 1;
        }

        while (!q.empty())
        {
            // 一层一层出
            vector<int> v;
            for (int i = 0;i < levelSize;i++)
            {
                // 记录当前节点
                TreeNode* front = q.front();
                // 删除节点并存入
                q.pop();
                v.push_back(front->val);
                // 并带入它的子节点
                if (front->left) q.push(front->left);
                if (front->right) q.push(front->right);
            }
            vv.push_back(v);
            // 一层出完更新一层的个数
            levelSize = q.size();
        }
        return vv;
    }
};

4.2 用队列实现栈

链接:点击跳转

【题目描述】

在这里插入图片描述

【思路】

队列的特点是先进先出,而栈是先进后出,首先定义两个队列

在这里插入图片描述

那如何模拟一个栈呢?首先往空的队列入数据

在这里插入图片描述

对于栈来说,先出的是4。因此我们可以把1 2 3移到另一个空队列中

在这里插入图片描述

【代码实现】

class MyStack {
public:
    MyStack() {}
    
    void push(int x) 
    {
    	// 往不是空的队列插入数据
        if (in.empty())
        {
            out.push(x);
        }
        else
            in.push(x);
    }
    
    int pop() 
    {
    	// 保持一个队列为空
    	// 将一个为空的队列的前n-1个移到空队列
    	// 剩下的那个这是栈顶元素
        if (in.empty())
        {
            while (out.size() > 1)
            {
                int front = out.front();
                out.pop();
                in.push(front);
            }
            int ans = out.front();
            out.pop();
            return ans;
        }
        else // out为空
        {
            while (in.size() > 1)
            {
                int front = in.front();
                in.pop();
                out.push(front);
            }
            int ans = in.front();
            in.pop();
            return ans;
        }
    }
    
    int top() 
    {
        if (in.empty())
        {
           return out.back();
        }
        else 
        {
            return in.back();
        }
    }
    
    bool empty()
    {
        return in.empty() && out.empty();
    }
private:
    queue<int> in;
    queue<int> out;
};

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

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

相关文章

Unity实现倒计时和获取系统时间

一:创建UGUI 1.创建Canvas画布组件,调节Canvas画布的分辨率等其他设置。我们可以把视图设置为2D模式下。 2.创建Text文本组件,取名为Timer计时器,我们调整Text文本组件的大小,用锚点设置Text文本组件的位置,并且设置好Text文本组件的颜色。 3.我们再创建一个Text文…

第三方系统访问微搭低代码的后端API

微搭低代码使用的是文档型数据库&#xff0c;有时候会有数据集成的需求&#xff0c;将低代码的数据库中的数据抽取到第三方系统中。本篇就介绍一下本地抽取数据以及云函数中抽取数据 1 本地抽取数据 本地抽取数据我们以nodejs作为后端服务&#xff0c;本机要求先安装好nodejs…

自然语言处理实战项目16- 基于CPU的大语言模型的实战训练全流程指导,模型调优与评估

大家好,我是微学AI,今天给大家介绍一下自然语言处理实战项目16- 基于CPU的生成式大语言模型的实战训练全流程详细讲解,模型调优与评估。该流程涵盖了数据准备、数据预处理、词表构建、模型选择与配置、模型训练、模型调优和模型评估等步骤。通过不断迭代和优化,可以提高模型…

客户端读写HBase数据库的运行原理

1.HBase的特点 HBase是一个数据库&#xff0c;与RDMS相比&#xff0c;有以下特点&#xff1a; ① 它不支持SQL ② 不支持事务 ③ 没有表关系&#xff0c;不支持JOIN ④ 有列族&#xff0c;列族下可以有上百个列 ⑤ 单元格&#xff0c;即列值&#xff0c;可以存储多个版本的值&…

海康威视相机-LINUX SDK 开发

硬件与环境 相机&#xff1a; MV-CS020-10GC 系统&#xff1a;UBUNTU 22.04 语言&#xff1a;C 工具&#xff1a;cmake 海康官网下载SDK 运行下面的命令进行安装 sudo dpkg -i MVSXXX.deb安装完成后从在/opt/MVS 路径下就有了相关的库&#xff0c;实际上我们开发的时候只需要…

3d Max因卡顿未保存?有什么保护文件和恢复操作呢?

大家在使用3d Max进行建模、渲染和动画制作的过程中&#xff0c;由于各种原因导致软件卡顿或崩溃是很常见的情况。 当卡顿发生时&#xff0c;如果之前的工作没有及时保存&#xff0c;可能会导致数据的丢失和时间的浪费。 一、先来看看保护文件 1、自动保存设置 3d Max提供了自…

一文快速读懂数据安全平台的优势与价值,让数据安全化繁为简

在大数据时代&#xff0c;数据已经成为公司的核心竞争力。《数字中国建设整体布局规划》为数字中国建设提出了“2522”整体框架布局&#xff0c;其中明确将“数字安全屏障”作为战略实施的两大关键能力之一&#xff0c;表明了数据安全是数字经济背后的重要工作。 广泛的数字化转…

python数组基本使用

使用Numpy进行数组运算 相比 List&#xff0c;NumPy 数组的优势 NumPy 全称为 Numerical Python&#xff0c;是 Python 的一个以矩阵为主的用于科学计算的基础软件包。NumPy 和 Pandas、Matpotlib 经常结合一起使用&#xff0c;所以被人们合称为数据分析三剑客。Numpy 中有功能…

网卡挂载与连接wifi

Viobot设备本身不具备无线功能&#xff0c;我们其实更推荐使用有线连接的方式使用&#xff0c;这样会更稳定&#xff0c;但如果确实想要使用无线测试的话&#xff0c;我们提供了无线网卡的驱动和安装方式。 无线网卡驱动属于外接的驱动&#xff0c;需要编译系统对应的驱动文件…

win10电脑记事本在哪里?电脑记事本如何查看字数?

在日常工作中&#xff0c;我们会遇到许多需要记录的信息和事项&#xff0c;而使用电脑记事本工具可以帮助我们方便地保存、管理这些内容。无论是记录工作会议的要点、制定工作计划&#xff0c;还是记录灵感和创意&#xff0c;电脑记事本都是非常实用的工具。 那么win10电脑记事…

nacos服务器启动报错集合

报错1 Error creating bean with name ‘user‘: Unsatisfied dependency expressed through field ‘jwtTokenManage 开启鉴权之后&#xff0c;你可以自定义用于生成JWT令牌的密钥&#xff0c;application.properties中的配置信息为&#xff1a; ### Since 1.4.1, worked when…

银联iso8583协议报文解析

最近在研究银联的ISO8583协议&#xff0c;涉及到报文这方面的东西&#xff0c;感觉挺多的&#xff0c;分享一下&#xff0c;或许对你有帮助。 ISO8583协议解决的核心问题&#xff1a; 明确了报文每个字段的数据类型&#xff0c;是数字还是字符&#xff0c;都能定义清楚 支持64…

ARMS 助力极氪提效服务应急响应,为安全出行保驾护航

作者&#xff1a;比扬 01 客户介绍与项目背景 浙江极氪智能科技有限公司于 2021 年 3 月成立&#xff0c;2021 年 4 月发布极氪品牌及旗下首款产品——极氪 001。极氪是一家以智能化、数字化、数据驱动的智能出行科技公司&#xff0c;秉承用户型企业理念&#xff0c;聚焦智能…

DNS指向别名还是IP

现在有一台服务器dbprod126&#xff0c;ip是172.22.100.4 现在有一个需求&#xff0c;需要在dns中对dbprod126建一个别名wondadb3r的记录&#xff0c;也就是ping wondadb3r的时候显示的是dbprod126的ip&#xff0c;目前有两​种方法&#xff0c;主要使用方法1指向别名&#xf…

matplotlib基础--2

5 图例 matplotlib中的图例是帮助观察者理解图像数据的重要工具。图列通常包含在图像中&#xff0c;用于解释不同的颜色、形状、标签和其它元素。 1&#xff09;主要参数 当不设置图例的参数时&#xff0c;默认的图例是这样的。 x np.linspace(0,1,50) y1 np.sin(x*2*np.p…

【unity插件】使用BehaviorDesigner插件制作BOSS的AI行为树

文章目录 前言素材插件一、基础使用二、敌人物理攻击三、敌人面向玩家四、敌人法术攻击五、随机进行攻击六、敌人不同的阶段推荐学习视频源码完结 前言 Behavior Designer是一个行为树插件&#xff0c;是一款为了让策划&#xff0c;程序员&#xff0c;美术人员方便使用的可视化…

基于SSM技客户管理系统源码和论文

基于SSM技客户管理系统源码和论文079 开发工具&#xff1a;idea 数据库mysql5.7 数据库链接工具&#xff1a;navcat,小海豚等 技术&#xff1a;ssm 一、课题的背景和意义 1、课题目的 客户管理是每个企业中最重要的模块&#xff0c;对客户的分类管理有利于更有效地了解从…

RHCE——九、SELinux

SELinux 一、概念1、作用2、SELinux与传统的权限区别 二、SELinux工作原理1、名词解释主体&#xff08;Subject&#xff09;目标&#xff08;Object&#xff09;策略&#xff08;Policy&#xff09;安全上下文&#xff08;Security Context&#xff09; 2、文件安全上下文查看1…

java入门第三节

java入门第三节 一.什么是oop 1.pop与oop (1).面向过程编程&#xff1a;&#xff08;POP&#xff1a;Procedure Oriented Programming&#xff09; 1.步骤清晰简单&#xff0c;第一步做什么&#xff0c;第二步做什么&#xff0c;按照顺序&#xff1b; 2.代码线性&#xff0…

什么是 TEE

参考文献&#xff1a; Sabt M, Achemlal M, Bouabdallah A. Trusted execution environment: what it is, and what it is not[C]//2015 IEEE Trustcom/BigDataSE/Ispa. IEEE, 2015, 1: 57-64. “U.S. government protection profifile for separation kernels in environment…