中缀表达式转后缀表达式(栈+队列)

package 数据结构;

import java.util.Arrays;
import java.util.Queue;
import java.util.Stack;
import java.util.concurrent.LinkedBlockingQueue;

/**
 * @program: java_每天一题
 * @description: 使用栈及队列实现中缀表达式转后缀表达式功能
 *            思路:1.初始化一个栈存放运算符s1,初始化一个队列存放后缀表达式q1
 *                 2.从左自右扫描中缀表达式
 *                 3.遇到数字,放入队列q1中
 *                 4.遇到运算符,进行比较运算符优先级
 *                 4.1 如果s1为空或者遇到左括号“(”,直接入栈
 *                 4.2 如果运算符优先级比栈顶优先级高,直接入栈
 *                 4.3 如果运算符优先级比栈顶优先级低,或者相等,想将s1顶层运算符弹出放入q1,再次转到4.1与新的顶层运算符相比较
 *                 5.遇括号时,如果是左括号“(”,直接入栈.如果是右括号,则依次弹出s1栈顶运算符,放入q1中,直到遇到左括号为止,此时将一对括号抛弃
 *                 6 重复步骤2-5,直到表达式最右边
 *                 7 将q1顺序输出 得到后缀表达式(逆波兰表达式)
 * @author: czg
 * @create: 2020-05-16 11:15
 */
public class j_栈_中缀转后缀_逆波兰 {
    public static void main(String[] args) {

        System.out.println(Arrays.toString(infixToArrarSuffix("1+((2+3)*4)-5")));
    }

    /**
     * 中缀表达式转后缀表达式(返回字符串格式)
     * @param infix 中缀表达式
     * @return
     */
    public static String infixToStringSuffix(String infix){
        Stack<String> s1=new Stack<>();//存放运算符
        Queue<String> q1=new LinkedBlockingQueue<String>();//存放后缀表达式
        int index=0;//循环中缀表达式下标
        StringBuilder result=new StringBuilder();//结果

        while (true){
            //获得下标指定元素
            String element=getOneElement(infix,index);
            //如果是运算符
            if(isOperator(element)){
                //s1.peek() 查看栈顶
                if(s1.empty()||"(".equals(element)||"(".equals(s1.peek())){
                    //如果s1为空或者遇到左括号“(”,直接入栈
                    s1.push(element);
                }else if(")".equals(element)){
                    //如果是右括号,则依次弹出s1栈顶运算符,放入q1中,直到遇到左括号为止,此时将一对括号抛弃
                    while (!s1.peek().equals("(")){
                        q1.add(s1.pop());
                    }
                    //丢弃左括号
                    s1.pop();
                }else if(operaPriority(element)>operaPriority(s1.peek())){
                    //如果运算符优先级比栈顶优先级高,直接入栈
                    s1.push(element);
                }else if(operaPriority(element)<=operaPriority(s1.peek())){
                    //如果运算符优先级比栈顶优先级低,或者相等,想将s1顶层运算符弹出放入q1,再次转到4.1与新的顶层运算符相比较
                    while (operaPriority(element)<=operaPriority(s1.peek())){
                        q1.add(s1.pop());
                        if(s1.empty()){
                            s1.push(element);
                            break;
                        }
                    }
                }else {
                    throw new RuntimeException("存在未知运算符,无法计算");
                }
            }else if(isInteger(element)){
                //直接存入q1
                q1.add(element);
            }
            index=index+element.length();

            //当到达末尾时,结束循环
            if(index>=infix.length()){
                if(!s1.empty()){
                    q1.add(s1.pop());
                }
                break;
            }
        }


        while (!q1.isEmpty()){
            result.append(q1.poll());
        }
        return result.toString();
    }

    /**
     * 中缀表达式转后缀表达式(返回字符串数组格式)
     * @param infix 中缀表达式
     * @return
     */
    public static String[] infixToArrarSuffix(String infix){
        Stack<String> s1=new Stack<>();//存放运算符
        Queue<String> q1=new LinkedBlockingQueue<String>();//存放后缀表达式
        int index=0;//循环中缀表达式下标

        while (true){
            //获得下标指定元素
            String element=getOneElement(infix,index);
            //如果是运算符
            if(isOperator(element)){
                //s1.peek() 查看栈顶
                if(s1.empty()||"(".equals(element)||"(".equals(s1.peek())){
                    //如果s1为空或者遇到左括号“(”,直接入栈
                    s1.push(element);
                }else if(")".equals(element)){
                    //如果是右括号,则依次弹出s1栈顶运算符,放入q1中,直到遇到左括号为止,此时将一对括号抛弃
                    while (!s1.peek().equals("(")){
                        q1.add(s1.pop());
                    }
                    //丢弃左括号
                    s1.pop();
                }else if(operaPriority(element)>operaPriority(s1.peek())){
                    //如果运算符优先级比栈顶优先级高,直接入栈
                    s1.push(element);
                }else if(operaPriority(element)<=operaPriority(s1.peek())){
                    //如果运算符优先级比栈顶优先级低,或者相等,想将s1顶层运算符弹出放入q1,再次转到4.1与新的顶层运算符相比较
                    while (operaPriority(element)<=operaPriority(s1.peek())){
                        q1.add(s1.pop());
                        if(s1.empty()){
                            s1.push(element);
                            break;
                        }
                    }
                }else {
                    throw new RuntimeException("存在未知运算符,无法计算");
                }
            }else if(isInteger(element)){
                //直接存入q1
                q1.add(element);
            }
            index=index+element.length();

            //当到达末尾时,结束循环
            if(index>=infix.length()){
                if(!s1.empty()){
                    q1.add(s1.pop());
                }
                break;
            }
        }


        String[] result=new String[q1.size()];//结果
        for (int i = 0; i < result.length; i++) {
            result[i]=q1.poll();
        }
        return result;
    }

    //获得一个元素
    public static String getOneElement(String experssion,int index){
        int count=index;
        String data="";
        while (true){
            String temp="";
            if(experssion.length()==count+1)
            {
                temp=experssion.substring(index);
            }else {
                temp=experssion.substring(index,count+1);
            }
            if(isOperator(temp)){
                data=temp;
                break;
            }
            if(isInteger(temp)||temp.equals(".")){
                data=temp;
                if(experssion.length()==count+1){
                    break;
                }
                count++;
            }else if(data.length()>0){
                break;
            }
        }
        return data;
    }



    //判断字符串是否为数字
    public static boolean isInteger(String str) {
        try {
            new Double(str);
            return true;
        }catch (Exception e){
            return false;
        }
    }
    //判断是否是运算符
    public static boolean isOperator(String str){
        return "+-*/()".indexOf(str)>=0;
    }
    //设置字符优先级
    public static int operaPriority(String opera){
        int result=0;
        switch (opera){
            case "+":
            case "-":  break;
            case "*":
            case "/":  result=1; break;
            default:
                throw new RuntimeException("运算符优先级无法解析");
        }
        return result;
    }
}

猜你喜欢

转载自www.cnblogs.com/czgxxwz/p/12899879.html