栈应用——逆波兰算法
创始人
2025-05-31 19:21:42
0

个人主页:【😊个人主页】
系列专栏:【❤️数据结构与算法】
学习名言:传屐朝寻药,分灯夜读书

系列文章目录

第一章 ❤️ 学前知识
第二章 ❤️ 单向链表
第三章 ❤️ 递归
第四章 ❤️ 顺序栈
第五章 ❤️ 队列


文章目录

  • 系列文章目录
  • 前言
  • 中缀表达式?
  • 后缀表达式
  • 逆波兰表达式(中缀表达式转后缀表达式)
  • 为啥要使用逆波兰表达式
  • 实现原理
  • 代码实现


前言

在我们进行数字运算时我们会根据优先级自然的将结果算出来如同喝水一样,这是因为我们在学习算数开始就已经对这种运算方式习以为常了,但只能分辨出0和1的计算机又是如何进行运算的呢?🤔🤔🤔

中缀表达式?

例如a+b,运算符在两个操作数的中间。这是我们一直习惯使用的表达式形式

后缀表达式

例如a b + ,运算符在两个操作数的后面。这是一种利于计算机处理的表达形式

逆波兰表达式(中缀表达式转后缀表达式)

逆波兰表达式又叫做后缀表达式。在通常的表达式中,二元运算符总是置于与之相关的两个运算对象之间,这种表示法也称为中缀表示。波兰逻辑学家J.Lukasiewicz于1929年提出了另一种表示表达式的方法,按此方法,每一运算符都置于其运算对象之后,故称为后缀表示。

为啥要使用逆波兰表达式

逆波兰表达式是一种十分有用的表达式,它将复杂表达式转换为可以依靠简单的操作得到计算结果的表达式。例如(a+b)(c+d)转换为ab+cd+
去除原来表达式中的括号,因为括号只指示运算顺序,不是实际参与计算的元素。
使得运算顺序有规律可寻,计算机能编写出代码完成计算。
在这里插入图片描述

实现原理

一、如果输入的是操作数,则直接追加入。当输入的是 运算符 或者 分界符时压入栈中
1. 如果是左括号 ‘(’, 则 直接压入栈中,等待下一个最近的 右括号 与之配对。
2. 如果是右括号 ‘)',则说明有一对括号已经配对(在表达式输入无误的情况下)。那我们就不将它压栈,而是直接将它丢弃😶‍🌫️,然后出栈,得到元素d,将d依次运算。一直循环,直到出栈元素d 是 左括号 ( ,我们同样丢弃他。
(3)如果是运算符
1.如果栈顶元素不是运算符,则二者没有可比性,则直接将此运算符压栈。 例如栈顶是左括号 ( ,或者栈为空。
2.如果栈顶元素是运算符 ,则比较进入的运算符和栈顶运算符的优先级。如果进入运算符 > 栈顶运算符 ,则直接将此运算符压栈。
如果不满足,则将栈顶运算符出栈,再试图将运算符压栈,如果如果依然不满足 ,继续将新的栈顶运算符弹出 ,直到该运算符可以压入栈中为止。
也就是说,如果在栈中,有2个相邻的元素都是运算符,则他们必须满足:下层运算符的优先级一定小于上层元素的优先级,才能相邻。
最后,如果栈中还有元素,则依次弹出追加到d后,就得到了后缀表达式。

代码实现

#include 
#define STACK_INIT_SIZE 20 //栈的初始化空间大小
#define STACKINCREMENT        10 //每次增加的栈空间大小
#define MAXBUFFER                10 //缓冲区大小
typedef double ElemType;
typedef struct
{int stackSize;ElemType* base;//指向栈底的指针ElemType* top;//指向栈顶的指针}sqStack;
void initStack(sqStack* s)
{s->base = (ElemType*)malloc(STACK_INIT_SIZE * sizeof(ElemType));if (!s->base){exit(0);}s->top = s->base;s->stackSize = STACK_INIT_SIZE;
}
void Push(sqStack* s, ElemType e)//进栈
{if (s->top - s->base >= s->stackSize){s->base = (ElemType*)realloc(s->base, (s->stackSize + STACKINCREMENT) * sizeof(ElemType));if (!s->base){exit(0);}s->top = s->base + s->stackSize;s->stackSize = s->stackSize + STACK_INIT_SIZE;//大小要更新,不然会误认为容量不够又继续申请内存}*(s->top) = e;//把e对应的元素压入栈顶s->top++;//栈顶上移
}
void Pop(sqStack* s, ElemType* e)//出栈
{if (s->top == s->base)//判断栈是不是空{return;}*e = *--(s->top);
}
int stackLen(sqStack s)//计算栈的当前容量,s.stackSize
{return (s.top - s.base);
}
int main()
{char c;sqStack s;int i = 0;double d, e;//临时变量char str[MAXBUFFER];//小数存放缓冲区initStack(&s);printf("请输入逆波兰表达式,数据与运算符之间用空格隔开,按#键结束!\n");scanf("%c", &c);while (c != '#'){while (isdigit(c) || c == '.')//判断c是数字,头文件ctype.h,过滤数字和点以外的数据{str[i++] = c;str[i] = '\0';//给不知道下一个是否还要字符的位置赋结束符,以免不知道多长if (i >= MAXBUFFER)//字符串溢出{printf("\n出错:输入的单个数据过长!\n");return -1;}scanf("%c", &c);//继续输入数据if (c == ' ')//输入空格,代表单个数据输入结束{d = atof(str);//把字符串str转化为浮点数Push(&s, d);i = 0;//i初始化,进入下一个循环break;}}switch (c){case '+'://两个出栈,并相加Pop(&s, &e);//出栈第一个数,给ePop(&s, &d);//出栈第二个数,给dPush(&s, d + e);break;case '-'://两个出栈,并相减Pop(&s, &e);//出栈第一个数,给ePop(&s, &d);//出栈第二个数,给dPush(&s, d - e);break;case '*'://两个出栈,并相乘Pop(&s, &e);//出栈第一个数,给ePop(&s, &d);//出栈第二个数,给dPush(&s, d * e);break;case '/'://两个出栈,并相除Pop(&s, &e);//出栈第一个数,给ePop(&s, &d);//出栈第二个数,给dif (e != 0){Push(&s, d / e);}else{printf("\n错误:除数为零!\n");return -1;}break;}scanf("%c", &c);}Pop(&s, &d);//最终的结算结果放在d里printf("计算结果为:%f\n", d);return 0;
}

相关内容

热门资讯

A股玻尿酸巨头出手!2700字... 医美龙头巨子生物“成分争议”风波持续发酵。日前,美妆博主大嘴博士(香港大学化学博士郝宇)发文,质疑巨...
计算机组成原理实验1---运算...     本实验为哈尔滨工业大学计算机组成原理实验,实验内容均为个人完成,...
3 ROS1通讯编程提高(1) 3 ROS1通讯编程提高3.1 使用VS Code编译ROS13.1.1 VS Code的安装和配置...
前端-session、jwt 目录:   (1)session (2&#x...
前端学习第三阶段-第4章 jQ... 4-1 jQuery介绍及常用API导读 01-jQuery入门导读 02-JavaScri...
EL表达式JSTL标签库 EL表达式     EL:Expression Language 表达式语言     ...
数字温湿度传感器DHT11模块... 模块实例https://blog.csdn.net/qq_38393591/article/deta...
【内网安全】 隧道搭建穿透上线... 文章目录内网穿透-Ngrok-入门-上线1、服务端配置:2、客户端连接服务端ÿ...
【Spring Cloud A... 文章目录前言Metadata元数据ClassMetadataSpring中常见的一些元注解Nacos...
React篇-关于React的... 一.简介1.介绍用于构建用户界面的 JavaScript 库2.创建项目(1)手动创建Documen...
win7 Pro 英文版添加中... win7pro x64英文版添加中文语言包1、下载语言包,并解压成lp.cab,复制到...
Android开发-Andro... 01  Android UI 1.1  UI 用户界面(User Interface,...
基于springboot教师人... 基于springboot教师人事档案管理系统【源码+论文】 开发语言:Jav...
编写软件界面的方式 本文重点解决如下问题:编写软件的界面有哪几种方式?通常情形下࿰...
keil调试专题篇 调试的前提是需要连接调试器比如STLINK。 然后点击菜单或者快捷图标均可进入调试模式。 如果前面...
GO语言小锤硬磕十三、数组与切... 数组用来保存一组相同类型的数据,go语言数组也分一维数组和多维数组。 直接上代码看一下...
三级数据库备考--数据库应用系... 1.数据库应用系统设计包括概念设计、逻辑设计、物理设计3个步骤,每个步骤的设计活动按照...
prometheus数据持久化... https://segmentfault.com/a/1190000015710814 promet...
孩子用什么样的灯对眼睛没有伤害... 现代社会高速发展,越来越多的人开始重视身体健康,尤其是很多家长ÿ...
微软Bing GPT支持AI绘... 我想要一张图片:大象、珊瑚、火山、云朵我想要一张图片:亚特兰蒂斯...