【数据结构】——逆波兰表达式
逆波兰表达式简介
假设有一天赵地佐同学(名称纯属虚构,如有雷同,纯属巧合)拿着一道数据极其恐怖的四则运算题找到同班的张三同学,希望他在1s内能给出答案。这时最好的办法是什么呢?当然是不理他,可惜乐于探究的张三同学并不愿意放弃这个机会,于是他拿出了随身携带的笔记本电脑。
为了解决这个问题,让我们尽可能抽象一下四则运算的表达式:
ans=A+B/C+(D*E+F)*G
像上面这种符合人们认知习惯自然书写而成的数学表达式称为中缀表达式。但可惜的是,愚蠢的计算机无法直接识别这种表达式,这意味这我们必须做一些工作让计算机可以从左向右顺序计算并得出正确结果。
将中缀表达式转化为后缀表达式(逆波兰表达式)便是一种解决办法。
逆波兰式是一种将待计算量写在前, 把运算符写在后(通常是两数之后)的计算式,比如:
中缀表达式 | 逆波兰表达式 |
A + B | A B + |
A * B | A B * |
A +B * C | A B C * + |
A * ( B + C ) | A B C + * |
逆波兰式的求解
逆波兰式的求解过程可以用栈来实现。为了便于理解,举一个带数值的例子:
中缀表达式:6 * ( ( 5 + ( 2 + 3 ) * 8 ) + 3 )
首先,转化为逆波兰式: 6 5 2 3 + 8 * + 3 + *
计算过程如下:
首先,将前四个数依次入栈:
Top Of Stack ——————> | 3 |
2 | |
5 | |
6 |
然后,遇到第一个符号为加号,记录并弹出栈顶的两个元素,计算结果后压入栈中
Top Of Stack ——————> | 5 |
5 | |
6 |
继续操作,遇到便数字压入栈中,遇到符号,弹出栈顶两元素并压入其结果。
(特别提醒:在减法和除法的计算中,数字弹出顺序与其计算顺序刚好相反)
Top Of Stack ——————> | 288 |
计算完成,其结果为288。
简单了解计算原理后,开始快乐地写代码(代码以函数形式给出,方便搬运):
#include<iostream>
#include<algorithm>
#include<string>
#include<stack>
using namespace std;
string str;long long calculate(string str)
{int len=str.length(),pos=0;stack<long long> sta;char ch;while(pos<len){if(str[pos]>='0'&&str[pos]<='9'){long long temp=0;while(str[pos]!=' '&&str[pos]!='.') temp=temp*10+(str[pos++]-'0');sta.push(temp);}else if(str[pos]==' '||str[pos]=='.') pos++;else if(str[pos]=='@') break;else{ch=str[pos++];int num1,num2;num2=sta.top(); sta.pop();num1=sta.top(); sta.pop();switch(ch){case '+': sta.push(num1+num2); break;case '-': sta.push(num1-num2); break;case '*': sta.push(num1*num2); break;case '/': sta.push(num1/num2); break;}}}return sta.top();
}int main()
{getline(cin,str);cout<<calculate(str);return 0;
}
中缀表达式与逆波兰式的转化
推荐一个大佬的博客(比我讲的清楚多了)中缀表达式转后缀表达式
整体思路仍然采用栈的方式 (以 3*(2+1)为例 )
准备工作:采用string类储存待转化的中缀表达式,并用两个栈储存记录数字与符号。
主要思想:
- 如果遇到数字,压入数字栈中
- 如果遇到左括号,压入符号栈中
- 如果遇到四则运算符,检验当前符号栈中有无同等级或更高级运算符
- 如果有,将同等级或更高级运算符依次压入数字栈中,然后再将当前符号压入。
- 如果没有,直接压入数字栈中。
- 如果遇到右括号,从当前符号栈顶出开始检验,不断将符号压入数字栈中直到遇到第一个左括号。但同时要将符号栈中的左括号丢弃掉。
- 最后进行尾处理,当字符串扫描完毕后,将当前符号栈中剩余的符号依次压入数字栈中。
主要步骤:
- 检测到数字 3 ,直接压入数字栈中
- 当前字符为 ‘ * ’ ,同时栈中没有同级或更高级运算符,直接压入符号栈中
- 当前字符为 ‘( ’,压入符号栈中
- (中间两个数字带一个 ‘ + ’ 号就省略了,做法完全相同)
- 遇到右括号,将符号栈中的 ‘ + ’ 压入数字栈中
具体实现代码:
#include<iostream>
#include<algorithm>
#include<string>
#include<stack>
using namespace std;string TRANS_TO_POLISH(string str)
{stack<string> num_stack, operator_stack;int len = str.length(), pos = 0;while (pos < len){if (str[pos] >= '0' && str[pos] <= '9'){long long temp = 0;while (str[pos] >= '0' && str[pos]<='9') temp = temp * 10 + (str[pos++] - '0');num_stack.push(to_string(temp));}else if (str[pos] == ' ' || str[pos] == '.') pos++;else{char ch = str[pos++];if (ch == '+'){while(!operator_stack.empty()&&(operator_stack.top()=="*"||operator_stack.top()=="/")) num_stack.push(operator_stack.top()),operator_stack.pop();while(!operator_stack.empty()&&(operator_stack.top()=="+"||operator_stack.top()=="-")) num_stack.push(operator_stack.top()),operator_stack.pop();operator_stack.push("+");}else if (ch == '-'){while(!operator_stack.empty()&&(operator_stack.top()=="*"||operator_stack.top()=="/")) num_stack.push(operator_stack.top()),operator_stack.pop();while(!operator_stack.empty()&&(operator_stack.top()=="+"||operator_stack.top()=="-")) num_stack.push(operator_stack.top()),operator_stack.pop();operator_stack.push("-");}else if (ch == '*'){while(!operator_stack.empty()&&(operator_stack.top()=="*"||operator_stack.top()=="/")) num_stack.push(operator_stack.top()),operator_stack.pop();operator_stack.push("*");}else if (ch == '/'){while(!operator_stack.empty()&&(operator_stack.top()=="*"||operator_stack.top()=="/")) num_stack.push(operator_stack.top()),operator_stack.pop();operator_stack.push("/");}else if (ch == '(') operator_stack.push("(");else{while (operator_stack.top() != "("){num_stack.push(operator_stack.top());operator_stack.pop();}operator_stack.pop();}}}while (!operator_stack.empty()) { num_stack.push(operator_stack.top()); operator_stack.pop(); }string ans = "";while (!num_stack.empty()) ans = num_stack.top() + " "+ans, num_stack.pop();return ans;
}int main()
{string str; getline(cin, str);cout << TRANS_TO_POLISH(str);return 0;
}
【数据结构】——逆波兰表达式相关推荐
- 数据结构-栈应用之逆波兰表达式(后缀表达式)
逆波兰表达式含义我就不做赘述了,摘自百科上的一段话: 逆波兰表达式又叫做后缀表达式.在通常的表达式中,二元运算符总是置于与之相关的两个运算对象之间,这种表示法也称为中缀表示.波兰逻辑学家J.Lukas ...
- 数据结构:栈的了解与示例(逆波兰表达式)
数据结构一般需要具备三点 1.能保存数据集合 2.需按照一定规则进行操作 3.可以对数据做各种操作 逆波兰表达式:12 3 + 3 4 - * 表示成普通算术式为 (12+3)*(3-4)=-15 判 ...
- 数据结构:后缀表达式(逆波兰表达式)
逆波兰表达式计算 package com.atchina.stack;import java.util.ArrayList; import java.util.List; import java.ut ...
- 数据结构:前缀,中缀,后缀表达式(逆波兰表达式)
前缀表达式(波兰表达式) 前缀表达式的运算符位于操作数之前. 比如 (1+2)*3-4 对应的前缀表达式就是: - * + 1 2 3 4 前缀表达式的计算机求值 从右至左扫描表达式,遇到数字时,就 ...
- 【数据结构与算法】之深入解析“逆波兰表达式求值”的求解思路与算法示例
一.题目要求 根据逆波兰表示法,求表达式的值.有效的算符包括 +.-.*./,每个运算对象可以是整数,也可以是另一个逆波兰表达式. 两个整数之间的除法只保留整数部分. 可以保证给定的逆波兰表达式总是有 ...
- 数据结构 - 栈 (逆波兰计算器)(栈的三种表达式)(前缀、中缀和后缀表达式,后缀也叫逆波兰表达式)(中缀表达式转后缀表达式实现步骤及完整代码)
栈的三种表达式:前缀.中缀和后缀表达式,后缀也叫逆波兰表达式 前缀(波兰表达式) 中缀(对人来讲很好理解,对于计算机来讲就方便了,一般会把中缀表达式转换成后缀表达式) 后缀(逆波兰表达式) 计算过程 ...
- 数据结构链表之栈——解决括号匹配问题和逆波兰表达式求值问题——6
括号匹配问题和逆波兰表达式求值问题 基于上一节已经使用python代码对栈进行了简单的实现,这一节我们在其基础上解决两个常见的问题 案例 括号匹配问题(点我直接到代码实现) 逆波兰表达式求值问题(点我 ...
- 【Java】LeetCode 150. 逆波兰表达式求值 (后缀表达式)
题目: 根据 逆波兰表示法,求表达式的值. 有效的算符包括 +.-.*./ .每个运算对象可以是整数,也可以是另一个逆波兰表达式. 说明: 整数除法只保留整数部分. 给定逆波兰表达式总是有效的.换句话 ...
- 逆波兰表达式简单介绍
逆波兰表达式又叫做后缀表达式.在通常的表达式中,二元运算符总是置于与之相关的两个运算对象之间,所以,这种表示法也称为中缀表示.波兰逻辑学家J.Lukasiewicz于1929年提出了另一种表示表达式的 ...
- 数据结构——逆波兰式
很久没有关注算法和数据结构,大部分知识都已经忘记了:是时间好好回炉一下了,说实话干读数据机构这本书还是挺枯燥而且这本书原理性比较多,有一定的难度.这不刚看到逆波兰式废了好大劲才搞懂,老了... 逆波兰 ...
最新文章
- Maven项目下update maven后Eclipse报错:java.lang.ClassNotFoundException: org.springfra
- 原创:Docker在云家政的应用 谢绝复制粘贴内容
- JavaWeb:JDBC之数据库连接池
- systick定时器 延时计时
- Result Maps collection already contains value for ***的问题
- input和img图片水平对齐
- 使用cocoaPods一键集成第三方登录(新浪微博,qq,微信)
- 闲话杂谈—至曾经的自己
- 面向智能化软件开发的开源生态大数据
- ab plc软件_【万泉河】PLC垃圾程序赏析2:AB RSLOGIX 5000
- css权威指南 note2
- MySQL 得到数据库的大小
- 屏幕适配 percent_库的扩展
- pane Java_ToolPane.java
- Java代码块、构造方法(包含继承关系)的执行顺序
- Windows程序设计之基本介绍
- mysql安装_win版
- 使用orCAD Library Builder建立TO-220的封装
- 前端面试题(一)(CSS篇)建议收藏,持续更新中...
- Android 字符串的替换字符