STL中的栈——stack

2023-11-15

stack为STL中的适配器容器,具有栈的结构特性。对于适配器容器,默认底层容器为deque,在创建stack对象时,也可以指定其他线性容器作为其底层容器。

基本操作:

#include<iostream>
#include<stack> //头文件
#include<vector>
#include<list>
using namespace std;
typedef int datatype;
constexpr auto N = 10;

int main()
{
	stack<datatype>stk;//创建stack对象,底层容器为deque,栈中元素类型为datatype
	stack < datatype, vector<datatype>>stk1;//创建stack对象,底层容器为vector
	stack<datatype, list<datatype>>stk2;//创建stack对象,底层容器为list

	//操作
	//入栈
	stk.push(3);
	stk.push(5);
	stk.push(2);
	//栈中元素个数
	cout << stk.size() << endl;
	
	while (!stk.empty()) { //判断不为空
		cout << stk.top() << endl; //获取栈顶元素
		stk.pop(); //出栈
	}
}

栈应用举例:

 栈在计算机科学中具有广泛的应用。一个典型的应用是在编译系统中,当调用一个函数时,将函数的参数、地址等相关信息入栈,当函数执行完毕后再出栈。这里采用栈结构来存储函数信息的主要原因是当函数嵌套调用时,根据函数调用先后次序一次入展,当最底层的函数执行完毕后出栈,再调用当前栈顶的函数......直到所有函数都执行完毕。

1.括号匹配

【算法】检查字符串中的括号是否合法

功能:检查字符串stk中的括号是否合法,假设只检查字符串中的四类括号:(,),[,] 。

算法:遍历的时候进行检查,左符号入栈,并记录栈顶元素,当某一次循环时,发现字符可与栈顶元素匹配时(采用排除法的方式发现字符可匹配),将栈顶元素pop,直到循环到最后一个字符。若栈为空,合法;若栈非空,不合法。

#include<iostream>
#include<stack> //头文件
#include<vector>
#include<list>
using namespace std;
typedef int datatype;
constexpr auto N = 10;

bool check_brackets(string str) {
	int i=0, sz = str.size();
	stack<char>stk;
	//遍历的时候进行匹配
	for (i = 0; i < sz; i++) {
		if (str[i] == '(' || str[i] == '[') //左括号入栈
			stk.push(str[i]);
		else {
			if (str[i] != ')' && str[i] != ']') //跳过非括号字符
				continue; 
			if (stk.empty()) //栈为空,不合法
				return false;

			char ch = stk.top(); //获取栈顶元素

			if (str[i] == ')' && ch != '(' || str[i] == ']' && ch != '[') //栈顶元素与当前括号不匹配,不合法
				return false;

			stk.pop(); //出栈
		}
	}
	if (!stk.empty()) return false; //栈非空,不合法
	return true;
}

int main()
{
	string s1="((56565))899(56)";
	bool islegitimate =check_brackets(s1);
	if (islegitimate)
		cout << "合法" << endl;
	else
		cout << "不合法" << endl;
}

2.算术表达式求值

在算术表达式(假设运算符只有加减乘除)中,由于运算符的优先级不同,再加上括号可以改变运算次序,导致求带括号的算术表达式的值比较复杂。下面用双栈解决该问题。

功能:求带括号的四则混合运算式exp的计算结果。假设操作数都为整数,且括号只有两种:“(”和“)”,并假设算术表达式中的运算符和括号合法。

自己画出入栈出栈的顺序!

#include<iostream>
#include<stack> //头文件
using namespace std;
typedef int datatype;
constexpr auto N = 10;

//处理ops(运算数栈)栈顶op的运算结果:
//从栈opers(操作数栈)中取两个数v1,v,就是那个v op v1的结果并返回
double cal(stack<double>& opers, stack<char>& ops) {
	double v=0, v1=0, ret=0;
	v1 = opers.top(), opers.pop();//右操作数
	v = opers.top(), opers.pop();//左操作数
	char op = ops.top(); ops.pop();//运算符
	switch (op){
		case '+':
			ret = v + v1; break;
		case '-':
			ret = v - v1; break;
		case '*':
			ret = v * v1; break;
		case '/':
			if (v1 == 0) exit(0);
			ret = v / v1;
			break;
	default:
		cout << "未知符号!" << endl;
		break;
	}
	opers.push(ret); //计算结果入栈
}

double calculate(string exp) {
	stack<double>opers; //操作数栈
	stack<char>ops; //运算符栈
	int i=0, sz = exp.size(), v = 0;
	for (i = 0; i < sz; i++) {
		if (isdigit(exp[i])) //exp[i]为数字,将其后连续数字组装为一个整数
		{
			v = exp[i] - '0';
			while (++i < sz && isdigit(exp[i])) //将两位及以上的数字表达出来
				v = v * 10 + exp[i] - '0';
			opers.push(v); //将组装的整数入栈
			--i;
		}
		else if (exp[i] == '(')//exp[i]为左括号,直接加入ops
			ops.push(exp[i]); 
		else if (exp[i] == '*' || exp[i] == '/') //exp[i]为乘除,消除ops栈顶的乘除
		{
			while (!ops.empty() && (ops.top() == '*' || ops.top() == '/')) //连续两个乘除,先进行前一个的计算
				cal(opers, ops);
			ops.push(exp[i]);
		}
		else if (exp[i] == '+' || exp[i] == '-' || exp[i] == ')')//exp[i]为加减或右括号,消除加减乘除
		{
			while (!ops.empty() && ops.top() != '(') //栈顶若为( ,则无法进行计算,其他符号才能
				cal(opers, ops);
			if (exp[i] == ')') //当为)时,中间的运算符都已经pop出去了
				ops.pop();
			else
				ops.push(exp[i]);
		}
	}
	while (!ops.empty())
		cal(opers, ops);
	return opers.top();
}

int main()
{
	string s1 = "7-((1+2)*4/5-6)";
	cout<<calculate(s1);
}

单调栈:

如果栈中的元素适中严格单调,则称这种有特殊类型的栈为单调栈。从栈顶到栈底单调递增的单调栈为递增栈,反之递减栈。

单调栈对栈的入栈和出栈操作加了一些限制条件,以维护栈的单调性。假设所考虑的数据序列为数组a,在将a中的每一个元素加入单调栈(以递减栈为例)时,依次考虑a的每一个元素a[i],并只执行如下两种类型的操作:
        (1)如果栈空或a[i]大于栈顶元素,则a[i]直接入栈。
        (2)如果a[i]小于栈顶元素,则出栈,直到a[i]大于栈顶元素或栈空。然后将a[i]入栈。


限定栈只能执行这两类操作能够确保栈中元素递减。


使用单调栈可以处理如下问题:
          (1)利用递减栈可以求a[i]左端比a[i]小且离a[i]最近的元素(简称左端第一个比a[i]小的元素);利用递增栈可以求a[i]左端第一个比a[i]大的元素。
        (2)利用递减栈可以求 a[i]左端与a[i]相邻且连续比a[i]大的元素个数(简称a[i]左
邻比a[i]大的元素个数);利用递增栈可以求a[i]左邻比a[i]小的元素个数。

【例2-2】给定一个整型数组a[ ]={5,6,2,4,9,7,3},求解如下两个问题:      

        (1)求a的每一个元素a[i]左端比它小的数中离它最近的数,并输出,如果a[i]左端没有比它小的数,则输出-1。对于上述数组a,结果为{-1,5,-1,2,4,4,2}。

        (2)求a的每一个元素a[i]左端比它大的数中与其相邻且连续的数的个数,并输出,如果a[i]的为最左元素或a[i-1]<a[i],则输出0。对于上述数组a,结果为:{0,0,2,0,0,1,3}。

#include<iostream>
#include<stack> //头文件
using namespace std;
typedef int datatype;
constexpr auto N = 10;

//求比他小的靠得最近的数,将一个个情况列出即可
void left_small(int a[], int n) {
	stack<int>stk;//递减栈,元素为数组a的元素
	for (int i = 0; i < n; i++) {
		while (!stk.empty() && a[i] < stk.top())//a[i]小于栈顶元素,出栈
			stk.pop();
		if (stk.empty()) cout << -1 << " "; //栈为空,a[i]左端不存在比其小的数
		else cout << stk.top() << " "; //栈不空,栈顶即为a[i]左端第一个比其小的数
		stk.push(a[i]); //a[i]入栈
	}
}

//输出数组a的每一个元素的左邻比其大的元素的个数,一定要先满足相邻,再连续
void left_bigger(int a[], int n)
{
	stack<int>stk;//递减栈,元素为数组a的元素
	for (int i = 0; i < n; i++) {
		while (!stk.empty() && a[i] <= a[stk.top()])  //注意后面是下标入栈!!!
			stk.pop();
		if (stk.empty()) cout << i << " "; //栈为空,a[i]之前的元素都比a[i]大
		else cout << i - stk.top() - 1 << " "; //栈不空,a的下标在区间(i,stk.top())中的元素都比a[i]大
		stk.push(i);//下标入栈
	}
}


int main()
{
	int a[] = { 5,6,2,4,9,7,3 };
	left_small(a, 7);
	cout << endl;
	left_bigger(a, 7);
}

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

STL中的栈——stack 的相关文章

  • C#中如何检测字符串是否为货币

    通常当我需要转换时currency string 如 1200 55 z 或 1 249 到十进制值我这样做 if currencyString Contains z decimal value Decimal Parse dataToCh
  • 从 SQL 数据库获取日期时间

    我的数据库表中有一个 DateTime 记录 我编写一个查询从数据库中获取它 string command2 select Last Modified from Company Data where Company Name Descrip
  • 如何自定义 DataTable 列的排序

    我需要对数据表列的值进行排序 该列包含字符串 整数或混合文本 例如 数据表列包含如下值 23 18 12 store 23 store a1 1283 25 如果我使用对值进行排序Dataview sort 方法会按此顺序产生 12 128
  • 将 2D 数组映射到 1D 数组

    我想用一维数组来表示一个二维数组 函数将传递两个索引 x y 和要存储的值 这两个索引代表一维数组的单个元素 并相应地设置它 我知道一维数组需要具有 arrayWidth arrayHeight 的大小 但我不知道如何设置每个元素 例如 如
  • 为什么C Clock()返回0

    我有这样的事情 clock t start end start clock something else end clock printf nClock cycles are d d n start end 我总是得到输出 时钟周期是 0
  • .NET 可移植类库中的 .ToShortDateString 发生了什么

    我想知道为什么没有 ToShortDateString在 NET 可移植类库中 我有 2 个项目 Silverlight 和常规 NET 类库 使用相同的代码 并且代码涉及调用 ToShortDateString on a DateTime
  • 使用 C# 使用应用程序密码登录 Office 365 SMTP

    在我们的 Office 365 公司帐户中实施两步身份验证之前 我的 C WPF 程序已成功进行身份验证并发送邮件 我使用了 SmtpClient 库 但现在我必须找到另一个解决方案 因为它不再起作用 我找不到任何使用 O365 应用程序密
  • 对数字进行向上和向下舍入 C++

    我试图让我的程序分别向上和向下舍入数字 例如 如果数字是3 6 我的程序应该四舍五入最接近的数字 4 如果该数字是3 4 它将向下舍入为 3 我尝试使用ceil库获取 3 个项目的平均值 results ceil marks1 marks2
  • 使用 VSTO 更改 Outlook 设置

    我刚刚花了大约 4 个小时试图弄清楚如何以编程方式检索 设置 Microsoft Outlook 2010 的 Outlook 设置 我所说的 设置 是指文件 选项 邮件下的设置 我想做的是检索用户设置的设置列表 自动化我们每天需要在某些消
  • 控制台应用程序 .net Core 2.0 的配置

    在 net Core 1 中我们可以这样做 IConfiguration config new ConfigurationBuilder AddJsonFile appsettings json true true Build 这样就可以使
  • 在生产者-消费者情况下使用条件变量

    我正在尝试了解条件变量以及如何在生产者 消费者情况下使用它 我有一个队列 其中一个线程将数字推入队列 而另一个线程从队列中弹出数字 当生产线程放置一些数据时 我想使用条件变量向消费线程发出信号 问题是有时 或大多数时候 它只将最多两个项目推
  • C#:如何使用 SHOpenFolderAndSelectItems [重复]

    这个问题在这里已经有答案了 有人可以举例说明如何使用 shell 函数吗SH打开文件夹并选择项目 http msdn microsoft com en us library bb762232 VS 85 aspx来自 C 我不太明白如何使用
  • C++ Primer 5th Edition 错误 bool 值没有指定最小大小?

    bool 的最小大小不应该是 1 个字节吗 这有点学术性的东西 尽管它们会转换为数字 并且 与其他所有事物一样 它们最终将基本上由计算机内存中的数字表示 但布尔值不是数字 你的bool可以取值true 或值false 即使您确实需要至少 1
  • 使用 AutoMapper 进行 LINQ GroupBy 聚合

    试图让查询工作 但老实说不确定如何 或者是否可能 进行它 因为我尝试过的一切都不起作用 共查询6个表 Person PersonVote PersonCategory Category City FirstAdminDivision Per
  • C# - 为什么我需要初始化 [Out] 参数

    我有几个从本机 dll 导入的方法 使用以下语法 internal static class DllClass DllImport Example dll EntryPoint ExampleFunction public static e
  • 多个同名内存数据库

    关系到这个答案 https stackoverflow com a 48446491 596758 我试图通过设置让多个上下文工作UseInMemoryDatabase以同名 下面的测试失败 第二个上下文为空 我还需要做什么才能在内存数据库
  • 如何使用 g++ 在 c++ 20 中使用模块?

    我读了这个链接https gcc gnu org wiki cxx modules https gcc gnu org wiki cxx modules并尝试从该网站复制以下示例 我已经知道这个编译器部分支持模块系统 注 我用的是windo
  • 如何仅更改 DateTime 的日期部分,同时保留时间部分?

    我在代码中使用了很多 DateTime 我想将这些日期时间更改为我的特定日期并保留 时间 1 2012 02 02 06 00 00 gt 2015 12 12 06 00 00 2 2013 02 02 12 00 00 gt 2015
  • Windows 上 libcurl 的静态库[重复]

    这个问题在这里已经有答案了 如何将此库 libcurl 静态链接到 exe 我努力了 disable share enable static 没有帮助 我使用的是MingW32 有没有一种简单的方法来静态链接这个库 这样我的应用程序就不再有
  • ASP.NET Core:会话 ID 始终变化

    今天启动了一个全新的 ASP NET Core 网站 按照说明添加会话 我们在索引页上打印出会话 ID 它始终是唯一的 我认为这可能是 cookie 合规性 所以我在 Chrome 的高级设置和调试器中删除了所有 cookie 但横幅不会再

随机推荐

  • 【MySQL】使用Visio绘制E-R图

    使用Visio绘制E R图 1 创建项目 文件 新建 常规 基本框图 2 调整页面方向 纵向或横向 文件 页面设置 3 准备E R图的三个基本形状 实体用矩形 关系用菱形 属性用椭圆 4 绘制E R图 双击形状后可以在形状中编辑文字 通过绘
  • Cursor!!!GPT-4帮我写代码

    首先介绍一款产品 cursor 官网 https www cursor so IDE作者 https twitter com amanrsanger 目前为止应该是第一个免费能够使用GPT4工作的软件 看作者的Twitter 他说自己提前向
  • 由于找不到d3dx9_43.dll无法继续执行此代码怎么修复?这个三个方法可以解决问题

    在运行游戏 软件的时候 计算机提示 由于找不到d3dx9 43 dll无法继续执行此代码 是怎么回事 其实d3dx9 43 dll是Windows操作系统下的DirectX9的一个组件 而DirectX是Windows系统支持游戏和显卡游戏
  • 【Spring Boot 源码学习】OnClassCondition 详解

    Spring Boot 源码学习系列 OnClassCondition 详解 引言 往期内容 主要内容 1 getOutcomes 方法 2 多处理器拆分处理 3 StandardOutcomesResolver 内部类 4 getMatc
  • linux tmux的经验总结

    背景 主要操作实现 安装 概念了解 快捷键 tmux重启后恢复终端layout界面的方法 如果有多个用户比如adminqilei等 新建windows或者pane分屏保留目录路径 复制模式 支持鼠标模式 窗口列表居中否则session和wi
  • 9大最佳知识库软件/文档管理工具

    企业的任何工作流程都离不开文档管理 面对复杂的业务流程 频繁的文档编辑任务和跨区域的文件共享需求 优秀的文档管理体系能够帮助企业实现安全的文档存储 高效的文档搜索 便捷的文档协作和有效的文档权限 版本 行为管控 由于各个产品切入文档管理市场
  • windows下安装cygwin+swoole教程

    swoole下载 http git oschina net swoole swoole cygwin下载 https www cygwin com setup x86 64 exe cygwin镜像地址 http mirrors sohu
  • 如何拯救空间不足的C盘?

    目录 操作步骤 确定软件后期安装的位置 修改注册表 验证 心得 操作步骤 确定软件后期安装的位置 建议选择硬盘内存比较多的一个盘 我选择的是D盘 然后复制D programs 修改注册表 打开注册表编辑器 双击HKEY LOCAL MACH
  • JS操作dom,bom

    属性是 方法里面是可以写参数的 window open 打开窗口 p1 要打开的新窗口地址 p2 窗口名称 p3 窗口特征 open newwindow html width 400px height 400px close 关闭窗口 al
  • STM32外部高速晶振不起振的故障分析

    STM32外部高速晶振不起振的故障分析 一 故障背景 网上售卖的STM32F103C8T6的核心板如图1所示 由于STM32F103C8T6最小系统核心板的采购成本高达20元 块至40元 块 为了降低采购成本 对其STM32F103C8T6
  • oracle sqlldr详解,sqlldr详解

    Oracle 的SQL LOADER可以将外部数据加载到数据库表中 下面是SQL LOADER的基本特点 1 能装入不同数据类型文件及多个数据文件的数据 2 可装入固定格式 自由定界以及可度长格式的数据 3 可以装入二进制 压缩十进制数据
  • codeblocks安装及使用教程详解

    一 官网下载 搜索codeblocks官网 下载最新codeblocks安装包 codeblocks官网 https www codeblocks org downloads 二 安装 1 双击下载好的安装文件 弹出如下界面 点击 Next
  • matlab dct实现代码,基于DCT数字水印算法的Matlab实现源代码

    M 256 原图像长度 N 32 水印图像长度 K 8 I zeros M M II zeros K K B zeros M M Idct zeros K K D zeros M M 读取原图像 I imread 33 png subplo
  • 机器学习 —— 类不平衡问题与SMOTE过采样算法

    在前段时间做本科毕业设计的时候 遇到了各个类别的样本量分布不均的问题 某些类别的样本数量极多 而有些类别的样本数量极少 也就是所谓的类不平衡 class imbalance 问题 本篇简述了以下内容 什么是类不平衡问题 为什么类不平衡是不好
  • 删除git远程库中误传的文件

    不小心把node modules文件夹上传到远端了哇 别急 有办法 git rm r cached node modules 如果是在某个文件夹下面 也可以使用路径 xxx node modules 之后再执行push git commit
  • c语言灯塔案例求塔低数,C++:有一个8层灯塔,每层所点灯数都等于该层上一层的两倍,一共有765盏灯,求塔底的灯数...

    满意答案 0214zyt 2013 05 23 采纳率 51 等级 12 已帮助 6734人 Note Your choice is C IDE include include using namespace std int main 第一
  • Java多线程的同步问题

    在多线程的编程环境中 可能会有两个或者更多的线程试图同时访问一个有限的资源 必须对这种潜在的资源冲突进行预防 解决办法 在线程使用一个资源的时候 我们为其加锁即可 访问资源的第一个线程为其加上锁以后 其它线程便不能访问那个资源 除非获得那个
  • 刷脸支付助力互联网产业时代全面到来

    近两年来 刷脸支付发展如火如荼 宁波 长沙等多个城市相继开展线下刷脸支付试点 建设银在其网点的ATM机推出刷脸取款 光大银也将人脸识别应用于账户登陆 转账 线上融资等场景 支付宝 财付通等第三方支付公司也争相推出刷脸支付设备 随着移动支付的
  • cs231n: How to Train a Neuron Network 如何训练神经网络

    CS231N第六第七课时的一些笔记 如何训练神经网络是一个比较琐碎的事情 所以整理了一下 以后训练Neuron Network的时候可以看一下 Activation Functions ReLu good ELU leaky ReLu no
  • STL中的栈——stack

    stack为STL中的适配器容器 具有栈的结构特性 对于适配器容器 默认底层容器为deque 在创建stack对象时 也可以指定其他线性容器作为其底层容器 基本操作 include