【C++初阶】stack的常见操作和模拟实现

news2024/11/26 9:44:40

在这里插入图片描述

👦个人主页:@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 用栈实现队列
  • 三、模拟实现stack
    • 3.1 简介
    • 3.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;
};

三、模拟实现stack

3.1 简介

在这里插入图片描述

stack是一种容器适配器,容器适配器可以被视为一种包装器,它们通过修改底层容器的接口或行为来实现新的功能。通过使用这些容器适配器,开发者可以方便地在不同场景下使用已有容器的功能,并且无需关心底层容器的具体实现。

其实就是STL中封装好的栈,在使用的时候我们不仅可以指定内部的数据类型,还可以指定内部的容器。不指定容器其实也是可以的,模板参数有一个缺省值,默认是deque

int main()
{
	//内部容器为vector
	stack<int, vector<int>> s1;  
	
	//内部容器为list   
	stack<int, list<int>> s2; 
	
	//内部为默认容器deque      
    stack<int> s3;      
                
	return 0;
}

3.2 代码实现

注意:指定内部的容器需要有push_backpop_backbacksizeempty等函数接口

#pragma once

namespace wj
{
	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;
	};
}

【测试代码】

#include <iostream>
#include <deque>
using namespace std;
#include "stack.h"
int main()
{
	wj::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;
	cout << "个数为:" << _st.size() << endl;
	return 0;
}

【输出结果】

在这里插入图片描述

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

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

相关文章

LNMT动静分离+keepalived

目录 前言 一、实验拓扑 二、配置tomcat 三、nfs配置 四、配置NGINX 五、配置NGINX的双机热备 六、验证双机热备 前言 LNMT动静分离是指在LNMT架构中使用动静分离技术&#xff0c;将动态请求和静态请求分开处理和分发&#xff0c;以提高性能和可扩展性。这种架构使用Nginx…

在GPU服务器(Linux)上安装Anaconda和PyTorch环境

安装Anaconda3 Anaconda官网&#xff1a;https://repo.anaconda.com/archive/ 根据自己需要&#xff0c;复制安装包名字&#xff0c;以Anaconda3-2023.07-2-Linux-x86_64.sh为例 命名规则&#xff1a;Anaconda3-<版本号>-Linux-x86_64.sh 在终端输入命令&#xff0c;下…

设备分类、设备号申请和注销

一、Linux内核对设备的分类 linux的文件种类&#xff1a; -&#xff1a;普通文件d&#xff1a;目录文件p&#xff1a;管道文件s&#xff1a;本地socket文件l&#xff1a;链接文件c&#xff1a;字符设备b&#xff1a;块设备 Linux内核按驱动程序实现模型框架的不同&#xff0…

JSX底层渲染机制

JSX底层渲染机制 一,.步骤 1.把我们写的jsx语法编译为虚拟DOM【virtualDOM】 虚拟DOM对象&#xff1a;框架自己内部构建的一套对象体系&#xff08;对象的相关成员都是React内部绑定的&#xff09;&#xff0c;基于这些属性描述出我们所构建视图中的DOM接的相关特征 1基于ba…

【crypto++使用】使用crypto++库函数运行RSA非对称加密

系列文章目录 1.&#xff08;全网最详细攻略&#xff09;【Crypto】在Visual studio2022中运行Cryptopp 文章目录 系列文章目录前言一、RSA加密过程、步骤可学习的网址 二、代码部分1.visual studio编程注意一个标准案例提供给大家 2.RSA密钥生成思考&#xff1a; 3.关于RSA的…

计算机视觉-卷积神经网络

目录 计算机视觉的发展历程 卷积神经网络 卷积&#xff08;Convolution&#xff09; 卷积计算 感受野&#xff08;Receptive Field&#xff09; 步幅&#xff08;stride&#xff09; 感受野&#xff08;Receptive Field&#xff09; 多输入通道、多输出通道和批量操作 …

死信队列理解与使用

一、简介 在rabbitMQ中常用的交换机有三种&#xff0c;直连交换机、广播交换机、主题交换机&#xff1b; 直连交换机中队列与交换机需要约定好routingKey去进行绑定&#xff1b; 广播交换机并不需要routingKey绑定,只需队列与交换机绑定即可&#xff1b; 主题交换机最大的特…

dml dql 约束 数据库设计

dml 1.添加数据 *语法 &#xff1a; *insert into 表名&#xff08;列名1&#xff0c;列名2&#xff0c;……..列名n&#xff09;values(值1&#xff0c;值2&#xff0c;…值n) *注意&#xff1a; 1.列名和值要一一对应 2.如果表名后&#xff0c;不写列名&#xff0c;就要给…

QT 获取程序编译时间并且转化格式

前言 有的时候我们要在程序的关于界面加上程序的编译时间等信息。可以通过如下代码实现 QString buildTime QStringLiteral("%1 %2").arg(__DATE__).arg(__TIME__);ui->label->setText(buildTime);QDateTime dateTime QLocale("en_US").toDateTim…

easyx图形库6:实现飞机大战:

飞机大战 一.飞机大战的基本窗体&#xff1a;二.飞机大战的主要战斗场景元素&#xff1a;一.透明图片&#xff1a;二.精灵对象&#xff1a; 三.主游戏场景的元素&#xff1a;1.英雄飞机的结构体定义&#xff1a;2.英雄飞机的代码实现&#xff1a;3.游戏背景的结构体定义&#x…

Day5:react函数组件与类组件

「目标」: 持续输出&#xff01;每日分享关于web前端常见知识、面试题、性能优化、新技术等方面的内容。 「主要面向群体&#xff1a;」前端开发工程师&#xff08;初、中、高级&#xff09;、应届、转行、培训、自学等同学 Day4-今日话题 react「函数组件和类组件」的区别&…

查局域网所有占用IP

查局域网所有占用IP 按&#xff1a;winr 出现下面界面&#xff0c;在文本框中输入 cmd 按确定即可出现cmd命令界面 在cmd命令窗口输入你想要ping的网段&#xff0c;下面192.168.20.%i即为你想要ping的网段&#xff0c;%i代表0-255 for /L %i IN (1,1,254) DO ping -w 1 -n 1…

(动态规划) 剑指 Offer 49. 丑数 ——【Leetcode每日一题】

❓剑指 Offer 49. 丑数 难度&#xff1a;中等 我们把只包含质因子 2、3 和 5 的数称作丑数&#xff08;Ugly Number&#xff09;。求按从小到大的顺序的第 n 个丑数。 示例: 输入: n 10 输出: 12 解释: 1, 2, 3, 4, 5, 6, 8, 9, 10, 12 是前 10 个丑数。 说明: 1 是丑数。…

2024年新iPad Pro将实现6年来最大的升级

彭博社的Mark Gurman长期以来一直将iPad Pro的下一次重大更新定在2024年&#xff0c;在最新一期的Power On时事通讯中&#xff0c;他详细阐述了一些细节&#xff0c;这些细节将使其成为“自2018年以来该产品的首次重大更新” 尽管Gurman将最近的iPad升级描述为“最近特别小”&…

word6 图文混排

目录 7-1 段落缩进排版7-2 搞定多级列表难题 7-1 段落缩进排版 段落对齐 缩进问题 悬挂缩进&#xff1a;缩进首行以外的段落 段落对齐&#xff1a; 7-2 搞定多级列表难题

k8s 安装 kubernetes安装教程 虚拟机安装k8s centos7安装k8s kuberadmin安装k8s k8s工具安装 k8s安装前配置参数

k8s采用master, node1, node2 。三台虚拟机安装的一主两从&#xff0c;机器已提前安装好docker。下面是机器配置&#xff0c;k8s安装过程&#xff0c;以及出现的问题与解决方法 虚拟机全部采用静态ip, master 30机器, node1 31机器, node2 32机器 机器ip 192.168.164.30 # ma…

【数据结构与算法篇】手撕八大排序算法之快排的非递归实现及递归版本优化(三路划分)

​&#x1f47b;内容专栏&#xff1a; 《数据结构与算法篇》 &#x1f428;本文概括&#xff1a; 利用数据结构栈(Stack)来模拟递归&#xff0c;实现快排的非递归版本&#xff1b;递归版本测试OJ题时&#xff0c;有大量重复元素样例不能通过&#xff0c;导致性能下降&#xff0…

Self-Supervised Learning

Self-Supervised Learning Bert 的数据是 340M parameters 抽象解释&#x1f446; Bert 单个字的预测 把一个字盖住&#xff1a; 1、把一个字替换成特殊字符(MASK)。 2、替换成随机的一个字,进行训练。 next sentence prediction 通过变换两个连起来的句子的顺序&#x…

C. Battle 2023 (ICPC) Jiangxi Provincial Contest -- Official Contest

Problem - C - Codeforces 题目大意&#xff1a;有n堆石子&#xff0c;给出一个数p&#xff0c;A先B后&#xff0c;每个人每次只能取p的幂个石子&#xff08;包括1&#xff09;问A能不能赢 1<n<3e5;1<p<1e18 思路&#xff1a;先递归算出sg函数看看&#xff0c;s…

detour编译问题及导入visual studio

Detours是经过微软认证的一个开源Hook库&#xff0c;Detours在GitHub上&#xff0c;网址为 https://github.com/Microsoft/Detours 注意版本不一样的话也是会出问题的&#xff0c;因为我之前是vs2022的所以之前的detours.lib不能使用&#xff0c;必须用对应版本的x64 Native To…