中缀表达式转后缀表达式并计算表达式的值(含JAVA代码实现)

该文详细介绍了如何将中缀表达式转换为后缀表达式,并提供了Java代码实现。转换过程中涉及括号处理、运算符优先级等关键点。之后,文章还阐述了如何基于后缀表达式进行计算,同样给出了相应的Java函数。整个过程包括了中缀到后缀的转换以及后缀表达式的计算逻辑。
摘要由CSDN通过智能技术生成

转载请标明出处,谢谢!

中缀表达式转后缀表达式思路:

从左至右依次遍历中缀表达式各个字符(需要准备一个字符栈存储操作符和括号)

1、字符为 运算数 :

直接送入后缀表达式(需要先分析出完整的运算数,即:-4、150这种数字要当作一个整体)。

2、字符为 左括号 :

直接入栈(左括号入栈后优先级降至最低)。

3、字符为 右括号 :

直接出栈,并将出栈字符依次送入后缀表达式,直到栈顶字符为左括号(左括号也要出栈,但不送入后缀表达式)。

总结:只要满足 栈顶为左括号 即可进行最后一次出栈。

4、字符为 操作符 :

若栈空,直接入栈。

若栈非空,判断栈顶操作符,若栈顶操作符优先级低于该操作符,该操作符入栈;否则一直出栈,并将出栈字符依次送入后缀表达式,直到栈空或栈顶操作符优先级低于该操作符,该操作符再入栈。

5、重复以上步骤直至遍历完成中缀表达式,接着判断字符栈是否为空,非空则直接出栈,并将出栈字符依次送入后缀表达式。

注:中缀表达式遍历完成,栈中可能还有字符未输出,故需要判断栈空。

中缀表达式转后缀表达式Java实现:

(1) 首先需要将中缀表达式拆分成字符串数组,使用 String2List 

 public static List<String> String2List(String s){
        List<String> list = new ArrayList<>();
        String temp = "";
        for(int i=0; i<s.length();i++){
            char c = s.charAt(i);
            if(Character.isDigit(c)){
                if(i!=s.length()-1 && Character.isDigit(s.charAt(i+1))){
                    temp += c;
                }else{
                    temp += c;
                    list.add(temp);
                    temp = "";
                }
            }else if(c == '-'){
                //对负数特殊处理(如“-4”要当作一个操作数来处理)
                if(i == 0 || s.charAt(i-1) == '('){
                    temp += c;
                }else{
                    list.add(c + "");
                }
            }else{
                list.add(c + "");
            }
        }
        return list;
    }

(2) 将得到的字符串数组传入 mid2back , 进行表达式的转换,其中需要对字符串进行判断,按照是否为操作数进行划分,此功能由 isNum 提供

public static List<String> mid2back(List<String> s){
        List<String> ss = new ArrayList<>();
        Stack<String> stack = new Stack<String>();
        for(int i=0; i<s.size(); i++){
            String c = s.get(i);
            //System.out.println(c);
            //数字直接输出,字符判断入栈(请注意:左括号的优先级,入栈后视为最低)
            if(isNum(c)){
                ss.add(c);
            }else{
                if(c.equals("(") || stack.isEmpty()){
                    stack.push(c);
                }
                else if(c.equals(")")){
                    //出栈直到碰到左括号
                    while(!stack.peek().equals("(")){
                        ss.add(stack.pop());
                    }
                    //左括号弹出去
                    stack.pop();
                }
                else if(c.equals("*") || c.equals("/")){
                    //栈顶运算符优先级低于当前操作符,入栈
                    if(stack.peek().equals("+") || stack.peek().equals("-") || stack.peek().equals("(") ){
                        stack.push(c);
                    }else{
                        //出栈,直到栈顶优先级低于当前操作符,或者栈空,然后入栈
                        while(!stack.isEmpty() && (stack.peek().equals("*") || stack.peek().equals("/"))){
                            ss.add(stack.pop());
                        }
                        stack.push(c);
                    }
                }
                else if(c.equals("+") || c.equals("-")){
                    if(stack.peek() == "("){
                        stack.push(c);
                    }else{
                        while(!stack.isEmpty() && !stack.peek().equals("(") ){
                            ss.add(stack.pop());
                        }
                        stack.push(c);
                    }
                    
                }
            }
        }
        //如果栈内还有运算符,直接弹出,直到栈空
        while(!stack.isEmpty()){
            ss.add(stack.pop());
        }
        //System.out.println(ss);
        return ss;
    }

public static boolean isNum(String s){
        for(int i = 0; i <= 9; i++){
            if(s.contains(i+"")){
                return true;
            }
        }
        return false;
    }

后缀表达式计算思路:

 从左到右扫描后缀表达式,遇到数字就入栈,遇到操作符就从栈弹出两个数字,然后计算得到的值继续入栈,继续扫描表达式,直到扫描完毕得到结果。

给出图例如下:

后缀表达式计算Java实现:

public static String backCal(List<String> ss){
        //这里必须为String类型,不然后边字符和数字的转换会出现问题
        Stack<String> stack = new Stack<>();
        for(int i=0; i<ss.size(); i++){
            String c = ss.get(i);
            //数字直接入栈
            if(isNum(c)){
                stack.push(c);
            }
            //运算符,取出来并计算,再放进去
            else{
                Long b = Long.parseLong(stack.pop());
                Long a = Long.parseLong(stack.pop());
                switch(c){
                    case "+":
                        stack.push(Long.toString(a + b));
                        break;
                    case "-":
                        stack.push(Long.toString(a - b));
                        break;
                    case "*":
                        stack.push(Long.toString(a * b));
                        break;
                    case "/":
                        stack.push(Long.toString(a / b));
                        break;
                }
            }
        }
        return stack.pop();
    }

整体代码: 

import java.util.*;

// 注意类名必须为 Main, 不要有任何 package xxx 信息
public class Main {
    public static void main(String[] args) {
        Scanner in = new Scanner(System.in);
        String s = in.nextLine();
        //先把所有括号统一
        s = s.replace("{","(");
        s = s.replace("[","(");
        s = s.replace("}",")");
        s = s.replace("]",")");
        //初始字符串预处理(提取数字整体作为一个字符串,创建字符串数组,其中包含对负数的处理)
        List<String> list = String2List(s);
        //中缀表达式转后缀表达式
        List<String> ss = mid2back(list);
        //后缀表达式计算
        System.out.print(backCal(ss));
    }
    public static List<String> mid2back(List<String> s){
        List<String> ss = new ArrayList<>();
        Stack<String> stack = new Stack<String>();
        for(int i=0; i<s.size(); i++){
            String c = s.get(i);
            //System.out.println(c);
            //数字直接输出,字符判断入栈(请注意:左括号的优先级,入栈后视为最低)
            if(isNum(c)){
                ss.add(c);
            }else{
                if(c.equals("(") || stack.isEmpty()){
                    stack.push(c);
                }
                else if(c.equals(")")){
                    //出栈直到碰到左括号
                    while(!stack.peek().equals("(")){
                        ss.add(stack.pop());
                    }
                    //左括号弹出去
                    stack.pop();
                }
                else if(c.equals("*") || c.equals("/")){
                    //栈顶运算符优先级低于当前操作符,入栈
                    if(stack.peek().equals("+") || stack.peek().equals("-") || stack.peek().equals("(") ){
                        stack.push(c);
                    }else{
                        //出栈,直到栈顶优先级低于当前操作符,或者栈空,然后入栈
                        while(!stack.isEmpty() && (stack.peek().equals("*") || stack.peek().equals("/"))){
                            ss.add(stack.pop());
                        }
                        stack.push(c);
                    }
                }
                else if(c.equals("+") || c.equals("-")){
                    if(stack.peek() == "("){
                        stack.push(c);
                    }else{
                        while(!stack.isEmpty() && !stack.peek().equals("(") ){
                            ss.add(stack.pop());
                        }
                        stack.push(c);
                    }
                    
                }
            }
        }
        //如果栈内还有运算符,直接弹出,直到栈空
        while(!stack.isEmpty()){
            ss.add(stack.pop());
        }
        //System.out.println(ss);
        return ss;
    }
    public static String backCal(List<String> ss){
        //这里必须为String类型,不然后边字符和数字的转换会出现问题
        Stack<String> stack = new Stack<>();
        for(int i=0; i<ss.size(); i++){
            String c = ss.get(i);
            //数字直接入栈
            if(isNum(c)){
                stack.push(c);
            }
            //运算符,取出来并计算,再放进去
            else{
                Long b = Long.parseLong(stack.pop());
                Long a = Long.parseLong(stack.pop());
                switch(c){
                    case "+":
                        stack.push(Long.toString(a + b));
                        break;
                    case "-":
                        stack.push(Long.toString(a - b));
                        break;
                    case "*":
                        stack.push(Long.toString(a * b));
                        break;
                    case "/":
                        stack.push(Long.toString(a / b));
                        break;
                }
            }
        }
        return stack.pop();
    }
    public static boolean isNum(String s){
        for(int i = 0; i <= 9; i++){
            if(s.contains(i+"")){
                return true;
            }
        }
        return false;
    }
    public static List<String> String2List(String s){
        List<String> list = new ArrayList<>();
        String temp = "";
        for(int i=0; i<s.length();i++){
            char c = s.charAt(i);
            if(Character.isDigit(c)){
                if(i!=s.length()-1 && Character.isDigit(s.charAt(i+1))){
                    temp += c;
                }else{
                    temp += c;
                    list.add(temp);
                    temp = "";
                }
            }else if(c == '-'){
                //对负数特殊处理(如“-4”要当作一个操作数来处理)
                if(i == 0 || s.charAt(i-1) == '('){
                    temp += c;
                }else{
                    list.add(c + "");
                }
            }else{
                list.add(c + "");
            }
        }
        return list;
    }
}

输入描述:

输入一个算术表达式,保证字符串中的有效字符包括[‘0’-‘9’],‘+’,‘-’, ‘*’,‘/’ ,‘(’, ‘)’,‘[’, ‘]’,‘{’ ,‘}’。且表达式一定合法。

输出描述:

得到计算结果

 

  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

2ephyr

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

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

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

打赏作者

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

抵扣说明:

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

余额充值