数据结构(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…...

JavaSec-RCE
简介 RCE(Remote Code Execution),可以分为:命令注入(Command Injection)、代码注入(Code Injection) 代码注入 1.漏洞场景:Groovy代码注入 Groovy是一种基于JVM的动态语言,语法简洁,支持闭包、动态类型和Java互操作性,…...

【WiFi帧结构】
文章目录 帧结构MAC头部管理帧 帧结构 Wi-Fi的帧分为三部分组成:MAC头部frame bodyFCS,其中MAC是固定格式的,frame body是可变长度。 MAC头部有frame control,duration,address1,address2,addre…...

python/java环境配置
环境变量放一起 python: 1.首先下载Python Python下载地址:Download Python | Python.org downloads ---windows -- 64 2.安装Python 下面两个,然后自定义,全选 可以把前4个选上 3.环境配置 1)搜高级系统设置 2…...
uni-app学习笔记二十二---使用vite.config.js全局导入常用依赖
在前面的练习中,每个页面需要使用ref,onShow等生命周期钩子函数时都需要像下面这样导入 import {onMounted, ref} from "vue" 如果不想每个页面都导入,需要使用node.js命令npm安装unplugin-auto-import npm install unplugin-au…...
C++.OpenGL (14/64)多光源(Multiple Lights)
多光源(Multiple Lights) 多光源渲染技术概览 #mermaid-svg-3L5e5gGn76TNh7Lq {font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;fill:#333;}#mermaid-svg-3L5e5gGn76TNh7Lq .error-icon{fill:#552222;}#mermaid-svg-3L5e5gGn76TNh7Lq .erro…...

推荐 github 项目:GeminiImageApp(图片生成方向,可以做一定的素材)
推荐 github 项目:GeminiImageApp(图片生成方向,可以做一定的素材) 这个项目能干嘛? 使用 gemini 2.0 的 api 和 google 其他的 api 来做衍生处理 简化和优化了文生图和图生图的行为(我的最主要) 并且有一些目标检测和切割(我用不到) 视频和 imagefx 因为没 a…...

Chromium 136 编译指南 Windows篇:depot_tools 配置与源码获取(二)
引言 工欲善其事,必先利其器。在完成了 Visual Studio 2022 和 Windows SDK 的安装后,我们即将接触到 Chromium 开发生态中最核心的工具——depot_tools。这个由 Google 精心打造的工具集,就像是连接开发者与 Chromium 庞大代码库的智能桥梁…...
uniapp 集成腾讯云 IM 富媒体消息(地理位置/文件)
UniApp 集成腾讯云 IM 富媒体消息全攻略(地理位置/文件) 一、功能实现原理 腾讯云 IM 通过 消息扩展机制 支持富媒体类型,核心实现方式: 标准消息类型:直接使用 SDK 内置类型(文件、图片等)自…...

stm32wle5 lpuart DMA数据不接收
配置波特率9600时,需要使用外部低速晶振...

STM32标准库-ADC数模转换器
文章目录 一、ADC1.1简介1. 2逐次逼近型ADC1.3ADC框图1.4ADC基本结构1.4.1 信号 “上车点”:输入模块(GPIO、温度、V_REFINT)1.4.2 信号 “调度站”:多路开关1.4.3 信号 “加工厂”:ADC 转换器(规则组 注入…...