用java实现栈,并且利用栈的特性计算中缀表达式(待加入括号)

本文介绍了如何使用Java实现栈的数据结构,并详细阐述了基于栈的中缀表达式计算算法。通过ArrayStack、NumStack和OperStack三个类来分别处理栈的基本操作、数字操作和符号操作,最后在CalculatorDemo主方法中完成中缀表达式的计算过程。

什么是栈?

简单讲就是先进后出,吃进去吐出来,可以用链表实现,也可以用数组实现

我们来看看jdk1.8中栈的源码

public
class Stack<E> extends Vector<E> {
    /**
     * Creates an empty Stack.
     */
    public Stack() {
    }

 
    public E push(E item) {
        addElement(item);

        return item;
    }

  
    public synchronized E pop() {
        E       obj;
        int     len = size();

        obj = peek();
        removeElementAt(len - 1);

        return obj;
    }

    
    public synchronized E peek() {
        int     len = size();

        if (len == 0)
            throw new EmptyStackException();
        return elementAt(len - 1);
    }

   
    public boolean empty() {
        return size() == 0;
    }

    
    public synchronized int search(Object o) {
        int i = lastIndexOf(o);

        if (i >= 0) {
            return size() - i;
        }
        return -1;
    }

    /** use serialVersionUID from JDK 1.0.2 for interoperability */
    private static final long serialVersionUID = 1224463164541339165L;
}

可以看出,它是继承Vertor,并且封装了自己特有的的几个方法

自定义栈实现中缀表达式计算

一共包含四个类,第一个是栈的操作,第二第三个是和操作相关

大概的算法思想

0.创建数字栈和符号栈
1.创建index用来循环扫描expression
2.如果E[index]是数字,直接入数栈
3.若E[index]是符号,
    1)如果当前的符号栈为空,入符号栈
    2)如果当前符号栈不为空,进行比较
        1)如果当前操作符优先级《=OperStack栈顶的操作符
           就从numStack中pop两个数,从符号栈中pop一个operator,进行运算,将运算结果进numStack,再把当前operator进operStack。
        2)如果 > operStack[top],直接入operStack.
4.如果栈中最后只有一个数字,那就是结果

ArrayStack .java 包含了栈的相关操作


/**
 * @author Administrator
 * @date 2019/6/14/14:05
 */

public class ArrayStack {
    /**
     * 栈的最大容量
     */
    private int maxSize;
    /**
     * 用数组模拟栈
     */
    private int[] stack;
    /**
     * 栈顶指针,初始位置为-1
     */
    int top = -1;

    public ArrayStack(int maxSize) {
        this.maxSize = maxSize;
        stack = new int[maxSize];
    }

    /**
     * 判断是否栈满
     * @return 满/true否则false
     */
    public boolean isFull(){
        return top == maxSize-1;
    }

    /**
     * 判断是否栈空
     * @return 空/true否则false
     */
    public boolean isEmpty(){
        return top == -1;
    }

    /**
     * 入栈
     * 栈顶指针+1
     * @param Node
     */
    public void push(int Node){
        //判断是否栈满,满了则不能入栈
        if (isFull()){
            System.out.println("栈满");
            return;
        }
        //入栈操作
        top++ ;
        stack[top] = Node;
    }

    /**
     * 出栈
     * 栈顶指针减1
     * @return
     */
    public synchronized int pop(){
        //定义返回的数据
        int obj;
        //判断是否栈空
        if (isEmpty()){
            System.out.println("栈空");
            throw new RuntimeException("栈空!");
        }
        //出栈操作
        obj =  stack[top];
        top--;

        return  obj;
    }

    /**
     * 显示栈里的数据
     */
    public void list(){
        if (isEmpty()){
            System.out.println("栈空,不能显示");
            return;
        }
        //循环显示
        for (int i = top; i >= 0 ; i--) {
            System.out.printf("stack[%d] = %d\n",i,stack[i]);
        }
    }

    public  int peek() {
        return  stack[top];
    }
}

NumStack.java 数字栈继承ArrayStack

/**
 * 数字栈
 * 继承ArrayStack
 * 1 计算结果
 * @author Administrator
 * @date 2019/6/14/14:06
 */

public class NumStack<T extends Integer> extends ArrayStack{
    //
    public NumStack(int maxSize) {
        super(maxSize);
    }

    /**
     * 计算每一次弹出的运算结果
     * @param num1 先弹出的数字
     * @param num2 后弹出的数字
     * @param operator 运算符
     */
    public int calculate(int num1 , int num2 , int operator){
        //返回的计算结果
        int res = 0;
        //根据操作符类型进行运算
        switch (operator){
            case '+':
                res = num1 + num2;
                break;
            case '*':
                res = num1 * num2;
                break;
            case '/':
                res = num2 / num1;
                break;
            case '-':
                res = num2 - num1;
                break;
            default:
                    break;
        }
        return res;
    }

}

OperStack.java 符号栈继承 ArrayStack

/**
 * 运算符栈
 * @author Administrator
 * @date 2019/6/14/14:06
 */

public class OperStack<T extends Integer> extends ArrayStack {
    //必须实现父类的有参构造
    public OperStack(int maxSize) {
        super(maxSize);
    }

    /**
     * 判断是否是运算符
     * @param oper
     * @return 是/true
     */
    public boolean isOper(char oper){
        return oper=='+' || oper=='-' || oper=='*' ||oper=='/';
    }

    /**
     * 判断运算符优先级,数字大的优先级高
     * @param operator
     * @return
     */
    public int priority(int operator){
        if (operator=='*' || operator=='/'){
            return 1;
        }
        else if (operator=='+' || operator=='-'){
            return 0;
        }
        else {
            return -1;
        }
    }

}

CalculatorDemo .java 计算中缀表达式(主方法)


/**
 * 计算中缀表达式
 * @author Administrator
 * @date 2019/6/14/14:36
 */

public class CalculatorDemo {
    /**
     * 符号栈
     */
    public static OperStack<Integer> operStack = new OperStack(10);
    /**
     * 数字栈
     */
    public static NumStack<Integer> numStack = new NumStack<>(10);

    /**
     * 主方法
     * @param args
     */
    public static void main(String[] args) {
        //需要计算的表达式,仅限整数
        String expression = "5+8*40/10";
        //表示当前的扫描的字符
        char ch ;
        //当前字符的下标
        int index = 0;
        //用于数字拼接
        String nums = "";
        //循环扫描expression
        while (true){
            //当前的字符
            ch = expression.substring(index,index+1).charAt(0);
            //如果是运算符
            if (operStack.isOper(ch)){
                //1)如果当前的符号栈为空,入符号栈果
                if (operStack.isEmpty()){
                    operStack.push(ch);
                }
                //2)如果当前符号栈不为空,进行比较
                else {
                    //1)如果当前操作符优先级《=OperStack栈顶的操作符
                    //就从numStack中pop两个数,从符号栈中pop一个operator,进行运算,将运算结果进numStack,再把当前operator进operStack。
                    if (operStack.priority(ch) <= operStack.priority(operStack.peek())){
                        int num1 = numStack.pop();
                        int num2 = numStack.pop();
                        int tempOper = operStack.pop();
                        int res = numStack.calculate(num1,num2,tempOper);
                        numStack.push(res);
                        operStack.push(ch);
                    }
                    // 2)如果 > operStack[top],直接入operStack.
                    else{
                        operStack.push(ch);
                    }
                }
            }
            //是数字,数字入数栈
            else {
                //多位数的数字我们不能直接进栈,而是需要字符串拼接
               nums +=ch;
              //index已经是最后一位了,直接入栈
                if (index == expression.length()-1){
                    numStack.push(Integer.parseInt(nums));
                }
                else {
                    //如果下一个是运算符,才push
                    if (operStack.isOper(expression.substring(index+1,index+2).charAt(0))){
                        //进栈
                        numStack.push(Integer.parseInt(nums));
                        //!!!置空,重要
                        nums = "";
                    }
                }


            }
            //要再前面,否者会由数组下标越界异常
            index ++;
            //当扫描到最后一个字符的后一个时结束循环
            if (index >= expression.length()){
                break;
            }

        }//while

        //当表达式扫描完毕
        while (true){
            if (operStack.isEmpty()){
                break;
            }
            int num1 = numStack.pop();
            int num2 = numStack.pop();
            int tempOper = operStack.pop();
            int res = numStack.calculate(num1,num2,tempOper);
            numStack.push(res);
        }
        //将最后结果出栈
        int result = numStack.pop();
        System.out.printf("表达式:%s = %d",expression,result);
    }//main

}

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值