栈之上节习题--多位数字的表达式计算

用栈来实现多位数的表达式计算

代码实现

我的想法:

  1. 用两个数组来装,把String直接用正则表达式划分为对应的数组
  2. 然后转成整型代入计算

我的代码:

package stack;

public class Calculater {
    public static void main(String[] args) {
        String expression = "7235*1235+3235+2235/1235-2*";
        //创建两个栈,分别为数栈和符号栈
        //没有必要像上次一样创建两个类,在分别对应类创建对应的栈
        NSStack numStack = new NSStack(20);
        NSStack operStack = new NSStack(20);
        String[] str = null;
        str = expression.split("[*/+-]");
        System.out.println(str[1]);
        System.out.println(str.length);
        //定义相关变量
        int index = 0;
        //扫描索引
        char ch = ' ';
        //用于承接扫描的单个字符
        int num1 = 0;
        int num2 = 0;
        //int oper = 0;
        //为什么定义符号位0,还为int型
        int res = 0;//结果
        int i = 0;
        //用来判断是否输入相应的数字
        while (true){

            //ch = expression.substring(index,index + 1).charAt(0);
            //没有必要加上substring的方法生成一个子字符串
            ch = expression.charAt(index);
            //判断ch是什么

            if(operStack.isOper(ch)){
                //问题来了,如果是多位数,他会出现一位数加一下的情况
                //如何把多位数看作是一个数扫描的时候
                numStack.push(Integer.parseInt(str[i]));
                System.out.println(str[i]);
                i++;
                //如果是运算符,总共是三中情况
                //情况一;符号栈为空,直接加入
                if(operStack.isEmpty()){
                    operStack.push(ch);
                    //好吧!我忘记了,低转高是自动的,不需要类型强转
                }else if(operStack.priority(operStack.top()) < operStack.priority(ch) ){
                    //情况二:符号栈不为空,并且输入的运算符优先级比符号栈里面的优先级要高
                    operStack.push(ch);
                }else{
                    //情况三:符号栈不为空,并且输入的运算符优先级比符号栈里面的低
                    num1 = numStack.pop();
                    num2 = numStack.pop();
                    res = numStack.cal(num1,num2,operStack.pop());
                    operStack.push(ch);
                    //符号入栈,别忘记
                    numStack.push(res);
                    //结果入栈,这个老是忘记
                }

            }

            //放哪?放在判断语句之前,已经是倒数第二个,那就最后一个少判断一次
            //放在判断语句之后,倒数第二个,最后一个执行完了才会再继续运行
            //循环完毕的条件
            if(index == (expression.length() - 1)){
                break;
            }
            index ++;

        }
        //检索完毕开始运行站内的符号和数字
        while (true){
            if(operStack.isEmpty()){
                break;
            }
            //判断为空没必要再用top指针,直接有对应的方法
            num1 = numStack.pop();
            num2 = numStack.pop();
            res = operStack.cal(num1,num2,operStack.pop());
            numStack.push(res);
        }
        System.out.println(expression + "  " +  numStack.pop());

    }
}
class NSStack{
    int maxSize;
    int top = -1;
    int[] ss;

    public NSStack(int maxSize) {
        this.maxSize = maxSize;
        ss = new int[maxSize];
    }
    public boolean isEmpty(){
        return top == -1;
    }
    public boolean isFull(){
        return top == (maxSize - 1);
    }
    public void push(int m){
        if(isFull()){
            return;
        }
        top ++;
        ss[top] = m;
    }
    public int pop(){
        if(isEmpty()){
            return 0;
        }
        int temp = ss[top];
        top --;
        return temp;
    }
    public int top(){
        return ss[top];
    }
    //优先级用数字表示,数字越大,优先级越高
    public int priority(int oper){
        if(oper == '*' || oper == '/'){
            //这里真心没看懂,我知道是转换成对应的unicode码
            //但是你在走索的时候就是用的char,为啥在判定优先级的时候
            //不用,要去用int.很麻烦,虽然确实也可以
            return 1;
        }else if(oper == '+' || oper == '-'){
            return 0;
        }else{
            return -1;
        }
    }
    //判断是不是一个运算符
    public boolean isOper(char val){
        return val == '*' || val == '-' || val == '+' || val == '/'||val == '=';
    }
    //难道还有等号?应该是吧!没有!他是一个一个string.charAt()
    //来遍历表达式,获取符号,比我想得简单
    //计算方法
    public int cal(int num1 ,int num2,int oper){
        int res = 0;
        switch (oper){
            case '+':
                res = num1 + num2;
                System.out.println(num1  + "+" + num2 + "=" + res);
                break;
            case '-':
                res = num2 - num1;
                System.out.println(num2  + "-" + num1 + "=" + res);
                break;
            case '*':
                res = num1 * num2;
                System.out.println(num1  + "*" + num2 + "="+ res);
                break;
            case '/':
                res = num2 / num1;
                System.out.println(num2  + "/" + num1 + "="+ res);
                break;
            default:
                break;
        }
        return res;
        //运算注意顺序,加法和乘法是没有的,减法和除法是有的
    }

}

问题:

  1. 因为数字的进栈和出栈是根据符号而来的,将字符串拆分成数字直接输入,两个问题面对。
  • 如果原来的方式扫描,你如何做到扫瞄完完整的数字在添加而不是扫描到一个就添加一个。
  • 换成我写的方式,数字和符号的添加方式就变了,不再是来一个数字,添加一下,而是有一个符号就添加一下,最后一个数字不能进栈了。想用一个等号链接,但是好像没找到相应的正则表达式
    答:去看看下面的,第一个问题不是问题,判断是否输入有两种方式,一种是遇到了符号,一种是数组的索引到头了。不是为空!话说就算为空,那也是默认值,那你也可以算出来,char的默认值是什么?/00000

教程代码:

package stack;

public class Calculater {
    public static void main(String[] args) {
        String expression = "7235*1235+3235+2235/1235-2*";
        //创建两个栈,分别为数栈和符号栈
        //没有必要像上次一样创建两个类,在分别对应类创建对应的栈
        NSStack numStack = new NSStack(20);
        NSStack operStack = new NSStack(20);
        String[] str = null;
        int index = 0;
        //扫描索引
        char ch = ' ';
        //用于承接扫描的单个字符
        int num1 = 0;
        int num2 = 0;
        //int oper = 0;
        //为什么定义符号位0,还为int型
        int res = 0;//结果
        String keepNum = "";
        //用于拼接多位数
        while (true){

            //ch = expression.substring(index,index + 1).charAt(0);
            //没有必要加上substring的方法生成一个子字符串
            ch = expression.charAt(index);
            //判断ch是什么
            if(operStack.isOper(ch)){
                //如果是运算符,总共是三中情况
                //情况一;符号栈为空,直接加入
                if(operStack.isEmpty()){
                    operStack.push(ch);
                    //好吧!我忘记了,低转高是自动的,不需要类型强转
                }else if(operStack.priority(operStack.top()) < operStack.priority(ch) ){
                    //情况二:符号栈不为空,并且输入的运算符优先级比符号栈里面的优先级要高
                    operStack.push(ch);
                }else{
                    //情况三:符号栈不为空,并且输入的运算符优先级比符号栈里面的低
                    num1 = numStack.pop();
                    num2 = numStack.pop();
                    res = numStack.cal(num1,num2,operStack.pop());
                    operStack.push(ch);
                    //符号入栈,别忘记
                    numStack.push(res);
                    //结果入栈,这个老是忘记
                }

            }else{
                keepNum += ch;
                if(index == expression.length() - 1){
                    numStack.push(Integer.parseInt(keepNum));
                }else{
                    //判断下一位是不是数字,如果是数字
                    // 就继续扫描,如果是运算符就入栈
                    //数以这里是看后一位,而不改变index的值
                    if(operStack.isOper(expression.charAt(index + 1))){
                        numStack.push(Integer.parseInt(keepNum));
                        //重要,记得清空keepNum
                        keepNum = "";
                    }
                }
            }

            //放哪?放在判断语句之前,已经是倒数第二个,那就最后一个少判断一次
            //放在判断语句之后,倒数第二个,最后一个执行完了才会再继续运行
            //循环完毕的条件
            if(index == (expression.length() - 1)){
                break;
            }
            index ++;

        }
        //检索完毕开始运行站内的符号和数字
        while (true){
            if(operStack.isEmpty()){
                break;
            }
            //判断为空没必要再用top指针,直接有对应的方法
            num1 = numStack.pop();
            num2 = numStack.pop();
            res = operStack.cal(num1,num2,operStack.pop());
            numStack.push(res);
        }
        System.out.println(expression + "  " +  numStack.pop());

    }
}
class NSStack{
    int maxSize;
    int top = -1;
    int[] ss;

    public NSStack(int maxSize) {
        this.maxSize = maxSize;
        ss = new int[maxSize];
    }
    public boolean isEmpty(){
        return top == -1;
    }
    public boolean isFull(){
        return top == (maxSize - 1);
    }
    public void push(int m){
        if(isFull()){
            return;
        }
        top ++;
        ss[top] = m;
    }
    public int pop(){
        if(isEmpty()){
            return 0;
        }
        int temp = ss[top];
        top --;
        return temp;
    }
    public int top(){
        return ss[top];
    }
    //优先级用数字表示,数字越大,优先级越高
    public int priority(int oper){
        if(oper == '*' || oper == '/'){
            //这里真心没看懂,我知道是转换成对应的unicode码
            //但是你在走索的时候就是用的char,为啥在判定优先级的时候
            //不用,要去用int.很麻烦,虽然确实也可以
            return 1;
        }else if(oper == '+' || oper == '-'){
            return 0;
        }else{
            return -1;
        }
    }
    //判断是不是一个运算符
    public boolean isOper(char val){
        return val == '*' || val == '-' || val == '+' || val == '/'||val == '=';
    }
    //难道还有等号?应该是吧!没有!他是一个一个string.charAt()
    //来遍历表达式,获取符号,比我想得简单
    //计算方法
    public int cal(int num1 ,int num2,int oper){
        int res = 0;
        switch (oper){
            case '+':
                res = num1 + num2;
                System.out.println(num1  + "+" + num2 + "=" + res);
                break;
            case '-':
                res = num2 - num1;
                System.out.println(num2  + "-" + num1 + "=" + res);
                break;
            case '*':
                res = num1 * num2;
                System.out.println(num1  + "*" + num2 + "="+ res);
                break;
            case '/':
                res = num2 / num1;
                System.out.println(num2  + "/" + num1 + "="+ res);
                break;
            default:
                break;
        }
        return res;
        //运算注意顺序,加法和乘法是没有的,减法和除法是有的
    }

}

总结对比:

  1. 教程思路,如果不断扫描,如果下一个数是数字,那就再字符串之后拼接。如果不是,那就有两种情况,一种是遇到符号,一种是到达栈的末尾,都是入栈,然后清空字符串

是什么限制了我的思维能力?练得少了!!

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值