java利用栈实现表达式求值

package Stack;
/**
 * 利用栈实现表达式的计算
 * @Author: HML
 * @Date: 2021/7/1  下午 3:31
 * @Version 1.0
 */
public class StackDemo2 {

    public static void main(String[] args){

        String express = "70*2*2-5+1-5+3-4";
        //创建两个栈,一个数栈,一个符号栈
        ArrayStack numStack = new ArrayStack(10);
        ArrayStack charStack = new ArrayStack(10);

        int index = 0;//遍历所需索引
        int num1 = 0;
        int num2 = 0;
        int oper = 0;
        int res = 0;
        char ch;//将每次拿到的符号放在ch中
        String keepNum = "";//用于拼接数字。这里会涉及到多位数
        //遍历输入的字符串
        while (true){
            //依次取到字符串的每个字符
            ch = express.substring(index,index+1).charAt(0);
            System.out.println(ch);
            //判断ch是什么
            if(charStack.isOper(ch)){
               //判断符号栈中是否有符号在栈
               if (!charStack.isEmpty()){
                   //如果栈中有符号,则需要比较栈中的操作符的优先级与当前优先级,若当前操作符的优先级小于或等于栈中的,则需从数栈中pop出两个数值,将符号栈中的符号出栈进行计算
                   if (charStack.priority(ch) <= charStack.priority(charStack.peek())){
                       num1 = numStack.pop();
                       num2 = numStack.pop();
                       oper = charStack.pop();
                       res = numStack.calRes(num1,num2,oper);
                       //将res从新如数栈
                       numStack.push(res);
                       //将当前的符号入符号栈
                       charStack.push(ch);
                   }else{
                       //若当前的符号的优先级要高于栈中的优先级,则直接入栈
                       charStack.push(ch);
                   }
               }else{
                   //前面判断栈不为空,这里就是栈空,直接将数据人放入栈中
                   charStack.push(ch);
               }
            }else{
                //这里前面是判断是字符,这里else就是数字了
                //数字怎么处理??直接入栈即可
                //numStack.push(ch-48);这里是ascii表示,48是0,这里用ch-48恰好就是其自己的10进制值
                //numStack.push(ch);

                //分析处理多位数怎么办??
                /**
                 * 1. 不能发现一个数就直接入栈
                 * 2. 判断表达式的后一位是否是符号,若是符号,则将数字入栈,否则还得接着扫描
                 * 3. 需定义一个变量用于字符串的拼接
                 */
                keepNum += ch;
                if (index == express.length()-1){
                    numStack.push(Integer.parseInt(keepNum));
                }else{
                    //判断后一位是否为数字
                    if(charStack.isOper(express.substring(index+1,index+2).charAt(0))){
                        //若最后一位是操作符,那好,则直接入栈
                        numStack.push(Integer.parseInt(keepNum));
                        //每次一判断完一串数字,就将keepnum清空,否则,会导致keepnum中保存原来的值
                        keepNum = "";
                    }
                }
            }
            //往后进行遍历
            index ++;
            if (index >= express.length()){
                break;
            }
        }
        //遍历完毕后,从数栈和符号栈取出元素进行运算即可,并将数栈中的元素返回
        //如果符号栈为空,则表示最后的结果就是数栈中的值
        while (true){
            if(charStack.isEmpty()){
                break;
            }
            num1 = numStack.pop();
            num2 = numStack.pop();
            oper = charStack.pop();
            res = numStack.calRes(num1,num2,oper);
            numStack.push(res);
        }
       //将数栈最后的数出栈
        int res2 = numStack.pop();
        System.out.printf("表达式的值 %s=%d",express,res2);

    }

//    public static void main(String[] args) {
//        ArrayStack arrayStack = new ArrayStack(10);
//        System.out.println(arrayStack.calRes(1, 3, '/'));
//    }
}
//创建一个栈
class ArrayStack{

    private int maxSize;//站的大小
    private int[] stack;//数组栈
    private int top = -1;//表示栈顶


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

    //增加一个方法,返回当前栈顶的值
    public int peek(){
        return stack[top];
    }

    //栈满
    public boolean isFull(){
       return top == maxSize - 1;
    }
    //栈空
    public boolean isEmpty(){
        return top == -1;
    }

    //入栈
    public void push(int value){
        //判断栈是否为满
        if (isFull()){
            System.out.println("栈满,无法插入");
            return;
        }
        top ++;
        stack[top] = value;
    }

    public int pop(){
        //判断栈是否空,这里因为要涉及到取数据,故这里会有异常
        if (isEmpty()){
            throw new RuntimeException("栈空,元素无法出栈~~~");
        }
        int value = stack[top];
        top--;
        return value;
    }
    //遍历栈
    public void list(){
        //判断栈是否为空
        if (isEmpty()){
            System.out.println("无法遍历,栈中没有元素出栈");
            return;
        }
        for (int i=top;i>=0;i--){
            System.out.printf("stack[%d]=%d",i,stack[i]);
        }
    }

    //优先级的定位
    public int priority(int oper){
        if (oper == '*' || oper == '/'){
            return 1;
        }
        else if (oper == '+' || oper == '-'){
            return 0;
        }else{
            return -1;
        }
    }

    //判断是否为一个运算符
    public boolean isOper(char ch){
        return ch == '*' || ch == '/' || ch == '+' || ch == '-';
    }
    //计算
    public int calRes(int num1,int num2,int oper){
        int res=0;//用来存放计算的结果

        switch (oper){
            case '+':
               res =  num1+num2;
               break;
            case '-':
                res = num2 - num1;
                break;
            case '*':
                res = num1 * num2;
                break;
            case '/':
                res = num2 / num1;
                break;
            default:
                break;
        }
        return res;
    }
}

  • 1
    点赞
  • 19
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 1
    评论
表达式是我们常见的数学表达式的一种表示方法,例如"3 + 4 * 2 - 5"。但是在计算机表达式并不方便进行计算,因此我们需要将其转换为后缀表达式(逆波兰表达式)来求值。 我们可以使用来处理表达式求值。具体的方法如下: 1. 创建一个空和一个空列表来存储间和最终结果。 2. 遍历表达式的每一个字符。 3. 如果遇到操作数(数字),直接将其添加到列表。 4. 如果遇到运算符,分以下几种情况处理: - 如果为空,或者顶为左括号,则直接将运算符入。 - 如果顶为运算符,并且顶运算符的优先级大于当前运算符,则将顶运算符出,并加入到列表,然后继续比较当前运算符与新的顶运算符的优先级。 - 最后将当前运算符入。 5. 如果遇到左括号,直接将其入。 6. 如果遇到右括号,则将的运算符依次出,加入到列表,直到遇到左括号为止。 7. 遍历完表达式后,将剩余的运算符依次出,加入到列表。 8. 最后,遍历列表的元素进行计算。如果遇到操作数,直接入;如果遇到运算符,从弹出两个操作数,并进行相应的运算,然后将运算结果重新入。 9. 最终,只剩下一个数,即为表达式求值结果。 通过上述方法,我们可以实现表达式求值,而且时间复杂度为O(n),其n为表达式的长度。这种方法利用的特性,在处理运算符时将其按照优先级依次出,确保了运算的正确顺序,并得到了最终的结果。
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

无敌小胖子.com

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值