栈的应用——括号匹配、表达式求值、递归

news2024/12/26 21:10:14

目录

    • 一、栈在括号匹配中的应用
      • 逻辑实现
      • 代码实现
    • 二、栈在表达式求值中的应用
      • 手算实现
      • 代码实现
    • 三、栈在递归中的应用
      • 逻辑实现
      • 代码实现

一、栈在括号匹配中的应用

括号匹配,顾名思义。若括号按照正确的格式嵌套,则可正确匹配,例如([]),反之若括号按照不正确的格式嵌套,则不可正确匹配,例如([))。

逻辑实现

考虑下列括号序列:
括号匹配题目
分析该括号序列是否可正确匹配的流程如下:
1、接收第1个括号"[“后,期待与之匹配的第8个括号”]“出现
2、接收第2个括号”(“,此时第1个括号”[“暂时放在一边,期待与之匹配的第7个括号”)“出现
3、接收第3个括号”[“,此时第2个括号”(“暂时放在一边,期待与之匹配的第4个括号”]“出现
4、接收第4个括号”]",第3个括号的期待得到满足等待第2个括号的期待出现
5、以此类推

代码实现

算法思想
1、初始时设置一个空栈,顺序读入等待判断的括号序列
2、若读入的是右括号,有两种情况:第一种情况是使置于栈顶的最急迫的期待得以满足,第二种情况为不合法(括号序列不匹配,退出程序)
3、若读入的是左括号,则作为一个急迫的期待压入栈中(后压入的期待比先压入的期待更加急迫)
4、若算法结束时栈为空,则匹配成功,否则,匹配失败

代码如下

int Parentheses_match(char Arr,int n){//要判断的括号序列存储在数组Arr[n]中
	SqStack S;
	InitStack(&S);//初始化栈
	int i=0;
	for(i=0;i<n;i++){//读取括号序列
		if(Arr[i]=='('||Arr[i]=='[') Push(&S,Arr[i]);//若读入的是左括号,入栈
		else if(Arr[i]==')'||Arr[i]==']'){//若读入的是右括号
			char x;
			GetTop(S,&x);//读栈顶元素,并用x返回栈顶元素
			
			//判断右括号是否和栈顶的左括号匹配
			if((x=='('&&Arr[i]==')')||(x=='['&&Arr[i]==']')){
				Pop(&S,&x);//弹出栈顶元素,等待下个期待被满足
			};//满足左括号的期待
			else return 0;//右括号未和最近的左括号配对,序列不合法
		}
	}
	if(StackEmpty(S)) return 1;//读取完括号序列后栈为空,序列合法
	else return 0;
}

其中用到的栈的基本操作可见文章操作受限的线性表——栈

二、栈在表达式求值中的应用

我们平时见到的表达式都是从左往后理解的,例如a+b=c、a/b=c等,我们可以称这种阅读方式为中缀表达式(即运算符在两个运算数中间)。相对应的是后缀表达式(即运算符在两个运算数之后)

手算实现

例如,中缀表达式 A + B ∗ ( C − D ) − E / F A+B*(C-D)-E/F A+B(CD)E/F对应的后缀表达式为 A B C D − ∗ + E F / − ABCD-*+EF/- ABCD+EF/中缀表达式转换为后缀表达式的过程如下图所示(按照运算符的运算顺序进行转换):
中缀表达式转后缀表达式
需要注意的是,中缀表达式转化为后缀表达式的结果不唯一,例如下图也是一种转化方式。这种不唯一性来源于某些运算的优先级相同,例如’+‘和’-‘,’*‘和’/'。我们在进行中缀表达式和后缀表达式的转换时,往往采用上图的转换原则——优先级相同的运算符从左到右进行编号
中缀表达式转后缀表达式

代码实现

算法思想:
1、顺序扫描表达式的每一项,根据类型做如下操作
2、若该项是操作数,则将其压入栈中
3、若该项是操作符(简写为op),则连续从栈中退出两个操作数Y和X,形成运算指令XY,并将得到的结果重新压入栈中
4、当表达式的所有项都扫描处理完后,栈顶存放的就是最后的计算结果

代码如下

int Expression_evaluation(char Arr,int n){//表达式存储在Arr数组中
	SqStack S;
	InitStack(&S);//初始化栈
	int i=0;
	for(i=0;i<n;i++){//读取表达式
		if(Arr[i]>=48&&Arr[i]<=57) Push(&S,Arr[i]);//读取的是操作数,入栈
		else{//读取的是操作符,出栈两个操作数进行运算
			int x;
			int y;
			if(Arr[i]==42){//如果是乘法运算
				Pop(&S,&x);
				Pop(&S,&y);
				x=x*y;
				Push(&S,x);
			}
			else if(Arr[i]==47){//如果是除法运算
				Pop(&S,&x);
				Pop(&S,&y);
				x=x/y;
				Push(&S,x);
			}
			else if(Arr[i]==43){//如果是加法运算
				Pop(&S,&x);
				Pop(&S,&y);
				x=x+y;
				Push(&S,x);
			}
			else if(Arr[i]==45){//如果是减法运算
				Pop(&S,&x);
				Pop(&S,&y);
				x=x-y;
				Push(&S,x);
			}
			else return -10000;//返回-10000表示表达式格式不正确
		}
	}
	int answer=GetTop(S,&x);//栈顶元素为计算结果
	return answer;
}

三、栈在递归中的应用

递归可以理解为一个函数/过程/数据结构的定义中又应用了它自身,则这个函数/过程/数据结构是递归定义的,简称递归。

递归模型必须满足两个条件,第一通过循环体(递归表达式)实现递归,第二递归要有出口(结束条件)

一个典型的递归的例子是斐波那契数列
斐波那契数列
代码实现如下:

int Fib(int n){
	if(n==0) return 0;
	else if(n==1) return 1;
	else return Fib(n-1)+Fib(n-2);//递归表达式
}

在递归调用的过程中,系统为每一层的返回点、局部变量、传入实参等开辟了递归工作栈来进行数据存储(函数调用时,需要用一个栈存储调用的返回地址、实参和局部变量等)。若递归的次数过多,容易造成栈溢出。

递归的有点事代码简单且容易理解,但效率不高,因为其包含很多重复的计算,例如在计算Fib(5)时,要先计算Fib(4)和Fib(3),在计算Fib(4)时又要计算Fib(3)和Fib(2)… …一共需要计算2次Fib(3)、3次Fib(2),5次Fib(1)和3次Fib(0)。

逻辑实现

如果想把递归算法转换为非递归算法,就需要借助栈来实现。例如斐波那契数列,在每一次计算时,都从栈顶读取(注意使读值不是出栈)两个元素相加再入栈,即可得到每一个斐波那契数列。

代码实现

int Fib_stack(int n){//计算Fib(n)
	if(n=0) return 0;//Fib(0)
	else if(n=1) return 1;//Fib(1)
	else{//Fib(n)	n>1
		SqStack S;
		InitStack(&S);//初始化栈
		int F0=0;
		int F1=1;
		
		Push(&S,F0);//Fib(0)入栈
		Push(&S,F1);//Fib(1)入栈
		int i=0;
		int Fi;
		int Fj;
		int Fk;
		for(i=2;i<=n;i++){//非递归的计算Fib(i)
			GetTop(S,&Fj);
			GetSecond(S,&Fk);
			Fi=Fj+Fk;
			Push(&S,Fi);
		}
	}
	int Fn;
	GetTop(S,&Fn);
	if(i==n) return Fn;//返回Fib(n)
}

另有队列的应用——层次遍历、计算机系统文章见链接【待补充】

本文内容为个人学习总结所得,如有问题欢迎评论区提出。

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

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

相关文章

scratch lenet(12): LeNet-5输出层和损失函数的计算

文章目录 1. 目的2. 输出层结构2.1 Gaussian Connection2.2 Gaussian Connection 的 weight 可视化 3. Loss Function3.1 当前类别判断错误时&#xff0c;loss function 中的项&#xff08;基本项&#xff09;3.2 判断为其他类别时&#xff0c; loss function 中的项&#xff0…

Spring发展历程及其体系结构

⭐作者介绍&#xff1a;大二本科网络工程专业在读&#xff0c;持续学习Java&#xff0c;努力输出优质文章 ⭐作者主页&#xff1a;逐梦苍穹 ⭐所属专栏&#xff1a;Spring 目录 发展历程体系结构 发展历程 体系结构 Spring框架的体系结构的主要组成部分&#xff1a; 核心容器…

idea如何集成Tomcat

&#xff08;1&#xff09;、这里应该找Add Configuration点击这里&#xff1a;如果没有标志&#xff0c;点击Exit (2)、这里可以配置一个配置项&#xff1a; &#xff08;3&#xff09;、loacl是本地&#xff0c;那个是远程&#xff1a;这里我选择本地 &#xff08;4&#xff…

代码随想录算法训练营第四十二天 | 01背包理论基础,01背包理论基础(滚动数组),416. 分割等和子集

代码随想录算法训练营第四十二天 | 01背包理论基础&#xff0c;01背包理论基础&#xff08;滚动数组&#xff09;&#xff0c;416. 分割等和子集 1.1 01背包理论基础 01背包 回溯法&#xff1a;暴力的解法是o(2^n)指数级别的时间复杂度&#xff0c;需要动态规划的解法来进行优…

如果你曾经拥有python,那么现在你应该拥抱Julia吗?

看完本文&#xff0c;您就会有较成熟的想法。 Julia和Python的区别是什么&#xff1f;为什么Julia适合用于大规模计算和超级计算机模拟&#xff1f; 你一定听说过Julia和Python这两个编程语言。虽然它们都可以用于从简单的机器学习应用程序到巨大的超级计算机模拟的所有方面&am…

Gradio的Audio组件介绍

❤️觉得内容不错的话&#xff0c;欢迎点赞收藏加关注&#x1f60a;&#x1f60a;&#x1f60a;&#xff0c;后续会继续输入更多优质内容❤️ &#x1f449;有问题欢迎大家加关注私戳或者评论&#xff08;包括但不限于NLP算法相关&#xff0c;linux学习相关&#xff0c;读研读博…

ImGUI项目建立(cmake+MinGW64)

Dear ImGUI ImGui是一个轻量级的C图形界面库&#xff0c;它可以用于创建各种交互式的工具和编辑器。具有跨平台、高性能的特点。 ImGUI自身不能创建窗口&#xff0c;需要使用Win32API或glfw或SDL等工具来创建窗口&#xff0c;另外需要使用OpenGL或DirectX、vulkan用于渲染图形…

excel数据的编排与整理——表格结构的整理(一)

excel数据的编排与整理——表格结构的整理(一) 1 快速移动一列数据到指定位置 1.1 移动到相邻行 1.1.1 题目内容 1.1.2 选中年龄列➡移动到左侧直到出现十字箭头 1.1.3 按下shift键和左键➡移动到指定位置,直到出现"T"字形 1.1.4 松开鼠标左键后,移动就完成了 1.2…

Debian 12中安装Rstudio

1.Debian 12中安装R 打开终端&#xff0c;执行命令&#xff1a;#apt search r-base (注&#xff1a;此图为安装r-base后再来截图的)&#xff0c;Debian 12官方源中默认为r-base 4.2.2,如果想安装最新版&#xff08;当前最新版为R-4.3.0&#xff09;,可参考上次写的博文“Debi…

thinkphp 反序列化漏洞

文章目录 配置xdebug反序列化漏洞利用链详细分析poc1&#xff08;任意文件删除&#xff09;poc2&#xff08;任意命令执行&#xff09; 补充代码 配置xdebug php.ini [Xdebug] zend_extensionD:/phpstudy_pro/Extensions/php/php7.3.4nts/ext/php_xdebug.dll xdebug.modedebu…

Windows系统下安装Hadoop

文章目录 安装步骤环境验证 前面我们已经讲过了在 Linux下安装配置Hadoop环境&#xff0c;还没看过的可以先去了解一下安装流程。今天我们来看一下如何在Window下安装Hadoop&#xff0c;这其实和在Linux下的安装都是大同小异的。下面我们具体来看一下安装步骤。 安装步骤 首先…

pytorch安装教程(Ubuntu22.04.1,Anaconda3-2023.03)

本文主要讲述了在Linux系统中&#xff0c;通过anaconda安装pytorch的具体步骤&#xff0c;即需要在Ubuntu已经安装好anaconda&#xff0c;其安装步骤可以参考此篇博客&#xff1a;Ubuntu安装Anaconda详细步骤&#xff08;Ubuntu22.04.1&#xff0c;Anaconda3-2023.03&#xff0…

数据结构期末总结

数据结构绪论 数据结构的概念 数据结构 &#xff1a; 数据结构是相互之间存在一种或多种特定关系的数据元素的集合数据结构研究的问题 &#xff1a;数据结构是一门研究非数值计算的程序设计问题中计算机的操作对象以及它们之间的关系和操作等的学科抽象数据类型ADT&#xff1a…

JWT漏洞

JWT介绍 1.1 JWT概念 JSON Web Token(JWT) 是一个开放标准。它定义了一种紧凑而独立的方法&#xff0c;用于在各方之间安全地将信息作为JSON对象传输。由于此信息是经过数字签名的&#xff0c;因此可以被验证和信任。可以使用secret&#xff08;HMAC算法&#xff09;或使用“…

SwinTransformer细节总结

SwinTransformer可以看成是披着ResNet外壳的vision transformer&#xff0c;swin 就是两个关键词&#xff1a;patch 多尺度。下面结合code来说一些重点的细节&#xff1a; 总览图 这里W-MSA缩写是window-multi head self attention&#xff0c;SW-MSA缩写是shifted window-mu…

JDK 8到JDK 17都有哪些吸引人的特性?

从JDK 8到JDK 17&#xff0c;Java语言和平台经历了许多变化和改进&#xff0c;引入了许多吸引人的新特性和功能。在这里&#xff0c;给大家列举一些我认为最有趣或最有用的新特性&#xff0c;并会以实际使用案例为大家展示新用法。希望大家多多点赞关注&#xff01;&#xff01…

C语言的switch case函数

文章目录 1 函数结构2 执行过程3 break关键字4 补充说明参考 1 函数结构 switch 是另外一种选择结构的语句&#xff0c;用来代替简单的、拥有多个分枝的 if else 语句&#xff0c;基本格式如下&#xff1a; switch(表达式){ case 整型数值1: 语句 1; case 整型数值2: 语句 2; …

极致呈现系列之:Echarts词云图的数据共振

目录 什么是词云图词云图的特性及应用场景词云图的特性词云图的应用场景 Echarts中词云图的常用属性vue3中创建词云图 什么是词云图 词云图&#xff08;Word Cloud&#xff09;是一种以文字的形式展示数据的可视化图表。它通过将各个文字按照一定的规则排列&#xff0c;并根据…

车载软件架构 —— 闲聊几句AUTOSAR OS(六)

我是穿拖鞋的汉子,魔都中坚持长期主义的工程师。 老规矩,分享一段喜欢的文字,避免自己成为高知识低文化的工程师: 没有人关注你。也无需有人关注你。你必须承认自己的价值,你不能站在他人的角度来反对自己。人生在世,最怕的就是把别人的眼光当成自己生活的唯一标准。到最…

centos版本的EDA虚拟机搭建2

这次教程主要介绍centos的必备软件的安装。 0、参考博客 1、VMware下CentOS 7虚拟机的安装 2、搭建属于自己的数字IC EDA环境&#xff08;二&#xff09;&#xff1a;搭建Centos的基本使用环境和工具 3、cenos7基本配置 1、git安装 sudo yum install -y git2、gvim安装 su…