JavaScript实现计算后缀表达式(逆波兰表达式)以及将中缀表达式转为后缀表达式
逆波兰表达式,它的语法规定,表达式必须以逆波兰表达式的方式给出。逆波兰表达式又叫做后缀表达式。这个知识点在数据结构和编译原理这两门课程中都有介绍,下面是一些例子:
正常的表达式 逆波兰表达式
a+b ---> a,b,+
a+(b-c) ---> a,b,c,-,+
a+(b-c)d ---> a,d,b,c,-,,+
a=1+3 ---> a=1,3 +
http=(smtp+http+telnet)/1024 写成什么呢?
http=smtp,http,telnet,+,+,1024,/
逆波兰表达式是一种十分有用的表达式,它将复杂表达式转换为可以依靠简单的操作得到计算结果的表达式。例如(a+b)(c+d)转换为ab+cd+
它的优势在于只用两种简单操作,入栈和出栈就可以搞定任何普通表达式的运算。
计算逆波兰表达式方式如下:
如果当前字符为变量或者为数字,则压栈,如果是运算符,则将栈顶两个元素弹出作相应运算,结果再入栈,最后当表达式扫描完后,栈里的就是结果。
将一个普通的中序表达式转换为逆波兰表达式的一般算法是:
(1)首先构造一个运算符栈,此运算符在栈内遵循越往栈顶优先级越高的原则。
(2)读入一个用中缀表示的简单算术表达式,为方便起见,设该简单算术表达式的右端多加上了优先级最低的特殊符号“#”。
(3)从左至右扫描该算术表达式,从第一个字符开始判断,如果该字符是数字,则分析到该数字串的结束并将该数字串直接输出。
(4)如果不是数字,该字符则是运算符,此时需比较优先关系。
做法如下:将该字符与运算符栈顶的运算符的优先关系相比较。如果,该字符优先关系高于此运算符栈顶的运算符,则将该运算符入栈。倘若不是的话,则将栈顶的运算符从栈中弹出,直到栈顶运算符的优先级低于当前运算符,将该字符入栈。
(5)重复上述操作(3)-(4)直至扫描完整个简单算术表达式,确定所有字符都得到正确处理,我们便可以将中缀式表示的简单算术表达式转化为逆波兰表示的简单算术表达式。
下面是程序化算法流程:
1、建立运算符栈stackOperator用于运算符的存储,压入'\0'。
2、预处理表达式,正、负号前加0(如果一个加号(减号)出现在最前面或左括号后面,则该加号(减号)为正负号) 。
3、顺序扫描表达式,如果当前字符是数字(优先级为0的符号),则直接输出该数字;如果当前字符为运算符或括号(优先级不为0的符号),则判断第4点 。
4、若当前运算符为'(',直接入栈;
若为')',出栈并顺序输出运算符直到遇到第一个'(',遇到的第一个'('出栈但不输出;
若为其它,比较stackOperator栈顶元素与当前元素的优先级:
如果 栈顶元素 >= 当前元素,出栈并顺序输出运算符直到 栈顶元素 < 当前元素,然后当前元素入栈;
如果 栈顶元素 < 当前元素,直接入栈。
5、重复第3点直到表达式扫描完毕。
6、顺序出栈并输出运算符直到栈顶元素为'\0'。
各运算符及符号优先级:
'\0': -1
')': 1
'(': 2
'+'、'-': 3
'*'、'/'、'%': 4
'^': 5
其它: 0
/**
* 计算逆波兰表达式的值
*/
function calculate(RPolishArray){
var result = 0;
var tempArray = new Array(100);
var tempNum = -1;
for(i = 0;i < RPolishArray.length;i++){
if(RPolishArray[i].match(/\d/)){
tempNum++;
tempArray[tempNum] = RPolishArray[i];
}else{
switch(RPolishArray[i]){
case '+':
result = (tempArray[tempNum-1] *1) + (tempArray[tempNum] * 1);
tempNum--;
tempArray[tempNum] = result;
break;
case '-':
result = (tempArray[tempNum-1] *1) - (tempArray[tempNum] * 1);
tempNum--;
tempArray[tempNum] = result;
break;
case '*':
result = (tempArray[tempNum-1] *1) * (tempArray[tempNum] * 1);
tempNum--;
tempArray[tempNum] = result;
break;
case '/':
result = (tempArray[tempNum-1] *1) / (tempArray[tempNum] * 1);
tempNum--;
tempArray[tempNum] = result;
break;
}
}
}
result = tempArray[tempNum];
return result;
}
/**
* 把普通算术表达式转换为逆波兰表达式
*/
function toRPolish(input){
var regex = /(\(|\)|\+|\-|\*|\/)+/;
var array = input.split(regex);
var RPolish = ""
var isI = false;
num = 0;
var SymbolArray = new Array(100);
var SymbolNum = -1;
for(j = 0;j < input.length;j++){
if(input.charAt(j).match(/\d/)){
if(isI == false){
RPolish += ','
RPolish += array[num];
num++;
isI = true;
}
}
else{
if(SymbolNum == -1){
SymbolNum++;
SymbolArray[SymbolNum] = input.charAt(j);
}else{
if(input.charAt(j).match(/\(/) || SymbolArray[SymbolNum].match(/\(/)){
SymbolNum++;
SymbolArray[SymbolNum] = input.charAt(j);
}else if(input.charAt(j).match(/\)/)){
while(!SymbolArray[SymbolNum].match(/\(/)){
RPolish += ',';
RPolish += SymbolArray[SymbolNum];
SymbolNum--;
}
SymbolNum--;
}else if(compare(input.charAt(j),SymbolArray[SymbolNum])){
SymbolNum++;
SymbolArray[SymbolNum] = input.charAt(j);
}else if(!compare(input.charAt(j),SymbolArray[SymbolNum])){
RPolish += ',';
RPolish += SymbolArray[SymbolNum];
SymbolNum--;
if(SymbolNum >= 0){
if(SymbolArray[SymbolNum].match(/\(/)){
SymbolNum++;
SymbolArray[SymbolNum] = input.charAt(j);
}else if(!compare(input.charAt(j),SymbolArray[SymbolNum])){
RPolish += ',';
RPolish += SymbolArray[SymbolNum];
SymbolArray[SymbolNum] = input.charAt(j);
}else{
SymbolNum++;
SymbolArray[SymbolNum] = input.charAt(j);
}
}else{
SymbolNum++;
SymbolArray[SymbolNum] = input.charAt(j);
}
}
}
isI = false;
}
}
while(SymbolNum >=0){
RPolish += ',';
RPolish += SymbolArray[SymbolNum];
SymbolNum--;
}
regex = /,/;
var RPolishArray = RPolish.split(regex);
return RPolishArray;
}
function compare(a,b){
if((a.match(/\*/)||a.match(/\//))&&(b.match(/\+/)||b.match(/\-/))){
return true;
}else{
return false;
}
}
JavaScript实现计算后缀表达式(逆波兰表达式)以及将中缀表达式转为后缀表达式的更多相关文章
- java 中缀转后缀(逆波兰)
import java.util.Stack; public class LeetCode_middleTransformToReversePolish { /** * @param args */ ...
- 逆波兰表达式[栈 C 语言 实现]
逆波兰表达式 逆波兰表达式又叫做后缀表达式.在通常的表达式中,二元运算符总是置于与之相关的两个运算对象之间,这种表示法也称为中缀表示.波兰逻辑学家J.Lukasiewicz于1929年提出了另一种表示 ...
- C++基础算法学习——逆波兰表达式问题
例题:逆波兰表达式逆波兰表达式是一种把运算符前置的算术表达式,例如普通的表达式2 + 3的逆波兰表示法为+ 2 3.逆波兰表达式的优点是运算符之间不必有优先级关系,也不必用括号改变运算次序,例如(2 ...
- 关于逆波兰式的c++实现
正常的表达式 逆波兰表达式 a+b ---> a,b,+ a+(b-c) ---> a,b,c,-,+ a+(b-c)*d ---> a,b,c,-,d,*,+ a+d*(b-c)- ...
- C++ | 栈的应用(逆波兰算法) | 计算器
#include <iostream> using std::cin; using std::cout; using std::endl; template<typename T&g ...
- javascript:逆波兰式表示法计算表达式结果
逆波兰式表示法,是由栈做基础的表达式,举个例子: 5 1 2 + 4 * + 3 - 等价于 5 + ((1 + 2) * 4) - 3 原理:依次将5 1 2 压入栈中, 这时遇到了运算符 + ...
- LeetCode_p150_逆波兰表达式计算/后缀表达式计算
有效的运算符包括 +, -, *, / .每个运算对象可以是整数,也可以是另一个逆波兰表达式. 说明: 整数除法只保留整数部分. 给定逆波兰表达式总是有效的.换句话说,表达式总会得出有效数值且不存在除 ...
- 中缀表达式变后缀表达式、后缀表达式(逆波兰)求值(python版本)
定义: 中缀表达式: 在通常的表达式中,二元运算符总是置于与之相关的两个运算对象之间,这种表示法也称为中缀表达式 后缀表达式: 又叫逆波兰表达式 ,不包含括号,运算符放在两个运算对象的后面,所有的计算 ...
- leetcode算法学习----逆波兰表达式求值(后缀表达式)
下面题目是LeetCode算法:逆波兰表达式求值(java实现) 逆波兰表达式即后缀表达式. 题目: 有效的运算符包括 +, -, *, / .每个运算对象可以是整数,也可以是另一个逆波兰表达式.同 ...
随机推荐
- C#实现EXCEL表格转DataTable
C#代码实现把Excel文件转化为DataTable,根据Excel的文件后缀名不同,用不同的方法来进行实现,下面通过根据Excel文件的两种后缀名(*.xlsx和*.xls)分别来实现.获取文件后缀 ...
- Spring Boot2 系列教程 (十二) | 整合 thymeleaf
前言 如题,今天介绍 Thymeleaf ,并整合 Thymeleaf 开发一个简陋版的学生信息管理系统. SpringBoot 提供了大量模板引擎,包含 Freemarker.Groovy.Thym ...
- Nginx作为web静态资源服务器——跨域访问
跨站访问 为什么浏览器禁止跨域访问 Nginx跨站访问 Syntax:add_header name value [always]; Default:—— Context:http,serve ...
- 2.Scanner的进阶使用
package com.duan.scanner; import java.util.Scanner; public class Demo04 { public static void main(St ...
- oa办公系统是什么?对企业有什么作用?
OA办公系统是指利用计算机网络帮助企业实现办公自动化,用系统软件代替传统的手工工作帮助企业处理内部事务,例如文档共享.部门协作.报销.业务流程等等,最终目的帮助企业提高工作效率,实现利益最大化. 随着 ...
- 美食家App开发日记4
研究了卡片式布局中的Recyclerview的用法,但是调试了很长时间,导入包总是有问题,一到手机上运行就会闪退.还是在网上查了很多方法,很不开心我还是解决不了.
- Android的学习之路一
在Android的道路上越走越远==,本着一颗童心去学习,没想到最后会成为自己的职业.看到过知乎上写的,并不是兴趣使比尔盖茨以及乔布斯他们成就斐然,而是他们真正的牛逼使得即使买大饼也能成为世界首富.然 ...
- GIMP(Linux下的Photoshop),Centos7下安装过程
点当然是上官网:https://www.gimp.org/ 这英语看不懂,果断用谷歌的网页翻译. 点下载,就会有 看到这个,就点 下载一个安装的包 用命令行打上 [root@localhost 下载] ...
- Nginx核心模块
error_log 语法:error_log file [ debug | info | notice | warn | error | crit ]默认值:${prefix}/logs/error. ...
- 小白学Java:RandomAccessFile
目录 小白学Java:RandomAccessFile 概述 继承与实现 构造器 模式设置 文件指针 操作数据 读取数据 read(byte b[])与read() 追加数据 插入数据 小白学Java ...