逆波兰表达式算法 java_Java实现表达式计算(中缀表达式转化为后缀表达式/逆波兰式)...

定义:

中缀表达式:我们平时写的数学表达式一般为中缀表达式,如“5+2*(3*(3-1*2+1))”,直接拿中缀表达式直接让计算机计算表达式的结果并不能做到。

后缀表达式:把中缀表达表达式“5+2*(3*(3-1*2+1))”转化“523312*-1+**+”这样的形式,就是后缀表达式。这种记法叫做后缀(postfix)或逆波兰(reverse Polish)记法。计算这个问题最容易的方法就是使用一个栈。

转换方法:

按次序读取中缀表达式的字符。

读到一个操作数的时候,立即放入到输出中。

读到操作符“+”,“-”,“*”,“/”,则从栈中弹出栈元素并输出,直到遇到优先级更低或者“(”的为止操作符为止(该元素不出栈)。

读到操作符“(”,则直接把“(”压入栈中。

读到操作符“)”,则从栈中弹出栈元素并输出,直到遇到第一个“(”为止。其中“(”不再添加到输出中,而是直接舍弃。

当输入为空时,把栈里的操作符全部依次弹出并输出。

举例:

输入:

操作

说明

输出

读取5     把操作数直接输出           5

读取+     栈为空,把操作符压入栈     +     5

读取2     把操作数直接输出     +     52

读取*     栈顶元素为+,优先级低于*,把操作符压入栈     +*     52

读取(     把 ( 直接压入栈     +*(     52

读取3     把操作数直接输出     +*(     523

读取*     栈顶元素为(,把操作符压入栈     +*(*     523

读取(     把 ( 直接压入栈     +*(*(     523

读取3     把操作数直接输出     +*(*(     5233

读取-     栈顶元素为(,把操作符压入栈     +*(*(-     5233

读取1     把操作数直接输出     +*(*(-     52331

读取*     栈顶元素为-,优先级低于*,把操作符压入栈     +*(*(-*     52331

读取2     把操作数直接输出     +*(*(-*     523312

读取+     栈顶元素为*,优先级高于+,以此弹出*,-到输出,到 ( 停止,把操作符压入栈中     +*(*(+     523312*-

读取1     把操作数直接输出     +*(*(+     523312*-1

读取)     从栈中弹出+到输出,遇到第一个 ( 停止,把 ( 弹出栈     +*(*     523312*-1+

读取)     从栈中弹出*到输出,遇到第一个 ( 停止,把 ( 弹出栈     +*     523312*-1+*

结束读取     把栈中的元素全部弹出到输出           523312*-1+**+

输出后缀表达式:

后缀表达式的计算:

按次序读取后缀表达式的每一个字符。

读取到操作数时,把操作数压入栈中。

读取到操作符时,对栈顶的2个操作数做相应运算,要注意操作数的前后顺序。结果压入栈中。

读取完所有的字符后,弹出栈。得到的值就是所求结果。

代码:

import java.util.Stack;

public class Main {

static Stack op = new Stack<>();

public static Float getv(char op, Float f1, Float f2){

if(op == '+') return f2 + f1;

else if(op == '-') return f2 - f1;

else if(op  == '*') return f2 * f1;

else if(op == '/') return f2 / f1;

else return Float.valueOf(-0);

}

/**

* calculate the value of the reverse Polish expression

* @param rp - reverse Polish expression

* @return - result of the expression

*/

public static float calrp(String rp){

Stack v = new Stack<>();

char[] arr = rp.toCharArray();

int len = arr.length;

for(int i = 0; i < len; i++){

Character ch = arr[i];

// if is operand, push to the stack

if(ch >= '0' && ch <= '9') v.push(Float.valueOf(ch - '0'));

// if is operator, calculate the result

// with top 2 operands in the stack,

// push the result into the stack

else v.push(getv(ch, v.pop(), v.pop()));

}

return v.pop();

}

/**

* from infix to postfix

* @param s - String in the form of infix

* @return String in the form of postfix

*/

public static String getrp(String s){

char[] arr = s.toCharArray();

int len = arr.length;

String out = "";

for(int i = 0; i < len; i++){

char ch = arr[i];

if(ch == ' ') continue;

// if is operand, add to

// the output stream directly

if(ch >= '0' && ch <= '9') {

out+=ch;

continue;

}

//if is '(', push to the stack directly

if(ch == '(') op.push(ch);

//if is '+' or '-', pop the operator

// from the stack until '(' and add to

// the output stream

//push the operator to the stack

if(ch == '+' || ch == '-'){

while(!op.empty() && (op.peek() != '('))

out+=op.pop();

op.push(ch);

continue;

}

//if is '*' or '/', pop the operator stack and

// add to the output stream

// until lower priority or '('

//push the operator to the stack

if(ch == '*' || ch == '/'){

while(!op.empty() && (op.peek() == '*' || op.peek() == '/'))

out+=op.pop();

op.push(ch);

continue;

}

//if is ')' pop the operator stack and

// add to the output stream until '(',

// pop '('

if(ch == ')'){

while(!op.empty() && op.peek() != '(')

out += op.pop();

op.pop();

continue;

}

}

while(!op.empty()) out += op.pop();

return out;

}

public static void main(String[] args){

//constraint: the operand should be

// equal or greater than 0

// but equal or less than 9

String exp = "5+2*(3*(2-1))";

System.out.println(calrp(getrp(exp)));

}

}

输出:

11.0

---------------------

作者:Ring_k

来源:CSDN

原文:https://blog.csdn.net/ring_k/article/details/79598961

版权声明:本文为博主原创文章,转载请附上博文链接!

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值