数组栈实现简单算数计算

import java.util.HashMap;
import java.util.Map;

public class SimpleArithmeticTest {

    public static void main(String[] args) {

        // 设置优先级
        Map<String, Integer> priorityMap = new HashMap<>();
        priorityMap.put("+", 1);
        priorityMap.put("-", 1);
        priorityMap.put("*", 2);
        priorityMap.put("/", 2);

        // 数字与符号之间需使用空格隔开
        String str01 = "1 + 3 * 4 - 2 + 12 / 3"; // 15
        String str02 = "1 * 5 - 3 + 6 / 2 + 1 + 1"; // 7
        String str03 = "1 + 3 - 2 + 15 / 3 - 4 * 1"; // 3
        System.out.println(calculate(priorityMap, str01));
        System.out.println(calculate(priorityMap, str02));
        System.out.println(calculate(priorityMap, str03));
    }

    private static Integer calculate(Map<String, Integer> priorityMap, String str) {

        String[] s = str.split(" ");
        // 声明两个栈,一个用来存数字,一个用来存符号
        MyArrayStack<Integer> numberStack = new MyArrayStack<>(str.length());
        MyArrayStack<String> symbolStack = new MyArrayStack<>(str.length());
        for (int i = 0; i < s.length; i++) {
            if (i % 2 == 0) { // 是数字位
                if (i == s.length - 1) { // 最后一位数字
                    // 数字栈里只可能存一个数字或者两个数字
                    // 符号栈里只可能存一个符号或者两个符号,如果存在两个符号,栈顶的符号优先级肯定比栈底的高,要优先计算
                    int nowNumber = Integer.parseInt(s[i]);
                    int result = 0;
                    while(numberStack.get() != null){ // 其实最多只会遍历两次
                        // 将栈顶数字与当前数字进行计算
                        result = getReult(nowNumber, numberStack.pop(), symbolStack.pop()); // 当前值为算术式的右侧数字,从数字栈出栈的数字为算数式左侧数字
                        nowNumber = result; // 第二次就要拿第一次计算的结果作为下一次计算的当前值
                    }
                    return result;
                }
                // 不是处理最后一位数字的时候执行的入栈操作
                numberStack.push(Integer.parseInt(s[i]));
            } else { // 是符号位
                String nowSymbol = s[i]; // 当前符号
                if (!symbolStack.isEmpty()) {
                    // 将当前的符号与已存入的符号的优先级进行比对
                    String lastSymbol = symbolStack.get(); // 栈顶符号,使用get,不是用pop,是为了防止不满足如下的情况,栈顶也出栈
                    // 如果当前的符号优先级小于或者等于栈顶符号,则需要取出数字栈中的栈顶两位进行运算
                    while (priorityMap.get(nowSymbol) <= priorityMap.get(lastSymbol)) {
                        symbolStack.pop(); // 满足当前条件的话,栈顶元素需出栈
                        int result = getReult(numberStack.pop(), numberStack.pop(), lastSymbol); // 先出栈的数字为算术式的右侧数字,第二次出栈的数字为算数式左侧数字
                        // 将运算的result再次入到数字栈,将当前符号入到符号栈中
                        numberStack.push(result);
                        if (null != symbolStack.get()) { // 栈顶符号,使用get,不是用pop,是为了防止不满足优先级的时候,栈顶也出栈
                            lastSymbol = symbolStack.get();
                        } else {
                            break;
                        }
                    }
                }
                // 1.字符栈还为空
                // 2.如果当前的符号优先级大于栈顶符号,则将符号入符号栈栈顶,下一步就是将数字入数字栈顶
                symbolStack.push(s[i]);
            }
        }
        return numberStack.pop();
    }

    /**
     * 根据符号进行运算
     * @param frontNumber
     * @param behindNumber
     * @param symbol
     * @return
     */
    private static int getReult(int behindNumber, int frontNumber, String symbol) {
        if ("+".equals(symbol)){
            return frontNumber + behindNumber;
        } else if("-".equals(symbol)){
            return frontNumber - behindNumber;
        } else if("*".equals(symbol)){
            return frontNumber * behindNumber;
        } else if("/".equals(symbol)){
            return frontNumber / behindNumber;
        } else {
            return 999999999;
        }

    }

}

/**
 * 使用数组实现的一个栈
 *
 * @param <T>
 */
class MyArrayStack<T> {

    private T[] arrayStack;
    private int stackSize = 0; // 当前栈中已存的数据量

    /**
     * 构造函数,参数值为初始化数组的长度
     *
     * @param length
     */
    public MyArrayStack(int length) {
        arrayStack = (T[]) new Object[length];
    }

    /**
     * 入栈一个元素
     * 如果stackSize大于length的0.75,则扩大二倍,
     *
     * @param t
     */
    public void push(T t) {
        if (stackSize > arrayStack.length * 0.75 - 1) {
            T[] newArrayStack = (T[]) new Object[arrayStack.length * 2];
            System.arraycopy(arrayStack, 0, newArrayStack, 0, arrayStack.length - 1);
            arrayStack = newArrayStack;
        }
        arrayStack[stackSize++] = t;
    }

    /**
     * 出栈一个元素
     */
    public T pop() {
        if (0 == stackSize) {
            return null;
        }
        T t = arrayStack[--stackSize];
        arrayStack[stackSize] = null;
        return t;

    }

    /**
     * 只用于查询栈顶元素值,不出栈
     */
    public T get() {
        if (0 == stackSize) {
            return null;
        }
        T t = arrayStack[stackSize - 1]; // 不使用--stackSize,是为了保证不改变stackSize大小
        return t;

    }

    /**
     * 当前栈是否为空
     *
     * @return
     */
    public boolean isEmpty() {
        return 0 == stackSize;
    }
}

结果:

15
7
3

 

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值