先了解一下什么是中缀和后缀表达式
中缀表达式就是我们平常写的算式,比如2*(3+4)-8/2,它对应的后缀表达式是234+*82/-。不要着急,接下来我们看看是怎么得到后缀表达式的。
当遇到数字时,直接输出,遇到符号入栈,在入栈之前需要判断各操作符的优先级大小,判断规则如下。
===栈外>栈内: 将栈外操作符入栈
===栈外<栈内: 将栈内操作符出栈
===栈内=栈外: 规定栈内高于栈外,将栈内的出栈
===遇到 ‘(’ : 直接入栈 ,入栈后将其优先级变为最低(即栈外‘(’最高,栈内‘(’最低)
遇到 ‘)’: 出栈所有操作符直达遇到 ‘(’ (栈外右括号优先级最低,低到和栈内左括号优先级相等)
具体执行如下图:(图有些粗糙)
接下来用Java实现一下中缀表达式转后缀表达式
public class Constant {//规定了各运算符的优先级,数值越小优先级越高 /** * 表示加法 */ public static final int OPERATORS_PRIO_PLUS_IN = 4; //栈内加法 public static final int OPERATORS_PRIO_SUB_IN = 4; //栈内减法 public static final int OPERATORS_PRIO_MULTY_IN = 2; //栈内乘法 public static final int OPERATORS_PRIO_DIV_IN = 2 ; //栈内除法 public static final int OPERATORS_PRIO_LEFT_BRAK_IN = 10; //栈内左括号 public static final int OPERATORS_PRIO_PLUS_OUT = 5 ; //栈外加法 public static final int OPERATORS_PRIO_SUB_OUT = 5; //栈外减法 public static final int OPERATORS_PRIO_MULTY_OUT = 3; //栈外乘法 public static final int OPERATORS_PRIO_DIV_OUT = 3; //栈外除法 public static final int OPERATORS_PRIO_LEFT_BRAK_OUT = 1; //栈外左括号 public static final int OPERATORS_PRIO_RIGHT_BRAK_OUT = 10; //栈外右括号 public static final int OPERATORS_PRIO_ERROR = -1; }
public class TestM1 { public static int Get_Prio(char opera,boolean instack)//opera是操作符,instack表示是否在栈内 { int prio = Constant.OPERATORS_PRIO_ERROR; if(instack)//在栈内 { switch(opera) { case '+': prio = Constant.OPERATORS_PRIO_PLUS_IN; break; case '-': prio = Constant.OPERATORS_PRIO_SUB_IN; break; case '*': prio = Constant.OPERATORS_PRIO_MULTY_IN; break; case '/': prio = Constant.OPERATORS_PRIO_DIV_IN; break; case '(': prio = Constant.OPERATORS_PRIO_LEFT_BRAK_IN; break; default: prio = Constant.OPERATORS_PRIO_ERROR; break; } } else//在栈外 { switch(opera) { case '+': prio = Constant.OPERATORS_PRIO_PLUS_OUT; break; case '-': prio = Constant.OPERATORS_PRIO_SUB_OUT; break; case '*': prio = Constant.OPERATORS_PRIO_MULTY_OUT; break; case '/': prio = Constant.OPERATORS_PRIO_DIV_OUT; break; case '(': prio = Constant.OPERATORS_PRIO_LEFT_BRAK_OUT; break; case ')': prio = Constant.OPERATORS_PRIO_RIGHT_BRAK_OUT; break; default: prio = Constant.OPERATORS_PRIO_ERROR; break; } } return prio; } public static void strMidTolast(String strMid,char[] strLast){//前一个是中缀,后一个是后缀 char[] stack = new char[strMid.length()]; int top = 0; int len = strMid.length();//中缀表达式的长度 int i = 0;//计数 int j = 0;//strLast的下标 int prioIn;//栈内优先级 int prioOut;//栈外优先级 while(i != len){ //判断当前的字符是不是数字,如果是数字直接入栈 if(Character.isDigit(strMid.charAt(i))){//charAt是Stirng类型里的方法 strLast[j++] = strMid.charAt(i);//将当前字符写入后缀表达式 i++; }else{ if(top == 0){//如果栈内没有操作符,让当前操作符入栈 stack[top++] = strMid.charAt(i); }else{ prioIn = Get_Prio(stack[top - 1],true);//得到栈顶元素的优先级 prioOut = Get_Prio(strMid.charAt(i),false);//得到栈外元素的优先级 if(prioIn < prioOut){//栈内优先级高,出栈 strLast[j++] = stack[--top]; }else if(prioIn == prioOut){//左括号右括号相遇 top--;//出栈 i++; }else{//栈外优先级高于栈内 stack[top++] = strMid.charAt(i); } } } } //判断栈内是否还有运算符 while(top > 0){ strLast[j++] = stack[--top]; } }