九、中缀表达式转为后缀表达式

使用栈将中缀表达式转为后缀表达式并计算

一、中缀表达式转换为后缀表达式

由于后缀表达式适合计算式进行计算,但是人对于较长的中缀表达式,很难将中缀表达式直接转换为后缀表达式,于是我们使用栈来实现中缀表达式转成后缀表达式。

二、 中缀表达式转后缀表达式的分析步骤

1.初始化两个栈:运算符栈S1和存储中间结果的栈S2

2.从左到右扫描中缀表达式

3.遇到操作数时,将其压入S2中

4.遇到运算符时,比较其与S1栈顶符号的优先级
4.1)如果S1为空或者栈顶运算符为“(”,则直接将此运算符压入栈中
4.2)否则,若优先级比栈顶元素的优先级高,也将运算符压入栈S1中
4.3)否则,若优先级小于等于栈顶元素的优先级,将S1栈顶的运算符弹出,并压入S2中,再转到4.1继续与S1中新的栈顶元素相比较

5.遇到括号时:
5.1)如果是左括号,就直接压入栈S1中
5.2)如果是右括号,则牙齿弹出S1栈顶的运算符,并压入栈S2中,直到遇到左括号为止,此时这一对括号丢弃

6.重复步骤2到5,直到表达式的最右端

7.将栈S1中剩余的运算符依次弹出并压入栈S2中

8.依次弹出S2中的元素并输出,结果的逆序即为中缀表达式对应的后缀表达式

三、举例说明

将中缀表达式“1+((2+3)×4)-5”转换为后缀表达式的过程如下
在这里插入图片描述
因此结果为 : "1 2 3 + 4 × + 5 –"

四、代码实现

package cn.zzw.algorithm.Stack;

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

public class PolandNotion1 {
    public static void main(String[] args) {

        //输入中缀表达式
        String expression= "1+((2+3)*4)-5";
        List<String> infixExpressionList=toInfixExpressionList(expression);
        System.out.println("中缀表达式对应的list为:"+infixExpressionList);

        List<String> suffixExpressionList=parseSuffixExpressionList(infixExpressionList);
        System.out.println("后缀表达式:"+suffixExpressionList);

        int result=calculate(suffixExpressionList);
        System.out.println("最终的结果为:"+result);

    }

    //将中缀表达式对应的List转换为后缀表达式的List
    public static List<String> parseSuffixExpressionList(List<String> list)
    {
        //定义两个栈
        Stack<String> stack1=new Stack<>();//符号栈
        //说明:因为 s2 这个栈,在整个转换过程中,没有 pop 操作,而且后面我们还需要逆序输出
        // 因此比较麻烦,这里我们就不用 Stack<String> 直接使用 List<String> s2
        // Stack<String> stack2 = new Stack<String>(); // 储存中间结果的栈 s2

        List<String> list2=new ArrayList<>();

        //遍历形参传入的list集合
        for(String item:list)
        {
            //如果是一个数,就直接加入list2
            if(item.matches("\\d+"))
            {
                list2.add(item);
            }
            else if (item.equals("("))
            {
                stack1.push(item);
            }
            else if(item.equals(")"))
            {
                //如果是右括号“)”,则依次弹出 s1 栈顶的运算符,并压入 s2,直到遇到左括号为止,此时将这 一对括号丢弃
                while (!stack1.peek().equals("("))
                {
                    list2.add(stack1.pop());
                }
                //将小括号从stack1中弹出,消除小括号
                stack1.pop();
            }
            else
            {
                //当 item 的优先级小于等于 s1 栈顶运算符, 将 s1 栈顶的运算符弹出并加入到 s2 中,再次转到(4.1) 与 s1 中新的栈顶运算符相比较
                while (stack1.size()!=0&&Operation.getValue(item)<=Operation.getValue(stack1.peek()))
                {
                    list2.add(stack1.pop());
                }
                //之后还需要将item入栈
                stack1.push(item);
            }
        }

        //最后将stack1中剩余的元素依次弹出并加入list2中
        while (stack1.size()!=0)
        {
            list2.add(stack1.pop());
        }
        return list2;
    }

    //将中缀表达式转为对应的List
    public static List<String> toInfixExpressionList(String s)
    {
        List<String> list=new ArrayList<>();
        //定义一个指针,用于遍历中缀表达式中的字符串
        int index=0;
        String str;//用于字符串的拼接
        char c;

        do {
            //如果是一个非数字,需要加入到list中
            if ((c=s.charAt(index))<48||(c=s.charAt(index))>57)
            {
                list.add(c+"");
                index++;//指针后移
            }
            else
            {
                //如果是数字,则要考虑多位数的情况
                str="";//先将str置空
                while (index<s.length()&&(c=s.charAt(index))>=48&&(c=s.charAt(index))<=57)
                {
                    str+=c;
                    index++;
                }
                list.add(str);
            }
        }while (index<s.length());

        return list;
    }

    //使用逆波兰表达式的运算
    public static int calculate(List<String> list)
    {
        //创建一个占空间
        Stack<String> stack=new Stack<>();
        //遍历集合
        for(String item:list)
        {
            //这里使用正则表达式取出数字
            //匹配的是多位数
            if(item.matches("\\d+"))
            {
                stack.push(item);
            }
            else
            {
                int num1=Integer.parseInt(stack.pop());
                int num2=Integer.parseInt(stack.pop());
                int result=0;
                if(item.equals("+"))
                {
                    result=num1+num2;
                }
                else if(item.equals("-"))
                {
                    result=num2-num1;
                }
                else if(item.equals("*"))
                {
                    result=num1*num2;
                }
                else if (item.equals("/"))
                {
                    result=num2/num1;
                }
                else
                {
                    throw new RuntimeException(("运算符有误"));
                }
                //重要,最后别忘了把计算出来的结果入栈
                stack.push(result+"");
            }
        }
        //最后留在栈中的数据就是最终的结果
        return Integer.parseInt(stack.pop());
    }
}

//编写一个类,可以返回一个运算符对应的优先级
class Operation
{
    private static int ADD=1;
    private static int SUB=1;
    private static int MUL=2;
    private static int DIV=2;

    //返回对应的优先级的数字
    public static int getValue(String operation)
    {
        int result=0;
        switch (operation)
        {
            case "+":
                result=ADD;
                break;
            case "-":
                result=SUB;
                break;
            case "*":
                result=MUL;
                break;
            case "/":
                result=DIV;
                break;
            
        }
        return result;
    }
}

五、测试结果

"C:\Program Files\Java\jdk1.8.0_181\bin\java.exe" "-javaagent:D:\IntelliJ IDEA\IntelliJ IDEA 2019.3.3\lib\idea_rt.jar=21098:D:\IntelliJ IDEA\IntelliJ IDEA 2019.3.3\bin" -Dfile.encoding=UTF-8 -classpath "C:\Program Files\Java\jdk1.8.0_181\jre\lib\charsets.jar;C:\Program Files\Java\jdk1.8.0_181\jre\lib\deploy.jar;C:\Program Files\Java\jdk1.8.0_181\jre\lib\ext\access-bridge-64.jar;C:\Program Files\Java\jdk1.8.0_181\jre\lib\ext\cldrdata.jar;C:\Program Files\Java\jdk1.8.0_181\jre\lib\ext\dnsns.jar;C:\Program Files\Java\jdk1.8.0_181\jre\lib\ext\jaccess.jar;C:\Program Files\Java\jdk1.8.0_181\jre\lib\ext\jfxrt.jar;C:\Program Files\Java\jdk1.8.0_181\jre\lib\ext\localedata.jar;C:\Program Files\Java\jdk1.8.0_181\jre\lib\ext\nashorn.jar;C:\Program Files\Java\jdk1.8.0_181\jre\lib\ext\sunec.jar;C:\Program Files\Java\jdk1.8.0_181\jre\lib\ext\sunjce_provider.jar;C:\Program Files\Java\jdk1.8.0_181\jre\lib\ext\sunmscapi.jar;C:\Program Files\Java\jdk1.8.0_181\jre\lib\ext\sunpkcs11.jar;C:\Program Files\Java\jdk1.8.0_181\jre\lib\ext\zipfs.jar;C:\Program Files\Java\jdk1.8.0_181\jre\lib\javaws.jar;C:\Program Files\Java\jdk1.8.0_181\jre\lib\jce.jar;C:\Program Files\Java\jdk1.8.0_181\jre\lib\jfr.jar;C:\Program Files\Java\jdk1.8.0_181\jre\lib\jfxswt.jar;C:\Program Files\Java\jdk1.8.0_181\jre\lib\jsse.jar;C:\Program Files\Java\jdk1.8.0_181\jre\lib\management-agent.jar;C:\Program Files\Java\jdk1.8.0_181\jre\lib\plugin.jar;C:\Program Files\Java\jdk1.8.0_181\jre\lib\resources.jar;C:\Program Files\Java\jdk1.8.0_181\jre\lib\rt.jar;C:\Users\1\IdeaProjects\algorithm\out\production\algorithm" cn.zzw.algorithm.Stack.PolandNotion1
中缀表达式对应的list为:[1, +, (, (, 2, +, 3, ), *, 4, ), -, 5]
后缀表达式:[1, 2, 3, +, 4, *, +, 5, -]
最终的结果为:16

Process finished with exit code 0

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值