中缀表达式转后缀表达式

来源:互联网 发布:温暖的一句话知乎 编辑:程序博客网 时间:2024/06/01 08:55

在一些简单的加减乘除算式中我们可以很容易的看出哪个运算符要先进行计算,但对于计算机来说却并不容易。为了能让计算机能够准确的计算出结果,我们需要将算式进行简单的转换,将优先级高的运算符排在前面,即将中缀表达式转化为后缀表达式(逆波兰式)。

        

例如给出前缀表达式:1+2*(4-3),很明显在这个表达式中运算符优先级由高到底的排列顺序为:-、*、+,转换为后缀表达式即:1243-*+

优先级:乘除的优先级高于加减,数字与操作符优先级相同,左括号的优先级低于所有运算符和数字(不需要对右括号的优先级定义,因为碰到右括号就直接开始弹栈顶)。

 

转换过程:

(1)初始化一个栈,和一个后缀表达式数组

(2)从左到右依次读取前缀表达式的每个字符

        1、 遇到左括号直接进栈。

        2、遇到右括号依次弹出栈顶元素,直至将左括号弹出,即弹出左右括号括起来的内容,并记录在后缀

               表达式数组中。

        3、遇到数字直接进栈。

        4、遇到运算符(该运算符还未进栈):p:若栈为空栈顶元素(即表达式的上一个字符)的优先级低

                                                                                  于当前遇到的操作符,该运算符直接进栈。

                                                                              q:若栈不为空栈顶元素的优先级高于或等于当前遇到的操作

                                                                                 符,依次弹出栈顶元素,并记录在后缀表达式数组中。直至

                                                                                 栈为空栈顶元素的优先级低于当前遇到的操作符。最后

                                                                                 该操作符压入栈

        5、依次弹出栈顶元素直至栈空


例:1+2*((4-3)+6/2),依次读取每个字符

        char c='1';

        数字直接进栈:

          1        char c='+';

        栈不为空,且栈顶元素为数字(条件q),数字的优先级与操作符相同,所以弹出栈顶元素并记录入后缀数组:

                                     后缀数组:1

                              此时栈空,将该字符压入栈:

           +        char c='2';

        数字直接进栈:

          2      +          char c='*';

          栈不为空,且栈顶元素为数字(条件q),数字的优先级与操作符相同,所以弹出栈顶元素并记录入后缀数组:

                                     后缀数组:12

          +          加号优先级低于乘号(条件p),乘号进栈         *     +        char c='(';

        左括号直接进栈:        (     *     +        char c='4';

        数字直接进栈:

       4     (     *     +        char c='-;

        栈不为空,且栈顶元素为数字(条件q),数字的优先级与操作符相同,所以弹出栈顶元素并记录入后缀数组:

                                     后缀数组:124

       -     (     *     +        char c='3';

        数字直接进栈:

      3     -     (     *     +        char c=')';

        开始依次弹出栈顶元素并记录弹出的元素,直至弹出第一个左括号:  

                                           后缀数组:1243-

         *     +       表达式读完开始依次弹出栈顶元素并记录弹出的元素,直至栈空:

                                                  后缀数组1243-*+


/* 中缀表达式转后缀表达式,结果保存在postfix数组中 * char[] infix:前缀数组。char[] postfix:后缀数组 */private static void infixtopostfix(char[] infix, char[] postfix) {index=0;//索引LinkedList<Character> st=new LinkedList();//LinkedList对象以push形式添加元素时做堆栈用,以add形式添加元素时做队列用for(int i=0;i<infix.length;i++){char c=infix[i];//获取前缀数组的各个字符if(c=='(')st.push(c);//左括号直接进栈else if(c==')'){while(st.peek()!='('){//记录下左右括号内的操作符postfix[index++]=st.pop();//碰到右括号时,弹出左右括号中的内容}st.pop();//弹出左括号}else{if(c>='0'&&c<='9')st.push(c);//数字直接进栈else{while(!st.isEmpty()&&precedence(st.peek(),c)>=0){//栈不为空&&上一个操作符的优先级高于当前操作符cpostfix[index++]=st.pop();//弹出的元素记录在后缀数组中}st.push(c);//当前操作符一定要进栈,并在下一层循环或最后弹出}}}//弹出栈中剩余的操作符while(!st.isEmpty()){postfix[index++]=st.pop();//弹出的元素记录在后缀数组中}}


比较两个符号的优先级:

/* * 比较两个操作符的优先级, * char post:栈顶元素。char c:当前读到的元素 * 返回1:上一个操作符的优先级高于当前操作符c的优先级,返回0:两个操作符的优先级相同,返回-1:上一操作符的优先级低于当前操作符c */private static int precedence(char post, char c) {if(post=='(')return -1;//上一个操作符为')',返回-1,操作符进栈if(post=='+'||post=='-'){if(c=='*'||c=='/')//‘+’、‘-’优先级低于‘*’、‘/’return -1return -1;elsereturn 0;//c同为'+'或'-'优先级相同,return 0}else if(post=='*'||post=='/'){if(c=='+'||c=='-')return 1;else return 0; }return 0;//栈顶元素为数字,操作数与操作符比较返回0}


完整代码:

import java.util.*;public class 中缀转后缀并计算 {private static int index;public static void main(String[] args) {System.out.println("请输入中缀表达式:");Scanner sc=new Scanner(System.in);char[] infix=sc.nextLine().toCharArray();char[] postfix=new char[infix.length];infixtopostfix(infix,postfix);System.out.println("后缀表达式为:");for(int i=0;i<index;i++){System.out.print(postfix[i]);}}/* 中缀表达式转后缀表达式,结果保存在postfix数组中 * char[] infix:前缀数组。char[] postfix:后缀数组 */private static void infixtopostfix(char[] infix, char[] postfix) {index=0;//索引LinkedList<Character> st=new LinkedList();//LinkedList对象以push形式添加元素时做堆栈用,以add形式添加元素时做队列用for(int i=0;i<infix.length;i++){char c=infix[i];//获取前缀数组的各个字符if(c=='(')st.push(c);//左括号直接进栈else if(c==')'){while(st.peek()!='('){//记录下左右括号内的操作符postfix[index++]=st.pop();//碰到右括号时,弹出左右括号中的内容}st.pop();//弹出左括号}else{if(c>='0'&&c<='9')st.push(c);//数字直接进栈else{while(!st.isEmpty()&&precedence(st.peek(),c)>=0){//栈不为空&&上一个操作符的优先级高于当前操作符cpostfix[index++]=st.pop();//弹出的元素记录在后缀数组中}st.push(c);//当前操作符一定要进栈,并在下一层循环或最后弹出}}}//弹出栈中剩余的操作符while(!st.isEmpty()){postfix[index++]=st.pop();//弹出的元素记录在后缀数组中}}/* * 比较两个操作符的优先级, * char post:栈顶元素。char c:当前读到的元素 * 返回1:上一个操作符的优先级高于当前操作符c的优先级,返回0:两个操作符的优先级相同,返回-1:上一操作符的优先级低于当前操作符c */private static int precedence(char post, char c) {if(post=='(')return -1;//上一个操作符为')',返回-1,操作符进栈if(post=='+'||post=='-'){if(c=='*'||c=='/')//‘+’、‘-’优先级低于‘*’、‘/’return -1return -1;elsereturn 0;//c同为'+'或'-'优先级相同,return 0}else if(post=='*'||post=='/'){if(c=='+'||c=='-')return 1;else return 0; }return 0;//栈顶元素为数字,操作数与操作符比较返回0}}













0 0