数据结构-栈-栈的应用(使用逆波兰表达式《后缀表达式》实现简易版运算器)

数据结构-栈-栈的应用(使用逆波兰表达式《后缀表达式》实现简易版运算器)

运算器可以包含小数、小括号、加减乘除

package com.orz.Stack;

import org.junit.Test;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.Stack;

/**
 * @author orz
 * @create 2020-10-27 10:45
 */
public class InfixExpressionSuffixExpressionTest{
    public static void main(String[] args) {
        String str="12.8+(2  -3.55)*4+  10/5.0";
        double resultByString = InfixExpressionSuffixExpression.getResultByString(str);
        System.out.println(resultByString);
    }
}
class InfixExpressionSuffixExpression {
    public static List<String> getExpression(String infixExpression)
    {
        //索引,用于获取字符,从零到length-1
        int index=0;
        //用于获取字符串中索引值为index的字符
        char ch=' ';
        //用于返回数组list集合,保存运算符和数值
        List<String> list=new ArrayList<>();
        //循环遍历
        while (index!=infixExpression.length())
        {
            //获取字符串中索引值为index的字符
            ch = infixExpression.charAt(index);
            //判断字符的优先级,-1代表非运算符非数值;0代表运算值,
            // 1代表+,-运算符;2代表*,x,X,/运算符;代表(,)小括号
            int order = getCharOrder(ch);

            //如果是非运算符,非数值,直接跳过
            if(order==-1)
            {
                index++;
            }

            else {
                //数值
                //需要判断是否是多位数
                if(order==0) {
                    //用于拼接多位数
                    StringBuilder str = new StringBuilder();
                    //先把这个数值拼上,再判断下一个是否也是数值,如果是就接着拼接,并使index索引值下移
                    //直到找到下一个不是数值为止
                    str.append(ch);
                    //索引值如果是length-1,说明已经是最后一个了,不需要再判断下一个是否是数值了,因为没有了
                   if(index!=infixExpression.length()-1)
                    {

                        int next = getCharOrder(infixExpression.charAt(index+1));
                        //判断下一个是否也是数值
                        //只要下一个字符也是数值类型,就拼接上;并使index+1
                        while (next == 0) {
                            //下一个是
                            char c = infixExpression.charAt(index+1);
                            str.append(c);
                            index++;
                            //判断是否到了最后一个,如果是最后一个,直接跳出循环体
                            if(index==infixExpression.length()-1)
                            {
                                break;
                            }
                            //没有到最后一个,在接着判断下一个是否还是数值型
                            next = getCharOrder(infixExpression.charAt(index+1));
                        }
                    }
                   //最后把多位数或者单位数加入到list中
                    list.add(String.valueOf(str));
                    index++;
                }
                else
                {
                    //运算符,直接加入
                    list.add(String.valueOf(ch));
                    index++;
                }
            }

        }

        return list;
    }

    /**
     * 中缀表达式转后缀表达式
     * ①设置一个空栈
     * ②从左到右读取中缀表达式,当读取到一个操作数时,立即将它放到输出中
     * ③当读取到运算符时,需要将该运算符放与当前栈顶元素比较,如果该运算符优先级·大于栈顶运算符的优先级,则将该运算符放入栈中;
     *      否则,将栈中的元素弹出直到栈顶元素低于该运算符的优先级;
     * ④如果读到的运算符是左括号时,将体压入栈中;如果读到的运算符是右括号时,将栈中的元素弹出直到遇到相对的左括号为止
     * ⑤重复上面的步骤,直到处理完所有的字符
     * @param list
     * @return
     */
    public static List<String> getSuffixExpression(List<String> list)
    {
        List<String> arrayList=new ArrayList<>(list);
        List<String> suffixList=new ArrayList<>();
        Stack<String> stack=new Stack<>();
        for (String str:arrayList) {
            if(getCharOrder(str.charAt(0))==0)
            {
                suffixList.add(str);
            }
            else if(str.charAt(0)=='(')
            {
                stack.push(String.valueOf('('));
            }
            else if(str.charAt(0)==')')
            {
                String popString = stack.pop();
                while (popString.charAt(0)!='(')
                {
                    suffixList.add(popString);
                    popString=stack.pop();
                }
            }
            else {
                if(stack.size()==0||stack.peek().charAt(0)=='(')
                {
                    stack.push(str);
                }
                else{
                    int charOrder = getCharOrder(str.charAt(0));
                    String popString=stack.peek();
                    int charOrder1 = getCharOrder(popString.charAt(0));
                    while (charOrder<=charOrder1&&popString.charAt(0)!='('&&stack.size()>0)
                    {
                        suffixList.add(popString);
                        stack.pop();
                        if(stack.size()==0)
                        {
                            break;
                        }
                        popString=stack.peek();
                        charOrder1 = getCharOrder(popString.charAt(0));
                    }
                    stack.push(str);
                }

            }
        }

        while (stack.size()!=0)
        {
            suffixList.add(stack.pop());
        }

        return suffixList;
    }

    /**
     * 使用后缀表达式计算
     * 从左到右扫描,如果是数值,放入栈中,如果是操作符,则从栈中弹出两个操作数进行运算
     * @param list
     * @return
     */
    public static double getResult(List<String> list)
    {
        ArrayList<String> arrayList=new ArrayList<>(list);
        Stack<String> stack=new Stack<>();
        for (String str:arrayList)
        {
            if(getCharOrder(str.charAt(0))==0)
            {
                stack.push(str);
            }else {
                char oper=str.charAt(0);
                double oper1=Double.parseDouble(stack.pop());
                double oper2=Double.parseDouble(stack.pop());
                double result=0;
                switch (oper)
                {
                    case '+':
                        result=oper2+oper1;
                        stack.push(String.valueOf(result));
                        break;
                    case '-':
                        result=oper2-+oper1;
                        stack.push(String.valueOf(result));
                        break;
                    case '*':
                        result=oper2*oper1;
                        stack.push(String.valueOf(result));
                        break;
                    case '/':
                        //一定是最底的数除以上面的数
                        result=oper2/oper1;
                        stack.push(String.valueOf(result));
                        break;
                    default:
                        break;
                }
            }
        }
        return Double.parseDouble(stack.pop());
    }

    /**
     * 判断字符的优先级,-1代表非运算符非数值;0代表运算值,
     *  1代表+,-运算符;2代表*,x,X,/运算符;代表(,)小括号
     * @param ch
     * @return
     */
    public static int getCharOrder(char ch)
    {
        if(ch=='('||ch==')'){
            return 3;
        }
        else if(ch=='*'||ch=='x'||ch=='X'||ch=='/')
        {
            return 2;
        }
        else if(ch=='+'||ch=='-')
        {
            return 1;
        }
        //.号说明是小数
        else if (ch >= 48 && ch <= 57 ||ch=='.') {
            return 0;
        }
        return -1;
    }

    /**
     * 输入一个字符串,返回运算结果
     * 过程为:
     * 字符串--->中缀表达式---->后缀表达式---->运算结果
     * @param str 表达式
     * @return 运算结果
     */
    public static double getResultByString(String str)
    {
        if(str==null||"".equals(str))
        {
            throw new RuntimeException("表达式不正确");
        }
        List<String> Expression= getExpression(str);
        List<String> suffixExpression = getSuffixExpression(Expression);
        double result=getResult(suffixExpression);
        return result;
    }

}
View Code

 

posted @ 2020-10-27 16:42  orz江小鱼  阅读(204)  评论(0编辑  收藏  举报