关于利用STL栈求解四则中缀表达式以及中缀表达式转逆波兰表达式和逆波兰表达式的求解
今天总结一下栈的一个重要应用---四则数学表达式的求解
数学表达式的求解是栈的一个重要的应用,在计算机的应用中
如果求解一个四则运算表达式,我们可能会直接写一个程序例如什么printf("%d",a+b)这些类似的简单代码实现加减乘除运算
但如果给你一个这样的表达式:9+(3-1)*3+10/2,这样的表达式对于计算机的困难点是乘除号出现在了加减号的后面,并且加上括号就更加麻烦了,
而只识别01的计算机可能会只按照式子从左往右挨个计算,这就忽略了四则运算表达式的按顺序计算,因此,我们需要设计一种算法来实现对于这类四则运算表达式的求解
我们都知道,对于有左括号的式子一定会有右括号但是有右括号的式子却不一档有左括号,因此我们需要一种储存的数据结构来实现逆序存储和匹配,因此就用了栈这种数据结构;
遇到左括号就进站,出现右括号左括号出战并且让数字参与运算;
但是很遗憾的是,括号也是四则运算式的一部分,有没有一种方法可以让括号不出现在运算式中呢?
答案是有的:
有一种表达式被称为是逆波兰表达式的表达式可以避免括号的出现,这种表达式不需要括号出现,并且是一种后缀表达式
后缀之地方在于运算符是出现在运算数之后的
例如这样的表达式

像这样,就避免了括号的出现,使运算更加简单;
那怎么将中缀表达式转成逆波兰表达式呢?
转换的标准是酱紫的:
碰到数字就输出,如果是运算符先判断与栈顶符号的优先级,是右括号或者优先级小于等于栈顶符号的,将栈顶元素一次输出并且弹栈,并且把当前符号进栈,直到输出后缀表达式;
当然这样说显得很笼统,我总结了一下记忆的方式:

按照这样的法则就可以将中缀表达式转成逆波兰表达式啦;
来举个栗子:9+(3-1)*3+10/2

转化方式和步骤是酱紫的,
我们接下来用代码实现一下:
1 #include<bits/stdc++.h>
2 using namespace std;
3 stack<char>q;
4 string s;
5 int main()
6 {
7 std::ios::sync_with_stdio(false);
8 cin.tie(0);
9 cout.tie(0);
10 getline(cin,s);
11 for(register int i=0;i<s.size();i++)
12 {
13 if(s[i]>='a'&&s[i]<='z')//碰到数字直接输出
14 cout<<s[i];
15 else if(s[i]==')')//如果碰到右括号,就找到左括号与它相匹配
16 {
17 while(true)
18 {
19 if(q.top()=='(')//碰到了就弹栈并且停止
20 {
21 q.pop();
22 break;
23 }
24 cout<<q.top();
25 q.pop();//没找到之前一直弹栈并输出
26 }
27 }
28 else//运算符
29 {
30 if(!q.empty()&&(s[i]=='+'||s[i]=='-')&&(q.top()=='*'||q.top()=='/'))//碰到加号或者减号
31 {
32 while(!q.empty())
33 {
34 if(q.top()=='(')//碰到括号就停止
35 break;
36 cout<<q.top();//一直弹栈并输出
37 q.pop();
38 }
39 q.push(s[i]);//当前的元素入栈
40 }
41 else
42 q.push(s[i]);//其余的入栈
43 }
44 }
45 while(!q.empty())
46 {
47 cout<<q.top();
48 q.pop();
49 }
50 return 0;
51 }
逆波兰表达式转化成功了,怎么求逆波兰表达式的值呢:
很简单,从头开始扫描,如果碰到数字就进站,
如果碰到运算符,将栈顶的两个数字出站进行运算,在将结果入栈,一直得到最终的结果;
图解演示一下吧:

相应的用代码实现是灰常简单的:
1 #include<bits/stdc++.h>
2 using namespace std;
3 const int num=1e4+10;
4 char ch[num];
5 int n;
6 stack<int>q;
7 bool operatorpoland(char op)//判段是不是运算符
8 {
9 if(op=='+'||op=='-'||op=='*'||op=='/')
10 return true;
11 else
12 return false;
13 }
14 int reversepoland()
15 {
16 int a,b;
17 for(register int i=0;i<n;i++)
18 {
19 if(!operatorpoland(ch[i]))//如果不是运算符
20 {
21 q.push((ch[i]-'0'));//入栈
22 }
23 else
24 {
25 int a=q.top();//取栈顶两个元素进行运算
26 q.pop();
27 int b=q.top();
28 q.pop();
29 if(ch[i]=='+')//如果运算符是加号
30 q.push(a+b);
31 else if(ch[i]=='-')//如果运算符号是减号
32 q.push(a-b);
33 else if(ch[i]=='*')//乘号
34 q.push(a*b);
35 else if(ch[i]=='/')//除号
36 q.push(a/b);
37 }
38 }
39 return q.top();//最后得到栈顶的元素即是结果
40 }
41 int main()
42 {
43 std::ios::sync_with_stdio(false);
44 cin>>ch;
45 n=strlen(ch);
46 printf("%d",reversepoland());
47 return 0;
48 }
可以拿两道题目练练手:
https://acm.sdut.edu.cn/onlinejudge3/contests/3980/problems/F
http://acm.hdu.edu.cn/showproblem.php?pid=1237(水却处理起来有些麻烦)
一会会看情况把没学完的kmp算法给补上;
那就先到这里啦~~~~
关于利用STL栈求解四则中缀表达式以及中缀表达式转逆波兰表达式和逆波兰表达式的求解的更多相关文章
- hdu1237 简单计算器[STL 栈]
目录 题目地址 题干 代码和解释 参考 题目地址 hdu1237 题干 代码和解释 解本题时使用了STL 栈,要记得使用#include<stack>. 解本题时使用了isdigit()函 ...
- 从零开始写STL—栈和队列
从零开始写STL-栈和队列 适配器模式 意图:将一个类的接口转换成客户希望的另外一个接口.适配器模式使得原本由于接口不兼容而不能一起工作的那些类可以一起工作. 主要解决:主要解决在软件系统中,常常要将 ...
- C++表达式求值(利用数据结构栈)
唉,刚刚用C++又又一次写了一个较完好的表达式求值程序,最后精简后程序还不到100行.这不经让我 想到了大一上学期刚学c语言时自己费了好大的劲,写了几百行并且功能还不是非常齐全(当时还不能计算有括号的 ...
- STL栈的应用之表达式求值
#include<iostream> #include<cstring> #include<cstdio> #include<stack> using ...
- ACM YTU 十进制与八进制的转换 (栈和队列) STL栈调用
十进制与八进制的转换(栈和队列) Description 对于输入的任意一个非负十进制整数,利用栈打印输出与其等值的八进制数. Input 111 Output 157 Sample Input 14 ...
- 利用顺序栈解决括号匹配问题(c++)-- 数据结构
题目: 7-1 括号匹配 (30 分) 给定一串字符,不超过100个字符,可能包括括号.数字.字母.标点符号.空格,编程检查这一串字符中的( ) ,[ ],{ }是否匹配. 输入格式: 输入在一行 ...
- C++ STL栈和队列
在C++标准库(STL)中,实现了栈和队列,方便使用,在这里我整理了一下笔记,作简要介绍. 1,栈(stack): 头文件 : #include<stack> 定义栈 :stack< ...
- 十进制--->二进制(利用C++栈功能)
原创 十进制转二进制很简单,其中用到C++的栈功能就能更加方便! stack<int> s; //栈的定义,s已经被定义为一个栈 s.push(); //将20入栈 s.push(); s ...
- hdu1702 ACboy needs your help again![简单STL 栈 队列]
目录 题目地址 题干 代码和解释 参考 题目地址 hdu1702 题干 代码和解释 本题很简单,只要掌握STL stack和STL vector的语法即可作答.记录本题是为了记录STL vector的 ...
随机推荐
- Spring框架中的单例bean是线程安全的吗?
不,Spring框架中的单例bean不是线程安全的.
- idea-中的Mark Diretory as的内容
Sources Root:告诉idea这个文件夹及其子文件夹中包含源代码,是需要编译构建的一部分 Test Sources Root:测试源文件夹允许您将与测试相关的代码与生产代码分开.通常,源和测试 ...
- CAN总线系列讲座第六讲——SJA1000的滤波器设置
CAN总线的滤波器设置就像给总线上的节点设置了一层过滤网,只有符合要求的CAN信息帧才可以通过,其余的一概滤除. 在验收滤波器的帮助下,只有当接收信息中的识别位和验收滤波器预定义的值相等时,CAN 控 ...
- DOS、DOS攻击、DDOS攻击、DRDOS攻击
https://baike.baidu.com/item/dos%E6%94%BB%E5%87%BB/3792374?fr=aladdin DOS:中文名称是拒绝服务,一切能引起DOS行为的攻击都被称 ...
- javascript新手实例1-DOM基本操作
学习javascript好多同学不知道怎么上手,跟着网上的新手教程做了一遍又觉得javascript很简单,但是真正自己用起来又觉得写不出什么东西,我觉得学习最好的方法就是跟着有趣的例子做,所以我们的 ...
- 探讨:微信小程序应该如何设计
微信小程序公测后,开发者非常热情,都有很高的期待,都想抓住这一波红利.但是热情背后需要冷静,我们需要搞清楚两个问题: 微信想要我们做什么?微信小程序可以做什么? 微信想要我们做什么? 首先来弄清楚微信 ...
- transformjs 污染了 DOM?是你不了解它的强大
原文链接:https://github.com/AlloyTeam/AlloyTouch/wiki/Powerful-transformjs 写在前面 上星期在React微信群里,有小伙伴觉得tran ...
- js原生的Ajax
js原生的Ajax其实就是围绕浏览器内内置的Ajax引擎对象进行学习的,要使用js原 生的Ajax完成异步操作,有如下几个步骤: 1)创建Ajax引擎对象 2)为Ajax引擎对象绑定监听(监听服务器已 ...
- jq移动端图片预览 (fly-zomm-img.js)
效果图: ===>==> 里面还与很多属性设置: index 关闭按钮等等 代码: //html-----------------------<div class="he ...
- string 函数
传送门:https://www.w3school.com.cn/php/php_ref_array.asp addcslashes() 返回在指定的字符前添加反斜杠的字符串. addslashes() ...