java 中缀表达式计算,c2java 第5篇 栈跟中缀表达式的直接计算

c2java 第5篇 栈和中缀表达式的直接计算

中缀表达式一般是先转换为后缀表达式,然后再计算的,其实我们可以边转换边计算。

/*Infix.java

使用两个栈直接求解中缀表达式,一个栈保存运算符S,一个栈保存操作数D。

例子:

a+b*c

D:a,b S:+

D:a,b,c S:+,*

D:a,bc S:+

D:a+bc S:

a*b/c+d

D: a,b S:*

D: a*b S:/

D:a*b/c S:+

D:a*b/c+d S:

a^b^c

D:a,b S:^

D:a,b,c S:^,^

D:a,b^c S:^

D:a^b^c S:

a*(b+c)

D:a S:*(

D:a,b S:*(+

D:a,b,c S:*(+)

D:a,b+c S:*

D:a*(b+c) S:

这几种情形,通过赋予运算符适当的优先级,可统一为:

清空栈优先级大于等于扫描优先级的运算符 (R0)

这里只是为了说明栈的应用,因此简单假设操作数是一位数字,并且没有空格,

如果扩展成BigDecimal应该不困难。

中缀表达式的计算规则,从左到右扫描一遍,在扫描过程中:

R1 如果遇到数字,则压入操作数栈D;

R2 如果遇到操作符,则根据R0弹出S中的操作符;

R3 每弹出一个操作符,就弹出D中两个操作数,并把结果压入D。

扫描结束时,可能S不为空,按规则R3。最终D中仅有的一个是结果,S 应该为空。

author: ludi 2014.04

*/

import java.util.Stack;

public class Infix

{

public static int eval(int a, int b, char op)

{

int ret = 0;

switch(op){

case '+': ret = a + b; break;

case '-': ret = a - b; break;

case '*': ret = a * b; break;

case '/': ret = a / b; break;

case '%': ret = a % b; break;

case '^': {

ret = 1;

while(b-- > 0){

ret *= a;

}

}break;

default: System.out.println("error op " + op); break;

}

return ret;

}

public static int evaluate(String infix)

{

Stack d = new Stack();

Stack s = new Stack();

int i, a, b;

char ch;

Symbol op, op2;

for(i = 0; i < infix.length(); ++i){

ch = infix.charAt(i);

if (Character.isDigit(ch)){

d.push(ch - '0');

}else {

op = new Symbol(ch);

while(!s.empty() && (s.peek().compareTo(op) >= 0)){

op2 = s.pop();

b = d.pop();

a = d.pop();

d.push(eval(a, b,op2.op));

}

if(ch == ')'){

s.pop(); /*弹出'('*/

}else s.push(op);

}

}

while(!s.empty()){

op2 = s.pop();

b = d.pop();

a = d.pop();

d.push(eval(a, b, op2.op));

}

System.out.printf("%s = %d d.size %d s.size %d%n", infix, d.peek(), d.size(), s.size());

return d.pop();

}

public static void main(String[] arg)

{

evaluate("1+2*3");

evaluate("2*(3+4)");

evaluate("2*3/2+1");

evaluate("2^3^2");

evaluate("(2^3)^2");

evaluate("(2^3)^2+2^3^2+2*3/2+1+2*(3+4)");

evaluate("2^(2*(3+4))");

}

}

class Symbol implements Comparable

{

char op;

int inputPrec; /*正在被扫描的操作符的优先级*/

int stackPrec; /*栈优先级:值越小停留在栈中时间越长*/

public Symbol (char ch){

op = ch;

switch(op){

case '+':

case '-':inputPrec = stackPrec = 1;

break;

case '*':

case '%':

case '/': inputPrec = 2;

stackPrec = 2;

break;

case '^':

inputPrec = 4;

stackPrec = 3; /*右结合的操作符扫描大于栈优先级*/

break;

case '(':

inputPrec = 5;

stackPrec = -1; /*最高的扫描优先级,最低的栈优先级*/

break;

case ')':

inputPrec = 0;

stackPrec = 0;

break;

}

}

public int compareTo(Symbol item)

{

int result;

if (stackPrec < item.inputPrec)

result = -1;

else if (stackPrec == item.inputPrec)

result = 0;

else

result = 1;

return result;

}

public char getOp()

{ return op; }

}

/*

ludi@msys ~/java

$ javac -encoding UTF-8 Infix.java && java Infix

1+2*3 = 7 d.size 1 s.size 0

2*(3+4) = 14 d.size 1 s.size 0

2*3/2+1 = 4 d.size 1 s.size 0

2^3^2 = 512 d.size 1 s.size 0

(2^3)^2 = 64 d.size 1 s.size 0

(2^3)^2+2^3^2+2*3/2+1+2*(3+4) = 594 d.size 1 s.size 0

2^(2*(3+4)) = 16384 d.size 1 s.size 0

ludi@msys ~/java

*/

这里面为了简明起见,没有做错误处理。

很好奇编译器是怎么计算常量表达式的,不知道是不是这样子呢。

附:

一些与栈有关的有意思的话题:

[1] 神奇的卡塔兰数Catalan

http://blog.csdn.net/nupt123456789/article/details/22735113

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值