将中缀表达式转换为后缀表达式

时间:2022-06-24 18:47:02

中缀表达式:(6/2*3+9)/2+(3+1-1)*3+10/2

后缀表达式:6 2 / 3 * 9 + 2 / 3 1 + 1 - 3 * +10 2 / +

转换顺序如下:

将中缀表达式转换为后缀表达式


实现代码如下,可直接运行,仅供测试使用,可能还存在bug。

package com.example;

import java.util.ArrayList;
import java.util.List;
import java.util.Scanner;
import java.util.Stack;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

/**
 * Created by Yawinstake on 2016/12/25
 */

/**
 * only support Integer
 */
public class CalcTest {
    private  final String[] TAGS = new String[]{"+","-","*","/","(",")"};
    //缓存中缀表达式解析结果
    private  final List<String> CACHE_INFIX = new ArrayList<>();
    //缓存后缀表达式结果
    private  final List<String> CACHE_SUFFIX = new ArrayList<>();
    //用于解析后缀表达式中间栈
    private  final Stack<String> tempStack = new Stack<>();
    //用于计算最终结果栈,最后只剩下一个数据时即为计算结果
    private  final Stack<Double> calcStack = new Stack<>();
    public static void main(String[] args){
        Scanner scanner = new Scanner(System.in);
        String input = scanner.nextLine();
        new CalcTest().calculateTest(input);
    }
    public  void calculateTest(String s){
        if(s == null){
            return;
        }
        split(s);
        String[] args_infix = CACHE_INFIX.toArray(new String[CACHE_INFIX.size()]);
        System.out.println("parse infix data:"+printStringArray(args_infix));
        translate(args_infix);
        String[] args_suffix = CACHE_SUFFIX.toArray(new String[CACHE_SUFFIX.size()]);
        System.out.println("suffix data:"+printStringArray(args_suffix));
        System.out.println("calc result is:"+calculateUseSuffix(args_suffix));
    }

    private double calculateUseSuffix(String[] args_suffix){
        if(args_suffix == null || args_suffix.length == 0){
            return 0;
        }
        //遇到符号则将其前两位置数字进行运算
        for(int i= 0;i<args_suffix.length;i++){
            if(isNumeric(args_suffix[i])){
                calcStack.push(Double.parseDouble(args_suffix[i]));
            }else{
                double number2 = calcStack.pop();
                double number1 = calcStack.pop();
                double result = calc(number1,number2,args_suffix[i]);
                calcStack.push(result);
            }
        }
        return calcStack.pop();

    }

    private double calc(double number1, double number2,String operator){
        if( operator== null){
            return 0f;
        }
        try{
            if(operator.equals("+")){
                return number1 + number2;
            }else if(operator.equals("-")){
                return number1 - number2;
            }else if(operator.equals("*")){
                return number1 * number2;
            }else if(operator.equals("/")){
                return number1 / number2;
            }
        }catch (Exception e){

        }
        return 0f;
    }

	//可以修改此方法支持其他类型
    public boolean isNumeric(String s){
        if(s == null || s.trim().length() == 0){
            return false;
        }
        Pattern mPattern = Pattern.compile("[0-9]*");
        Matcher matcher = mPattern.matcher(s);
        return matcher.matches();
    }


    /**
     * 将中缀表达式转换为后缀表达式
     * @param args
     */
    private  void translate(String[] args){
        if(args == null || args.length == 0){
            return;
        }
        for(int i=0;i<args.length;i++){
            String arg = args[i];
            //数字输出,运算符进栈,括号匹配出栈,栈顶优先级低出栈
            if(isTag(arg)){
                if(arg.equals(")")){
                    //should pop
                    while(!tempStack.empty()){
                        String popTag = tempStack.pop();
                        if(popTag.equals("(")){
                           break;
                        }
                        addToSuffix(popTag);
                    }
                }else {
                    /**
                     * 判断栈内数据是否为空
                     * 不为空时循环取出栈顶数据与当前遍历数据比较优先级
                     * 结果为false时出栈,直到结果为true时退出循环
                     * 不论是否执行循环,最终都需要把当前的数据压入栈中
                     */
                    while(!tempStack.empty()){
                        String topArg = tempStack.peek();
                        //
                        if(isTagHighPriorityToStackFirst(topArg,arg)) {
                           break;
                        }
                        String popTag = tempStack.pop();
                        addToSuffix(popTag);
                    }
                    tempStack.push(arg);
                }
            }else{
                CACHE_SUFFIX.add(arg);
                if(i == args.length - 1){
                    while(!tempStack.empty()){
                        String popTag = tempStack.pop();
                        addToSuffix(popTag);
                    }
                }
            }
            System.out.println("arg is "+arg+",tempStack is"+tempStack+",CACHE_SUFFIX is "+CACHE_SUFFIX);
        }
    }


    private void addToSuffix(String tag){
        if(tag == null || tag.length() == 0){
            return;
        }
        if(isTagCanAdd(tag)){
            CACHE_SUFFIX.add(tag);
        }
    }

    /**
     *
     * @param topTag 栈顶
     * @param currentTag 当前数据
     * @return
     * 当栈顶为"("时,返回true
     * 当栈顶优先级等于当前要入栈数据时,返回false
     * 当栈顶优先级高于要入栈数据时,返回false
     * 当栈顶优先级低于要入栈数据时,返回true
     */
    private  boolean isTagHighPriorityToStackFirst(String topTag , String currentTag){
        if(topTag.equals(currentTag)){
            return false;
        }
        if(topTag.equals("(")){
            return true;
        }
        if(topTag.equals("*") || topTag.equals("/")){
                return false;
        }else{
            if(currentTag.equals("+") || currentTag.equals("-")){
                return false;
            }
        }
        return true;
    }

    private  boolean isTag(String s){
        if(s == null || s.trim().length() == 0){
            return false;
        }
        for(String tag : TAGS){
            if(tag.equals(s)){
                return true;
            }
        }
        return false;
    }

    private  boolean isTagCanAdd(String s){
        if(s == null || s.trim().length() == 0){
            return false;
        }
        for(String tag : TAGS){
            if(tag.equals(s) && !tag.equals(")") && !tag.equals("(")){
                return true;
            }
        }
        return false;
    }

    private  boolean isArgNotContainAnyTag(String arg){
        for(String tag : TAGS){
            if(arg.contains(tag)){
                return false;
            }
        }
        return true;
    }

    private static ArrayList<String> spitBytag(String s , String tag){
        if(s == null || tag == null){
            return null;
        }
        ArrayList<String> list = new ArrayList<>();
        if(!s.contains(tag)){
            list.add(s);
            return list;
        }
        String[] args = s.split(changeTag(tag));
        if(args.length == 1){
            if(s.indexOf(tag) == 0){
                list.add(tag);
                list.add(args[0]);
            }else {
                list.add(args[0]);
                list.add(tag);
            }
        }else {
            for (String arg : args) {
                //ignore space
                if (arg != null && arg.trim().length() != 0) {
                    if (list.size() == 0) {
                        list.add(arg);
                    } else {
                        if(!list.get(list.size()-1).equals(tag)) {
                            list.add(tag);
                        }
                        list.add(arg);
                    }
                }else{
                    list.add(tag);
                }
            }
        }
//        System.out.println("s is "+s+",tag is "+tag +",list is "+list+",args length is "+args.length);
        return list;
    }

    private static String changeTag(String tag){
        return "["+tag+"]";
    }

    private static String printStringArray(String[] array){
        if(array == null){
            return "";
        }
        StringBuilder sb = new StringBuilder();
        for(String s : array){
            if(sb.length() == 0){
                sb.append(s);
            }else{
                sb.append(",").append(s);
            }
        }
        return sb.toString();
    }

    private  void split(String s){
        split(s,0);
    }

    /**
     * 采用递归
     * @param s
     * @param index
     */
    private  void split(String s,final int index){
        if(index == TAGS.length){
            return;
        }
        List<String> list = spitBytag(s,TAGS[index]);
        if(list != null && list.size() > 0){
            if(list.size() == 1){
                String subS = list.get(0);
                if (subS.length() == 1 || isArgNotContainAnyTag(subS)) {
                    CACHE_INFIX.add(subS);
                }else{
                    split(subS,index+1);
                }
            }else {
                for (String subS : list) {
                    if (subS != null) {
                        if (subS.length() == 1 || isArgNotContainAnyTag(subS)) {
                            CACHE_INFIX.add(subS);
                        }else{
                            split(subS,index+1);
                        }
                    }
                }
            }
        }
    }
}
执行结果:

parse infix data:(,6,/,2,*,3,+,9,),/,2,+,(,3,+,1,-,1,),*,3,+,10,/,2
suffix data:6,2,/,3,*,9,+,2,/,3,1,+,1,-,3,*,+,10,2,/,+
calc result is:23.0


部分内容参考了:http://blog.csdn.net/antineutrino/article/details/6763722/