数据结构与算法--利用栈结构实现计算器

对于计算一个表达式1+2*3/4,该如何处理,如何处理不同的操作符的优先级

栈的特点和队列相反,先进后出.
可以把队列类比于一个两头通透的通道,一端进入另一端拿出.
而栈是一个一头封闭的通道,从一端压入一端拿出.

下面是基于数组的实现,

import java.util.List;
/**
 * @Project: StackCalculator
 * @Description: 一个简单的基于数组的栈实现
 * @Creator: sunwei
 * @CreatDate: 2020/7/4
 * @Modifier:
 */
public class ArrayStack<T> {
    //栈顶指针
    private int top = -1;
    //数据
    private Object[] data;
    //栈大小
    private int maxSize;

    /**
     * <p>Your Description about this Method</p>
     * @param maxSize 栈大小
     * @version 0.1.0
     * @return
     * @author SunWei
     * @date 2020/7/4 16:56
     * @since 0.1.0
    */
    public ArrayStack(int maxSize) {
        this.maxSize = maxSize;
        data = new Object[maxSize];
        top = -1;
    }

    /**
     * <p>入栈</p>
     * @param obj 要压入的数据
     * @version 0.1.0
     * @return void
     * @author SunWei
     * @date 2020/7/4 16:56
     * @since 0.1.0
    */
    public void push(T obj) throws Exception {
        if (isFull()) {
            throw new Exception("stack is full");
        }
        top++;
        data[top] = obj;
    }

    /**
     * <p>出栈</p>
     * @param
     * @version 0.1.0
     * @return T
     * @author SunWei
     * @date 2020/7/4 16:57
     * @since 0.1.0
    */
    public T pop() throws Exception {
        if (isEmpty()) {
            throw new Exception("stack is empty");
        }
        T value = (T)data[top--];
        return value;
    }

    /**
     * <p>判断是否为空</p>
     * @param
     * @version 0.1.0
     * @return boolean
     * @author SunWei
     * @date 2020/7/4 16:57
     * @since 0.1.0
    */
    public boolean isEmpty() {
        return top == -1;
    }

    /**
     * <p>判断是否已满</p>
     * @param
     * @version 0.1.0
     * @return boolean
     * @author SunWei
     * @date 2020/7/4 16:57
     * @since 0.1.0
    */
    public boolean isFull() {
        return top == maxSize - 1;
    }

    /**
     * <p>获取栈的长度</p>
     * @param
     * @version 0.1.0
     * @return int
     * @author SunWei
     * @date 2020/7/4 16:57
     * @since 0.1.0
    */
    public int length() {
        return top + 1;
    }

    /**
     * <p>获取栈顶元素</p>
     * @param
     * @version 0.1.0
     * @return T
     * @author SunWei
     * @date 2020/7/4 16:58
     * @since 0.1.0
    */
    public T get() {
        return isEmpty() ? null : (T)data[top];
    }
}

利用栈的特点,实现一个带有优先级的计算器,
栈的使用场景相当多,最经典的莫过于jvm中的虚拟机栈,一个方法的调用执行对于jvm而言就是一个栈帧从入栈到出栈的过程.

import cn.wei.ds.ArrayStack;
/**
 * @Author :sunwei
 * @Description:
 * @Date create in 15:25  2020/7/4
 * @Modified by:
 */
public class StackCalculator {

    private ArrayStack<Double> numberStack;
    private ArrayStack<String> operatonStack;

    /**
     * <p>一个有优先级的简单数字运算实现</p>
     * @param equation 计算式
     * @version 0.1.0
     * @return double
     * @author SunWei
     * @date 2020/7/4 16:59
     * @since 0.1.0
    */
    public double calculate(String equation) throws Exception {
        if (equation == null || equation.length() < 1) {
            throw new Exception("equation is invalid");
        }
        numberStack = new ArrayStack(equation.length());
        operatonStack = new ArrayStack(equation.length());
        int aheadFlag = 0;
        //将算式拆分成一个一个的字符
        String[] arr = equation.split("|");
        //将夹在低优先级中的高优先级运算全部做完
        for (int i = 0; i < arr.length; i++) {

            //操作符和数字个数关系不正确,算式不正确
            if (numberStack.length() < operatonStack.length()) {
                throw new Exception("equation is invalid");
            }

            if (priority(arr[i]) == -1) {//为数字
                double value = Double.valueOf(arr[i]);
                if (aheadFlag == 0 && numberStack.get() != null) {//前一个字符也是数字,做组合
                    double numer = numberStack.pop();
                    value = numer * 10 + Double.valueOf(arr[i]);
                }
                numberStack.push(value);
                aheadFlag = 0;
            } else {
                if (aheadFlag == 1) {//前一个字符是运算符,这里抛出错误,+-10这种的暂时认为错误
                    throw new Exception("equation is invalid");
                }
                String obj = operatonStack.get();
                if (obj == null) {//目前没有运算符,直接入栈
                    operatonStack.push(arr[i]);
                } else if (priority(obj) > priority(arr[i])) {//当前运算符的优先级比上一个运算符低,需要做完上一个运算
                    String operation = operatonStack.pop();
                    double num1 = numberStack.pop();
                    double num2 = numberStack.pop();
                    double result = computer(num1, num2, operation);
                    numberStack.push(result);
                    operatonStack.push(arr[i]);
                }else{//当前运算符的优先级比上一个运算符高或者相等,直接入栈
                    operatonStack.push(arr[i]);
                }
                aheadFlag = 1;
            }
        }
        //运算优先级分割的运算,最终只留下了一个值就是最终结果
        while(true){
            if(numberStack.length()==1){
                break;
            }
            Double num1 = numberStack.pop();
            Double num2 = numberStack.pop();
            String operation = operatonStack.pop();
            double result = computer(num1, num2, operation);
            numberStack.push(result);
        }
        return numberStack.get();
    }

    /**
     * <p>判断是否为运算符</p>
     * @param oper oper
     * @version 0.1.0
     * @return boolean
     * @author SunWei
     * @date 2020/7/4 16:59
     * @since 0.1.0
    */
    public boolean isOperation(String oper) {
        return priority(oper) != -1;
    }

    /**
     * <p>获取运算符优先级</p>
     * @param oper oper
     * @version 0.1.0
     * @return int
     * @author SunWei
     * @date 2020/7/4 17:00
     * @since 0.1.0
    */
    public int priority(String oper) {
        if ("+".equals(oper) || "-".equals(oper)) {
            return 0;
        } else if ("*".equals(oper) || "/".equals(oper)) {
            return 1;
        } else {
            return -1;
        }
    }

    /**
     * <p>数字运算</p>
     * @param num1 num1
     * @param num2 num2
     * @param operation operation
     * @version 0.1.0
     * @return double
     * @author SunWei
     * @date 2020/7/4 17:00
     * @since 0.1.0
    */
    public double computer(double num1, double num2, String operation) throws Exception {
        switch (operation) {
            case "+":
                return num2 + num1;
            case "-":
                return num2 - num1;
            case "*":
                return num2 * num1;
            case "/":
                return num2 / num1;
            default:
                throw new Exception("operation is invalid");
        }
    }
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值