字符串转List、中缀转后缀、逆波兰计算器

逆波兰计算器

主要步骤:

  1. 将字符串转为List
  2. 中缀转后缀(重点!!!!)
  3. 实现逆波兰计算器

具体代码如下:

public static void main(String[] args) {
    //将字符串转为List
    String result = replaceSpace("-35-(33 + (4 + 5))");
    List<String> originList = strToList(result);
    System.out.println(originList);
    
    //中缀转后缀
    List<String> transList = transfer(originList);
    System.out.println(transList);

    //逆波兰计算器
    int res = calculate(transList);
    System.out.println(res);
}
/**
 * 将输入的字符串转List,同时处理多位数情况
 * -35-(33+(4+5)) ====》 [-, 35, -, (, 33, +, (, 4, +, 5, ), )]
 * @param s 输入的字符串
 * @return List
 */
public static List<String> strToList(String s){
  List<String> resList = new ArrayList<>();
  int i = 0;
  while (i < s.length()) {
      if (Character.isDigit(s.charAt(i))) {
          long num = 0;
          while (i < s.length() && Character.isDigit(s.charAt(i))) {
              num = num * 10 + s.charAt(i) - '0';
              i++;
          }
          resList.add(num + "");
      } else {
          resList.add(s.charAt(i) + "");
          i++;
      }
  }
  return resList;
}
/**
* 中缀转后缀
* 该处我做了改动,使用对0做加减来表示符号位,有点蠢但是好理解
* [-, 35, -, (, 33, +, (, 4, +, 5, ), )] ====》 [0, 35, -, 33, 4, 5, +, +, -]
* @param list
* @return
*/
private static List<String> transfer(List<String> list) {
    //创建一个符号栈
    Stack<String> stack = new Stack<>();
    //创建一个用于存放结果的集合
    List<String> resList = new ArrayList<>();
    //遍历原始集合
    for (int i=0; i<list.size(); i++) {
        String cur = list.get(i); //cur为当前字符串
        if ("(".equals(cur)){
            //当为左括号时,直接入符号栈
            stack.push(cur);
        }else if (")".equals(cur)){
            //当为右括号时,遍历符号栈,当找到对应左括号时退出循环
            while (!"(".equals(stack.peek())){
                //若不是对应的左括号,则将该位出栈,并加入到结果集合中
                resList.add(stack.pop());
            }
            //若找到对应的左括号,则退出循环,并将该左括号出栈
            stack.pop();
        }else if (isNumber(cur)){
            //当为数字时,直接加入结果集
            resList.add(cur);
        }else {
            //当为符号位时,先判断当前符号是否为符号位-/+
            if ("-".equals(cur) || "+".equals(cur)){
                //判断是否位于字符串第一位,或者位于左括号后,往结果集中加入0
                //因为加入0做数字进入计算,则可以把符号位当做运算符号计算,例如 (-35) === (0-35)
                if (i == 0 || "(".equals(list.get(i-1))){
                    resList.add("0");
                }
            }
            //当为符号位时,判断当前符号与栈顶符号的优先级,
            //1、若当前优先级小于等于栈顶优先级则,遍历符号栈,将元素出栈直到不满足该条件,再将当前符号位cur压入栈中
            //2、若当前优先级大于栈顶优先级则直接压入栈中
            while (stack.size() != 0 && !"(".equals(stack.peek()) && level(cur) <= level(stack.peek())){
                resList.add(stack.pop());
            }
            stack.push(cur);
        }
    }

    //遍历符号栈,将剩余符号加入结果集
    while (stack.size()!=0){
        resList.add(stack.pop());
    }
    return resList;
}
/**
 * 后缀表达式进行计算
 * 1、遍历后缀表达式
 * 2.1、若为数字,则直接push到栈中
 * 2.2、若为符号位,则取出栈中的 栈顶 和 次栈顶位,使用该符号进行计算,将计算结果push到栈中
 * 3、直到遍历完毕,取出栈内的栈顶元素即为最终结果
 * @param list list
 * @return int
 */
public static int calculate(List<String> list) {
    //创建一个栈做中间结果存放
    Stack<String> stack = new Stack<>();
    //遍历后缀表达式
    for (String item : list) {
        if (isNumber(item)){
            stack.push(item); //若为数字,则直接push到栈中
        }else {
            //若为符号位,则取出栈中的 栈顶 和 次栈顶位,使用该符号进行计算,将计算结果push到栈中
            int num1 = Integer.parseInt(stack.pop());
            int num2 = Integer.parseInt(stack.pop());
            int res = 0;
            if ("+".equals(item)){
                res = num2 + num1;
            }else if ("-".equals(item)){
                res = num2 - num1;
            }else if ("*".equals(item)){
                res = num2 * num1;
            }else if ("/".equals(item)){
                res = num2 / num1;
            }
            stack.push(String.valueOf(res));
        }
    }
    //直到遍历完毕,取出栈内的栈顶元素即为最终结果
    return Integer.parseInt(stack.pop());
}
/**
 * 判断符号优先级
 */
public static int level(String a){
    if ("+".equals(a) || "-".equals(a)){
        return 0;
    }else if ("*".equals(a) || "/".equals(a)){
        return 1;
    }else {
        throw new RuntimeException("符号不存在");
    }
}
/**
 * 判断是否为数字
 */
public static boolean isNumber(String a){
    return String.valueOf(a).matches("(-?|\\+?)\\d+");
}
/**
 * 去除空格
 */
public static String replaceSpace(String s){
    return s.replaceAll("\\s","");
}
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值