前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >计算器:中缀表达式转后缀表达式

计算器:中缀表达式转后缀表达式

作者头像
卡尔曼和玻尔兹曼谁曼
发布2019-01-25 14:42:18
2.1K0
发布2019-01-25 14:42:18
举报

这几天想写一个Android的计算器,所以先写好中缀表达式到后缀表达式的计算。

例如:中缀表达式(8+9*10)-4/2+3 我们可以进行如下操作: 1、将每个操作符对应的两个操作数用括号括上(((8+(9*10))-(4/2))+3) 2、将操作符移到对应的括号外(((8(910*)+)(42)/)-3)+ 3、去掉括号即可  8910*+42/-3+

是不是很简单,这样我们就讲一个中缀表达式转换成论文后缀表达式。

那么计算机中是怎样进行的呢? 转换的整体流程如下: 中缀表达式转后缀表达式的方法: 1.遇到操作数:直接输出(添加到后缀表达式中) 2.栈为空时,遇到运算符,直接入栈 3.遇到左括号:将其入栈 4.遇到右括号:执行出栈操作,并将出栈的元素输出,直到弹出栈的是左括号,左括号不输出。 5.遇到其他运算符:加减乘除:弹出所有优先级大于或者等于该运算符的栈顶元素,然后将该运算符入栈 6.最终将栈中的元素依次出栈,输出。

下面是我写得一个示例代码:

package cn.tzy.calculator;

import java.util.HashMap;
import java.util.LinkedList;
import java.util.Map;
import java.util.Queue;
import java.util.Stack;

/**
 * Created by gchx on 2015/2/9.
 */
public class Calculator {
	
    private Map<String, Integer> priority;//操作符优先级Map

    public Calculator() {
        initPriority();
    }

    private void initPriority() {
        this.priority = new HashMap<>();
        //这里的#号是操作符堆栈中的栈底元素,是为了程序方便处理而添加的
        this.priority.put("#", 0);
        this.priority.put("+", 1);
        this.priority.put("-", 1);
        this.priority.put("*", 2);
        this.priority.put("/", 2);
    }

    //得到操作符的优先级
    public int getPriority(String operator) {
        //这里括号进行特殊处理
        if (operator.matches("[()]")) {
            return -1;
        } else {
            return priority.get(operator);
        }
    }
   
    //判断优先级高低
    private boolean isPrior(String one, String another) {
        return getPriority(one) <= getPriority(another);
    }

    //得到栈顶元素
    private <T> T getTopEle(Stack<T> stack) {
        if (stack == null) {
            return null;
        } else {
            return stack.get(stack.size() - 1);
        }
    }

    /**
     * @param expression 算数表达式
     * @return
     * 将中缀表达式转换为后缀表达式
     */
    public Queue<String> toSuffix(String expression) {
    	Queue<String> operandQueue = new LinkedList<>();//操作数队列
        Stack<String> operatorStack = new Stack<>();//操作符堆栈
        operatorStack.push("#");

        String current = "";
        String operator = "";
        String number = "";
        int start = 0;
        int end = 0;
        for (int i = 0; i < expression.length(); i++) {
            current = String.valueOf(expression.charAt(i));
            // 如果是数字,末尾标记end++
            if (current.matches("[\\d\\.]")) {
                // 如果数字是最后一个字符,直接将其入队列
                if (i == expression.length() - 1) {
                    operandQueue.add(current);
                } else {
                    end++;
                }
            } else {
                // 如果是字符
                // 如果是左括号,将其入栈
                if (current.equals("(")) {
                    operatorStack.push(current);
                } else {
                    // 如果是右括号和其它运算符,先将前面的数字入队列
                    number = expression.substring(start, end);
                    if (!number.isEmpty()) {
                    	operandQueue.add(number);
					}
                    // 如果是右括号,执行出栈操作,并将出栈的元素入队列,直到弹出栈的是左括号,左括号直接出栈
                    if (current.equals(")")) {
                        while (!getTopEle(operatorStack).equals("(")) {
                            operandQueue.add(operatorStack.pop());
                        }
                        operatorStack.pop();
                    } else {
                        // 如果是其它运算符,弹出所有优先级大于或者等于该运算符的栈顶元素,然后将该运算符入栈
                        operator = current;
                        while (isPrior(operator, getTopEle(operatorStack))) {
                            operandQueue.add(operatorStack.pop());
                        }
                        operatorStack.push(operator);
                    }
                }
                // 将指向数字的首尾指针加1
                start = end = i + 1;
            }
        }

        for (int i = operatorStack.size() - 1; i > 0; i--) {
            operandQueue.add(operatorStack.pop());
        }
        
        return operandQueue;
    }
    

    /**
     * @param expression 算数表达式
     * @return
     * 得到表达式的结果
     */
    public double getResult(String expression) {
    	Queue<String> suffixQueue = toSuffix(expression);
    	Stack<String> suffixStack = new Stack<String>();
    	String current = "";
    	double frontOperand;
    	double backOperand;
    	double value = 0;
    	for (int i = suffixQueue.size(); i > 0; i--) {
    		current = suffixQueue.poll();
    		//如果是数字,入栈
			if (current.matches("^\\d+(\\.\\d+)*$")) {
				suffixStack.push(current);
			} else {
				backOperand = Double.valueOf(suffixStack.pop());
				frontOperand = Double.valueOf(suffixStack.pop());
				if (current.equals("+")) {
					value = frontOperand + backOperand;
				} else if (current.equals("-")) {
					value = frontOperand - backOperand;
				} else if (current.equals("*")) {
					value = frontOperand * backOperand;
				} else if (current.equals("/")) {
					try {
						value = frontOperand / backOperand;
					} catch (Exception e) {
						return 0;
					}
				}
				suffixStack.push(String.valueOf(value));
			}
		}
    	String result = suffixStack.get(0);
    	return Double.valueOf(result);
    }

}

单元测试代码如下:

package cn.tzy.calculator;

import java.util.Queue;

import org.junit.Assert;
import org.junit.Test;

public class CalculatorTest {

	private Calculator calculator;
	private String infix;

	public CalculatorTest() {
		this.calculator = new Calculator();
		this.infix = "(8+9*10)-4/2+3";
	}

	@Test
	public void testToSuffix() {
		Queue<String> suffix = calculator.toSuffix(infix);
		for (int i = suffix.size(); i > 0; i--) {
			System.out.print("(" + suffix.poll() + ")");
		}
	}
	
	@Test
	public void testGetResult() {
		double result = calculator.getResult(infix);
		Assert.assertEquals(result, 99, 0);
	}
}
本文参与 腾讯云自媒体分享计划,分享自作者个人站点/博客。
原始发表:2015年02月10日,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档