数据结构(3.8)——栈的应用
栈在括号匹配中的应用
流程图

代码
#include <stdio.h>
#include <stdlib.h>
#define MaxSize 10typedef struct {char data[MaxSize];int top;
} SqStack;// 初始化栈
void InitStack(SqStack* S) {S->top = -1; // 初始化栈顶指针
}// 判空
bool StackEmpty(SqStack* S) {if (S->top == -1) {return true;} else {return false;}
}// 入栈
bool Push(SqStack* S, char x) {if (S->top == MaxSize - 1) { // 栈满,报错return false;} else {S->top = S->top + 1; // 指针先加1S->data[S->top] = x; // 新元素入栈return true;}
}// 出栈
bool Pop(SqStack* S, char* x) {if (StackEmpty(S)) {return false;} else {*x = S->data[S->top]; // 栈顶元素先出栈S->top = S->top - 1; // 指针减1return true;}
}// 括号匹配检查
bool bracketCheck(char str[], int length) {SqStack S;InitStack(&S); // 初始化一个栈for (int i = 0; i < length; i++) {if (str[i] == '(' || str[i] == '[' || str[i] == '{') {Push(&S, str[i]); // 扫描到左括号,入栈} else {if (StackEmpty(&S)) { // 扫描到右括号,且当前栈空return false; // 匹配失败}char topElem;Pop(&S, &topElem); // 栈顶元素出栈if (str[i] == ')' && topElem != '(') {return false;}if (str[i] == ']' && topElem != '[') {return false;}if (str[i] == '}' && topElem != '{') {return false;}}}return StackEmpty(&S); // 检索全部括号后,栈空说明匹配成功
}int main() {char str[] = "{([()])}";int length = sizeof(str) / sizeof(str[0]) - 1; // 计算字符串长度,减1是为了去掉结尾的'\0'if (bracketCheck(str, length)) {printf("括号匹配成功\n");} else {printf("括号匹配失败\n");}return 0;
}
栈在表达式求值中的应用

中缀、后缀、前缀表达式
中缀表达式
运算符在两个操作数中间:
- a + b
- a + b - c
- a + b - c * d
后缀表达式
运算符在两个操作数后面:
- ab +
- ab + c-或者a bc - +
- ab + cd * -
前缀表达式
运算符在两个操作数前面:
- + ab
- - + ab c
- - + ab * cd
中缀表达式转后缀表达式(手算)
- 确定中缀表达式中各个运算符的运算顺序
- 选择下一个运算符,按照[左操作数 右操作数 运算符]的方式组合成一个新的操作数(若运算顺序不唯一,则后缀表达式也不唯一)
- 如果还有运算符没被处理,就继续2步骤
例:
转换成后缀表式: 15 7 11+ - / 3 * 2 11 + + -


"左优先"原则:只要左边的运算符能先计算,就优先计算左边的(可保证运算唯一)
中缀表达式转后缀表达式(机算)

代码示例:
要将中缀表达式转换为后缀表达式,可以按照以下步骤进行:
- 初始化一个空栈,用于保存暂时还不能确定运算顺序的运算符。
- 初始化一个空字符串,用于保存最终的后缀表达式。
- 从左到右扫描中缀表达式中的每个字符。
- 对于每个字符,执行以下操作:
- 如果是操作数,直接添加到后缀表达式中。
- 如果是左括号
(,将其压入栈中。 - 如果是右括号
),则弹出栈中的运算符并添加到后缀表达式中,直到遇到对应的左括号(。左括号(弹出但不添加到后缀表达式中。 - 如果是运算符(如
+、-、*、/等),则将栈中所有优先级高于或等于当前运算符的运算符弹出并添加到后缀表达式中。然后将当前运算符压入栈中。
- 扫描完中缀表达式后,将栈中剩余的运算符全部弹出并添加到后缀表达式中。
下面是一个C语言的示例代码,用于将中缀表达式转换为后缀表达式:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>#define MAX_SIZE 100// 栈的结构定义
typedef struct {char items[MAX_SIZE];int top;
} Stack;// 初始化栈
void initStack(Stack* stack) {stack->top = -1;
}// 判断栈是否为空
int isEmpty(Stack* stack) {return stack->top == -1;
}// 判断栈是否满
int isFull(Stack* stack) {return stack->top == MAX_SIZE - 1;
}// 压栈
void push(Stack* stack, char value) {if (isFull(stack)) {printf("Error: Stack is full.\n");return;}stack->items[++stack->top] = value;
}// 出栈
char pop(Stack* stack) {if (isEmpty(stack)) {printf("Error: Stack is empty.\n");return '\0';}return stack->items[stack->top--];
}// 获取栈顶元素
char peek(Stack* stack) {if (isEmpty(stack)) {printf("Error: Stack is empty.\n");return '\0';}return stack->items[stack->top];
}// 操作符优先级
int precedence(char op) {if (op == '+' || op == '-') {return 1;} else if (op == '*' || op == '/') {return 2;} else if (op == '(' || op == ')') {return 0;}return -1;
}// 中缀转后缀
void infixToPostfix(char* infix, char* postfix) {Stack stack;initStack(&stack);int i, j;for (i = 0, j = 0; infix[i] != '\0'; ++i) {if (infix[i] == ' ') continue;else if (isdigit(infix[i]) || isalpha(infix[i])) {postfix[j++] = infix[i];} else if (infix[i] == '(') {push(&stack, infix[i]);} else if (infix[i] == ')') {while (!isEmpty(&stack) && peek(&stack) != '(') {postfix[j++] = pop(&stack);}pop(&stack); // 弹出左括号} else {while (!isEmpty(&stack) && precedence(infix[i]) <= precedence(peek(&stack))) {postfix[j++] = pop(&stack);}push(&stack, infix[i]);}}while (!isEmpty(&stack)) {postfix[j++] = pop(&stack);}postfix[j] = '\0'; // 结束字符串
}int main() {char infix[] = "a+b*(c-d)-e/f";char postfix[MAX_SIZE];infixToPostfix(infix, postfix);printf("Infix: %s\n", infix);printf("Postfix: %s\n", postfix);return 0;
}
后缀表达式的计算(手算)
从左往右扫描,每遇到一个运算符,就让运算符前面最近的两个操作数执行对应运算,合体为一个操作数
注意:两个操作数的左右顺序


后缀表达式的计算(机算)
用栈实现后缀表达式的计算:
- 从左往右扫描下一个元素,直到处理完所以元素
- 若扫描到操作数则压入栈,并回到1;否则执行3
- 若扫描到运算符,则弹出两个栈顶元素,执行相应运算,运算结果压回栈顶,回到1
注意:后缀表达式先弹出的元素是‘右操作数’
入栈流程:







中缀表达式转前缀表达式(手算)
- 确定中缀表达式中各个运算符的运算顺序
- 确定下一个运算符,按照[运算符 左操作数 右操作数]的方式组合成一个新的操作数
- 如果还有运算符没被处理,就继续2
"右优先"原则:只要右边的运算符能先计算,就优先算右边的


前缀表达式的计算
- 从右往左扫描下一个元素,直到处理完所有元素
- 若扫描到操作数则压入栈,并回到1;否则执行3
- 若扫描到运算符,则弹出两个栈顶元素,执行相应运算,运算结构压回栈顶,回到1
注意前缀表达式先弹出的元素是‘左操作数’

栈在递归中的应用
递归调用时,函数调用栈可称为“递归工作栈”
每进入一层递归,就将递归调用所需信息压入栈顶
每退出一层递归,就从栈顶弹出相应信息
- 缺点:太多层递归可能会导致栈溢出



递归算法可能会包含很多重复计算
总结



相关文章:
数据结构(3.8)——栈的应用
栈在括号匹配中的应用 流程图 代码 #include <stdio.h> #include <stdlib.h> #define MaxSize 10typedef struct {char data[MaxSize];int top; } SqStack;// 初始化栈 void InitStack(SqStack* S) {S->top -1; // 初始化栈顶指针 }// 判空 bool StackEmpty(…...
前端面试题35(在iOS和Android平台上,实现WebSocket协议有哪些常见的库或框架?)
在iOS和Android平台上,实现WebSocket协议有许多成熟且被广泛使用的库和框架。下面是一些推荐的选项: iOS 平台 SocketRocket 简介:这是由Facebook开源的库,专门为iOS和Mac OS X设计,提供WebSocket连接的功能。它基于S…...
Mysql如何高效ALTER TABL
ALTER TABLE 缺点 MySQL 的ALTER TABLE 操作的性能对大表来说是个大问题。 MySQL MySQL 执行大部分修改表结构操作的方法是用新结构的 创建一个,空表从旧表中查出所有数据插入,新表然后删除旧。表这样操作可能需要花费很长,时间 如内果存不…...
vue3+vite搭建第一个cesium项目详细步骤及环境配置(附源码)
文章目录 1.创建vuevite项目2.安装 Cesium2.1 安装cesium2.2 安装vite-plugin-cesium插件(非必选)2.3 新建组件页面map.vue2.4 加载地图 3.完成效果图 1.创建vuevite项目 打开cmd窗口执行以下命令:cesium-vue-app是你的项目名称 npm create…...
LiteOS增加执行自定义源码
开发过程注意事项: 源码工程路径不能太长 源码工程路径不能有中文 一定要关闭360等杀毒软件,否则编译的打包阶段会出错 增加自定义源码的步骤: 1.创建源码目录 2. 创建源文件 新建myhello目录后,再此目录下再新建源文件myhello_demo.c 3. 编…...
《Nature》文章:ChatGPT帮助我学术写作的三种方式
图片翻译 ** 文章内容** 忏悔时间:我使用生成式人工智能(AI)。尽管在学术界关于聊天机器人是积极力量还是消极力量的争论不休,但我几乎每天都使用这些工具来完善我所写论文中的措辞,并寻求对我被要求评估的工作进行替…...
防火墙安全策略与用户认证综合实验
一、实验拓扑 二、实验需求 1.DMZ区内的服务器,办公区仅能在办公时间内<9:00-18:00>可以访问,生产区的设备全天可以访问 2.办公区不允许访问互联网,办公区和游客区允许访问互联网 3.办公区设备10.0.2.10不充许访问DMZ区的FTP服务器和HT…...
vue学习day05-watch侦听器(监视器)、Vue生命周期和生命周期的四个阶段、、工程化开发和脚手架Vue cli
13、watch侦听器(监视器) (1)作用:监视数据变化,执行一些业务逻辑或异步操作 (2)语法: 1)简写语法——简单数据类型,直接监视 ① Watch:{ 数…...
数字人+展厅互动体验方案:多元化互动方式,拓宽文化文娱新体验
数字化创新已成为推动展厅可持续发展,创造全新消费体验,满足游客多元化需求的关键力量。 “数字人数字互动展厅”可以适应年轻一代的文化传播与多媒体互动新体验趋势,打造新生代潮玩聚集地,促进文化创意传播与互动体验场景创新&a…...
在Spring Boot项目中集成监控与报警
在Spring Boot项目中集成监控与报警 大家好,我是微赚淘客系统3.0的小编,也是冬天不穿秋裤,天冷也要风度的程序猿! 1. 引言 在当今的软件开发中,监控和报警系统是保证系统稳定性和可靠性的重要组成部分。Spring Boot…...
opencv实现目标检测功能----20240704
早在 2017 年 8 月,OpenCV 3.3 正式发布,带来了高度改进的“深度神经网络”(dnn)模块。 该模块支持多种深度学习框架,包括 Caffe、TensorFlow 和 Torch/PyTorch。这次我们使用Opencv深度学习的功能实现目标检测的功能,模型选用MobileNetSSD_deploy.caffemodel。 模型加载…...
音视频解封装demo:使用libmp4v2解封装(demux)出mp4文件中的h264视频数据和aac语音数据
1、README 前言 本demo是使用的mp4v2来将mp4文件解封装得到h264、aac的,目前demo提供的.a静态库文件是在x86_64架构的Ubuntu16.04编译得到的,如果想在其他环境下测试demo,可以自行编译mp4v2并替换相应的库文件(libmp4v2.a&#…...
手撸俄罗斯方块(一)——简单介绍
手撸俄罗斯方块 简单介绍 《俄罗斯方块》(俄语:Тетрис,英语:Tetris),是1980年末期至1990年代初期风靡全世界的电脑游戏,是落下型益智游戏的始祖,电子游戏领域的代表作之一&a…...
构建LangChain应用程序的示例代码:61、如何使用 LangChain 和 LangSmith 优化链
本示例介绍如何使用 LangChain 和 LangSmith 优化链。 设置 我们将为 LangSmith 设置环境变量,并加载相关数据 import osos.environ["LANGCHAIN_PROJECT"] "movie-qa" # 设置 LANGCHAIN_PROJECT 环境变量为 "movie-qa"import pan…...
Android系统通过属性设置来控制log输出的方案
Android系统通过属性设置来控制log输出的方案 背景 项目中经常需要在针对性的模块或者文件,分析问题的时候输出Log,但问题分析完成后,又由于性能问题,需要关闭这些log输出。当前大多数情况下是控制整个系统的log等级来实现&#…...
JavaDoc的最佳实践
文章目录 一、JavaDoc 使用说明1.1 什么是 JavaDoc1.2 文档注释结构1.3 常见的 Javadoc 标签 二、文档最佳实践2.1 注释原则2.2 实际案例 参考资料 一、JavaDoc 使用说明 1.1 什么是 JavaDoc JavaDoc 是一款能根据源代码中的文档注释来产生 HTML 格式的 API 文档的工具。 Jav…...
数字力量助西部职教全面提升——唯众品牌大数据、人工智能系列产品中标甘肃庆阳职院数字经济人才培养基地!
近日,唯众品牌凭借在大数据和人工智能领域深耕多年的技术积累和卓越产品,成功中标庆阳职业技术学院全国一体化算力网络国家枢纽节点数字经济人才培养基地项目,标志着唯众在助力西部职业教育与数字经济融合发展的新征程上迈出了坚实的一步。 …...
Swagger的原理及应用详解(四)
本系列文章简介: 在当今快速发展的软件开发领域,特别是随着微服务架构和前后端分离开发模式的普及,API(Application Programming Interface,应用程序编程接口)的设计与管理变得愈发重要。一个清晰、准确且易于理解的API文档不仅能够提升开发效率,还能促进前后端开发者之…...
Elasticsearch7.10集群搭建
Elasticsearch详细介绍: Elasticsearch 是一个分布式、RESTful 风格的搜索和分析引擎。它的核心基于 Apache Lucene,能够处理海量的数据,并支持实时的全文搜索。以下是关于 Elasticsearch 的详细介绍。 一、基本概念 索引(Index…...
SMU Summer 2024 Contest Round 3
A.Hcode OnlineJudge 先用欧拉筛把质数预处理出来,然后枚举左端点的质数,只需要询问右端点是不是质数并取差值的min就行了 #include<bits/stdc.h> #define endl \n #define mk make_pair #define int long long using namespace std; typedef lon…...
日语AI面试高效通关秘籍:专业解读与青柚面试智能助攻
在如今就业市场竞争日益激烈的背景下,越来越多的求职者将目光投向了日本及中日双语岗位。但是,一场日语面试往往让许多人感到步履维艰。你是否也曾因为面试官抛出的“刁钻问题”而心生畏惧?面对生疏的日语交流环境,即便提前恶补了…...
第一篇:Agent2Agent (A2A) 协议——协作式人工智能的黎明
AI 领域的快速发展正在催生一个新时代,智能代理(agents)不再是孤立的个体,而是能够像一个数字团队一样协作。然而,当前 AI 生态系统的碎片化阻碍了这一愿景的实现,导致了“AI 巴别塔问题”——不同代理之间…...
【论文阅读28】-CNN-BiLSTM-Attention-(2024)
本文把滑坡位移序列拆开、筛优质因子,再用 CNN-BiLSTM-Attention 来动态预测每个子序列,最后重构出总位移,预测效果超越传统模型。 文章目录 1 引言2 方法2.1 位移时间序列加性模型2.2 变分模态分解 (VMD) 具体步骤2.3.1 样本熵(S…...
Linux离线(zip方式)安装docker
目录 基础信息操作系统信息docker信息 安装实例安装步骤示例 遇到的问题问题1:修改默认工作路径启动失败问题2 找不到对应组 基础信息 操作系统信息 OS版本:CentOS 7 64位 内核版本:3.10.0 相关命令: uname -rcat /etc/os-rele…...
云原生安全实战:API网关Kong的鉴权与限流详解
🔥「炎码工坊」技术弹药已装填! 点击关注 → 解锁工业级干货【工具实测|项目避坑|源码燃烧指南】 一、基础概念 1. API网关(API Gateway) API网关是微服务架构中的核心组件,负责统一管理所有API的流量入口。它像一座…...
搭建DNS域名解析服务器(正向解析资源文件)
正向解析资源文件 1)准备工作 服务端及客户端都关闭安全软件 [rootlocalhost ~]# systemctl stop firewalld [rootlocalhost ~]# setenforce 0 2)服务端安装软件:bind 1.配置yum源 [rootlocalhost ~]# cat /etc/yum.repos.d/base.repo [Base…...
【从零开始学习JVM | 第四篇】类加载器和双亲委派机制(高频面试题)
前言: 双亲委派机制对于面试这块来说非常重要,在实际开发中也是经常遇见需要打破双亲委派的需求,今天我们一起来探索一下什么是双亲委派机制,在此之前我们先介绍一下类的加载器。 目录 编辑 前言: 类加载器 1. …...
数学建模-滑翔伞伞翼面积的设计,运动状态计算和优化 !
我们考虑滑翔伞的伞翼面积设计问题以及运动状态描述。滑翔伞的性能主要取决于伞翼面积、气动特性以及飞行员的重量。我们的目标是建立数学模型来描述滑翔伞的运动状态,并优化伞翼面积的设计。 一、问题分析 滑翔伞在飞行过程中受到重力、升力和阻力的作用。升力和阻力与伞翼面…...
node.js的初步学习
那什么是node.js呢? 和JavaScript又是什么关系呢? node.js 提供了 JavaScript的运行环境。当JavaScript作为后端开发语言来说, 需要在node.js的环境上进行当JavaScript作为前端开发语言来说,需要在浏览器的环境上进行 Node.js 可…...
Linux操作系统共享Windows操作系统的文件
目录 一、共享文件 二、挂载 一、共享文件 点击虚拟机选项-设置 点击选项,设置文件夹共享为总是启用,点击添加,可添加需要共享的文件夹 查询是否共享成功 ls /mnt/hgfs 如果显示Download(这是我共享的文件夹)&…...

