码迷,mamicode.com
首页 > 编程语言 > 详细

JAVA-栈实现中序表达式求值

时间:2017-04-16 09:15:27      阅读:310      评论:0      收藏:0      [点我收藏+]

标签:system   用两个栈   void   pop   前缀表达式   计算机   row   equals   blog   

中序表达式对我们而言是很直观的(我们平时接触的就是这个),但计算机处理起来比较麻烦(括号、优先级之类的),前序和后序表达式中没有括号,而且在计算中只需单向扫描,不需要考虑运算符的优先级。如2*3/(2-1)+3*(4-1)

前序表达式就是前缀表达式,不含括号的算术表达式,而且它是将运算符写在前面,操作数写在后面的表达式,例如:+/*23-21*3-4,也称为“波兰式”。

后序表达式与前序表达式扫描方式正好相反,例如:23*21-/341-*+。

 

用两个栈实现中序表达式求值,表达式中只支持int( 但是计算的结果可能是float)

InfixExpr expr = new InfixExpr("2+3*4+5");

Assert.assertEquals(19, expr.evaluate(), 0.001f);

下面展示了在栈中具体的操作过程

技术分享

技术分享

技术分享

技术分享

下面是具体的实现代码:

public class InfixExpr {

    String expr = null;

    public InfixExpr(String expr) {
    this.expr = expr;
    }

    public float evaluate() {

    char[] ch = expr.toCharArray();
    MyStack stackOfTocken = new MyStack();
    MyStack stackOfNumber = new MyStack();

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

        if (Character.isDigit(ch[i])) {
        int tmp = Integer.parseInt("" + ch[i]);
        while (i < ch.length - 1 && Character.isDigit(ch[++i])) {
            tmp = tmp * 10 + Integer.parseInt("" + ch[i]);
        }
        System.out.println(tmp);
        stackOfNumber.push(tmp);

        }
        if (ch[i] == ‘+‘ || ch[i] == ‘-‘ || ch[i] == ‘*‘ || ch[i] == ‘/‘) {
        stackOfTocken.push(ch[i]);
        }

        if (!(stackOfTocken.isEmpty()) && (char) stackOfTocken.peek() == ‘*‘) {
        int tmp = Integer.parseInt("" + ch[++i]);
        while (i < ch.length - 1 && Character.isDigit(ch[++i])) {
            tmp = tmp * 10 + Integer.parseInt("" + ch[i]);
        }
        if (i != ch.length - 1) {
            i--;
        }
        stackOfNumber.push(tmp);

        int tmp1 = Integer.parseInt("" + stackOfNumber.pop());
        int tmp2 = Integer.parseInt("" + stackOfNumber.pop());
        stackOfNumber.push(tmp1 * tmp2);
        stackOfTocken.pop();

        }
        if (!(stackOfTocken.isEmpty()) && (char) stackOfTocken.peek() == ‘/‘) {
        int tmp = Integer.parseInt("" + ch[++i]);
        while (i < ch.length - 1 && Character.isDigit(ch[++i])) {
            tmp = tmp * 10 + Integer.parseInt("" + ch[i]);
        }
        if (i != ch.length - 1) {
            i--;
        }
        stackOfNumber.push(tmp);

        int tmp1 = Integer.parseInt("" + stackOfNumber.pop());
        int tmp2 = Integer.parseInt("" + stackOfNumber.pop());
        stackOfNumber.push(tmp2 / tmp1);
        stackOfTocken.pop();
        }
    }
    // 将栈中的数字和运算法逆置,便于计算
    reverse(stackOfNumber);
    reverse(stackOfTocken);

    while (!(stackOfTocken.isEmpty())) {
        if ((char) stackOfTocken.peek() == ‘+‘) {
        int tmp1 = Integer.parseInt("" + stackOfNumber.pop());
        int tmp2 = Integer.parseInt("" + stackOfNumber.pop());
        stackOfNumber.push(tmp1 + tmp2);
        }
        
        if ((char) stackOfTocken.peek() == ‘-‘) {
        int tmp1 = Integer.parseInt("" + stackOfNumber.pop());
        int tmp2 = Integer.parseInt("" + stackOfNumber.pop());
        stackOfNumber.push(tmp1 - tmp2);
        }
        stackOfTocken.pop();
    }

    return Float.parseFloat("" + stackOfNumber.pop());
    }

    private void reverse(MyStack s) {

    if (s.isEmpty()) {
        return;
    }
    // 如果s里面只有一个元素,就返回。具体实现是先pop出来一个,判断剩下的是不是空栈。
    Object tmp1 = s.pop();
    reverse(s);
    if (s.isEmpty()) {
        s.push(tmp1);
        return;
    }
    Object temp2 = s.pop();
    reverse(s);
    s.push(tmp1);
    reverse(s);
    s.push(temp2);

    }
}

 

 

 

以及测试用例:

public class InfixExprTest {

    @Before
    public void setUp() throws Exception {
    }

    @After
    public void tearDown() throws Exception {
    }

    @Test
    public void testEvaluate() {
    // InfixExpr expr = new InfixExpr("300*20+12*5-20/4");
    {
        InfixExpr expr = new InfixExpr("2+3*4+5");
        Assert.assertEquals(19.0, expr.evaluate(), 0.001f);
    }
    {
        InfixExpr expr = new InfixExpr("3*20+12*5-40/2");
        Assert.assertEquals(100.0, expr.evaluate(), 0.001f);
    }

    {
        InfixExpr expr = new InfixExpr("3*20/2");
        Assert.assertEquals(30, expr.evaluate(), 0.001f);
    }

    {
        InfixExpr expr = new InfixExpr("20/2*3");
        Assert.assertEquals(30, expr.evaluate(), 0.001f);
    }

    {
        InfixExpr expr = new InfixExpr("10-30+50");
        Assert.assertEquals(30, expr.evaluate(), 0.001f);
    }

    }

}

 

JAVA-栈实现中序表达式求值

标签:system   用两个栈   void   pop   前缀表达式   计算机   row   equals   blog   

原文地址:http://www.cnblogs.com/HarryHook/p/6717767.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!