算法与数据结构 02 后缀表达式

  • 中缀转后缀
    1.初始化:添加运算符栈opStack和存储中键结果的线性表suffixList
    2.从左至右遍历中缀表达式的元素
    3.遇到数字时,将其压入suffixList
    4.遇到运算符时,比较其与opStack栈顶运算符的优先级
    如果opStack为空,或栈顶运算符为左括号,则直接将此运算符入栈;如果优先级比栈顶运算符的高,也将运算符压入opStack;否则,将opStack栈顶的运算符弹出并压入到suffixList中,再次返回并与opStack中新的栈顶运算符相比较
    5.遇到括号时:
    (1)如果是左括号,则直接入栈
    (2)如果是右括号,则依次弹出opStack栈顶的运算符,并压入suffixList,直到遇到左括号为止,此时将这一对括号丢弃
    6.重复步骤2-5 直到表达式的最右边
    7.将opStack剩余的运算符依次弹出并压入suffixList
    8.依次弹出suffixList中的元素并输出,结果的逆序即为中缀表达式对应的后缀表达式

  • 代码实现

 public static void main(String[] args) {
    String expression = "(10+20/2*3)/2+8";
    expression = infixToSuffix(expression);
    System.out.println(expression);
  }
  static String infixToSuffix(String expression) {
    //操作符的栈
    ArrayStack<String> opStack = new ArrayStack<>();
    //后缀表达式的线性表
    ArrayList<String> suffixList = new ArrayList<>();

    //格式化表达式
    expression = insertBlanks(expression);
    String[] tokens = expression.split(" ");
    for (String token : tokens) {
      //过滤空串
      if (token.length() == 0) {
        continue;
      }
      //判断操作符+ - * /
      if (isOperator(token)) {
                /*
                什么时候操作符进栈?
                1.如果栈为空
                2.如果栈顶是 (
                3.如果栈顶是操作符,且优先级比当前token小

                什么时候需要将栈顶操作符出栈?
                1.栈顶操作符的优先级 >= 当前token
                */
        while (true) {
          if (opStack.isEmpty() || opStack.peek().equals("(") || priority(opStack.peek()) < priority(token)) {
            opStack.push(token);
            break;
          }
          suffixList.add(opStack.pop());
        }
      } else if (token.equals("(")) {
        opStack.push(token);
      } else if (token.equals(")")) {
        while (!opStack.peek().equals("(")) {
          suffixList.add(opStack.pop());
        }
        opStack.pop();
      } else if (isNumber(token)) {
        suffixList.add(token);
      } else {
        throw new IllegalArgumentException("wrong char :" + expression);
      }
    }
    while (!opStack.isEmpty()) {
      suffixList.add(opStack.pop());
    }
    //将数字元素和操作符元素进行拼接
    StringBuilder sb = new StringBuilder();
    for (int i = 0; i < suffixList.size(); i++) {
      sb.append(suffixList.get(i));
      sb.append(' ');
    }
    return sb.toString();
  }

  private static int priority(String token) {
    if (token.equals("+") || token.equals("-")) {
      return 0;
    }
    if (token.equals("*") || token.equals("/")) {
      return 1;
    }
    return -1;
  }

  private static boolean isNumber(String token) {
    return token.matches("\\d+");
  }

  private static boolean isOperator(String token) {
    return token.equals("+") || token.equals("-") || token.equals("*") || token.equals("/");
  }

  //对原表达式进行格式化处理 给所有的非数字字符两边添加空格
  private static String insertBlanks(String expression) {
    StringBuilder sb = new StringBuilder();
    for (int i = 0; i < expression.length(); i++) {
      char c = expression.charAt(i);
      if (c == '(' || c == ')' || c == '+' || c == '-' || c == '*' || c == '/') {
        sb.append(' ');
        sb.append(c);
        sb.append(' ');
      } else {
        sb.append(c);
      }
    }
    return sb.toString();
  }
}
//输出结果
10 20 2 / 3 * + 2 / 8 + 
  1. 后缀表达式计算代码实现
 public static void main(String[] args) {
  String expression = "(10+20/2*3)/2+8";
  int result=evaluateExpression(expression);
  System.out.println(expression+"="+result);
}
  private static int evaluateExpression(String expression) {
    ArrayStack<Character> operatorStack=new ArrayStack<>();
    ArrayStack<Integer> numberStack=new ArrayStack<>();

    expression=insertBlanks(expression);
    String[] tokens=expression.split(" ");
    for (String token: tokens){

      if (token.length()==0){
        continue;
      }else if(token.equals("+")||token.equals("-")){
        while (!operatorStack.isEmpty()&&(operatorStack.peek()=='+'||operatorStack.peek()=='-'||operatorStack.peek()=='*'||operatorStack.peek()=='/')){
          processAnOperator(numberStack,operatorStack);
        }
        operatorStack.push(token.charAt(0));
      }else if (token.equals("*")||token.equals("/")){
        while (!operatorStack.isEmpty()&&(operatorStack.peek()=='*'||operatorStack.peek()=='/')){
          processAnOperator(numberStack,operatorStack);
        }
        operatorStack.push(token.charAt(0));
      }else if (token.equals("(")){
        operatorStack.push(token.charAt(0));
      }else if (token.equals(")")){
        while (operatorStack.peek()!='('){
          processAnOperator(numberStack,operatorStack);
        }
        operatorStack.pop();
      }else {
        numberStack.push(new Integer(token));
      }
    }
    while (!operatorStack.isEmpty()){
      processAnOperator(numberStack,operatorStack);
    }
    return numberStack.pop();
  }

  private static void processAnOperator(ArrayStack<Integer> numberStack, ArrayStack<Character> operatorStack) {
    char op=operatorStack.pop();
    int num1=numberStack.pop();
    int num2=numberStack.pop();

    if (op=='+'){
      numberStack.push(num2+num1);
    }else if (op=='-'){
      numberStack.push(num2-num1);
    }else if (op=='*'){
      numberStack.push(num2*num1);
    }else {
      numberStack.push(num2/num1);
    }
  }

  private static String insertBlanks(String expression) {
    StringBuilder sb=new StringBuilder();
    for (int i=0;i<expression.length();i++){
      char c=expression.charAt(i);
      if (c == '('||c==')'||c=='+'||c=='-'||c=='*'||c=='/'){
        sb.append(' ');
        sb.append(c);
        sb.append(' ');
      }else{
        sb.append(c);
      }
    }
    return sb.toString();
  }
 }
 //输出结果
 (10+20/2*3)/2+8=28
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值