栈-2-栈的使用--逆波兰表达式问题解决

一.没有括号
1.通过一个索引来遍历表达式
2.如果发现是一个数字
先拼接进一个临时变量保存,
然后当前字符判断是表达式最后一个字符
直接将拼接的临时变量存进数字栈
否则, 要判断下一个是否是符号, 如果是符号, 就可以将拼接的临时变量放进数字栈, 并重置临时变量.
3.如果发现是一个符号
判断符号栈是否为空
为空, 直接进符号栈
不为空, 要判断当前的符号和符号栈栈顶符号的优先级
如果当前符号的优先级小于或等于栈顶, 就从数字栈中取两个数, 符号栈中取一个符号, 进行运算, 将运算结果入数字栈, 再将当前的符号进符号栈
如果当前符号的优先级大于栈顶, 直接进符号栈
4.当表达式扫描完毕,
判断符号栈是否为空, 为空, 数字栈中就是结果,
不为空, 从数字栈中取两个数, 符号栈中取一个符号, 进行运算, 将运算结果入数字栈.

二. 前缀表达式(波兰表达式)
前缀表法式在计算机中的计算方式
从右到左的扫描表达式
遇到数字直接压入栈中, 知道遇到运算符, 弹出栈顶的两个数, 进行运算, 然后将结果进数字栈
重复上述过程一直到最左端, 最后的值就是结果
例如(3+4)*5-6的前缀表达式就是- * + 3456

三.后缀表达式 逆波兰表达式
(3+4)*5-6
34+5 * 6-

中缀表达式转后缀表达式(逆波兰表达式)
思路
创建两个栈
s1为符号栈, s2为中间结果栈
什么情况入符号栈, 什么时候入中间结果栈呢?
当拿到的为数字时直接入s2
当拿到的为符号时
如果s1为空, 或者栈顶为(, 直接进入s1
否侧, 判断优先级, 比栈顶的优先级高, 直接进入s1,
比栈顶的优先级低或者相等, 就要先将栈顶pop出来并放进s2, 直到高于栈顶或者栈顶是(, 或者s1空了, 才进入s1.
当拿到的符号为)时, 依次将s1栈顶的符号压入s2中, 直到s1中的栈顶是(, 将这个栈顶丢弃, 此时一对()就结束了.
就这样一直扫描到中缀表达式的最后, 将s1中剩余的符号依次弹出, 然后压入s2.
s2的逆序就是后缀表达式.

中缀转后缀

import java.util.ArrayList;
import java.util.List;

public class Houzhuibiaodaoshi {

    public static void main(String[] args) {
        String zhongzhuibiaodashi = "1+((5+6)*7)-9";
        List<String> l = getList(zhongzhuibiaodashi);
        System.out.println(l); //[1, +, (, (, 5, +, 6, ), *, 7, ), -, 9]
        List<String> hou = getHou(z);
        System.out.println(hou); //[1, 5, 6, +, 7, *, +, 9, -]
    }

    //传入一个字符串, 直接转换成list的形式, 方便遍历
    public static List<String> getList(String exp){
        List<String> ls = new ArrayList<String>();
        int cur = 0;
        String duoweishu; //用于多位数的拼接
        char c;

        do{
            if((c = exp.charAt(cur)) < 48 || (c = exp.charAt(cur)) > 57){  //也就是非数字
                ls.add(""+c);
                cur++;
            }else{ //也即是数字
                duoweishu = ""; //先将多位数重置
                while(cur < exp.length() && (c = exp.charAt(cur)) >= 48 && (c = exp.charAt(cur)) <= 57){
                    duoweishu += c;
                    cur++;
                }
                ls.add(duoweishu);
            }
        }while(cur < exp.length());
        return ls;
    }
	//传入一个中缀表达式的list, 直接转换成后缀表达式
    public static List<String> getHou(List<String> zhong){
        Stack<String> s1 = new Stack<String>();
        List<String> s2 = new ArrayList<String>();
        for (String item : zhong){
            if (item.matches("\\d+")){ //如果是一个数字或者多位数数字
                s2.add(item);
            }else if (item.equals("(")){
                s1.push(item);
            }else if (item.equals(")")){
                while(!s1.peek().equals("(")){
                    s2.add(s1.pop());
                }
                s1.pop();  //一对()结束
            }else if (item.equals("+") || item.equals("-") || item.equals("*") || item.equals("/")){
                //就要判断优先级
                while(s1.size()!=0 && !s1.peek().equals("(") && ((youxianji(s1.peek())) >= (youxianji(item)))){ //这里要用到判断优先级的方法
                    s2.add(s1.pop());
                }
                s1.push(item);
            }else{
                System.out.println("操作符号错误!");
                return s2 = null;
            }
        }
        while(s1.size() != 0){
            s2.add(s1.pop());
        }
        return s2;
    }

    //判断优先级的方法
    public static int youxianji(String item){
        int add = 1;
        int jian = 1;
        int cheng = 2;
        int chu = 2;
        int result = 0;
        switch(item){
            case "+":
                result = add;
                break;
            case "-":
                result = jian;
                break;
            case "*":
                result = cheng;
                break;
            case "/":
                result = chu;
                break;
        }
        return result;
    }
}

得出后缀表达式的算法

//利用后缀表达式的list, 得到表达式的结果
    public static int getSum(List<String> hou){
        int temp = 0;
        int num1 = 0;
        int num2 = 0;
        Stack<Integer> s = new Stack<Integer>();
        for (String item : hou){
            if (item.matches("\\d+")){
                s.push(Integer.parseInt(item));
            }else{
                num1 = s.pop();
                num2 = s.pop();
                switch(item){
                    case "+":
                        temp = num2 + num1;
                        break;
                    case "-":
                        temp = num2 - num1;
                        break;
                    case "*":
                        temp = num2 * num1;
                        break;
                    case "/":
                        temp = num2 / num1;
                        break;
                }
                s.push(temp);
            }
        }
        return s.pop();
    }
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值