思路:
1.初始化两个栈:运算符栈s1和存储中间结果的栈s2;
2.从左至右扫描中缀表达式;
3.扫描到 *** 作数直接压入栈s2中;
4.扫描到运算符时,比较其与s1栈顶运算符的优先级:
4.1若s1为空或者栈顶运算符为左括号,则直接将扫描到的运算符压入s1;
4.2否则,若扫描到的运算符优先级比s1栈顶运算符高,也将其压入栈s1;
4.3否则,将s1栈顶运算符d出并压入到栈s2中,同时再次与s1中新的栈顶运算符比较;
5.扫描到括号时:
5.1若扫描到的是左括号,则直接压入到栈s1中;
5.2若扫描到的是右括号,则依次d出s1栈顶运算符,并压入栈s2,直至遇到左括号为 止,最后将栈s1中的左括号丢弃;
6.重复步骤2-5,直到扫描到中缀表达式的最右边;
7.将s1中剩余的运算符依次d出并压入栈s2;
8.依次d出s2中的元素并输出,结果的逆序即为中缀表达式对应的后缀表达式。
注:因为栈s2在转换的过程中只入栈不出栈,且最后出栈的逆序为中缀表达式对应的后缀表达式,故下面代码中用ArrayList s2代替Stack s2。
先来看看执行结果:
具体代码如下:
package DataStructures.stack; import java.util.ArrayList; import java.util.List; import java.util.Stack; public class PolandNotation { public static void main(String[] args) { //将中缀表达式转成后缀表达式 //1.先将中缀表达式放入List中,方便遍历 //2.将得到的中缀表达式List转为后缀表达式对应的List String expression = "1+((2+3)*4)-15"; ListinfixexpressionList = toInfixexpressionList(expression); System.out.println("中缀表达式对应的List为:"+infixexpressionList); List parseSuffixexpressionList = parseSuffixexpressionList(infixexpressionList); System.out.println("后缀表达式对应的List为:"+parseSuffixexpressionList); System.out.println("1+((2+3)*4)-15="+cal(parseSuffixexpressionList)); //先定义逆波兰表达式 //(3+4)*5-6 => 34+5*6- //为了方便,逆波兰表达的数字和符号使用空格隔开 // String suffixexpression = "30 4 + 5 * 6 -"; // // List list = getListString(suffixexpression); // System.out.println("(3+4)*5-6 的逆波兰表达式为:"+list); // // System.out.println("(3+4)*5-6="+cal(list)); } //将中缀表达式转成对应的List public static List toInfixexpressionList(String s){ //定义一个List用于存放中缀表达式 List ls = new ArrayList (); //定义一个指针用于遍历中缀表达式字符串 int index = 0; //定义一个字符串,用于对表达式中多位数的拼接 String str; //每遍历一个字符串就放入c中 char c; do{ //若c不是数字,直接加入到ls中 if( (c = s.charAt(index)) < 48 || (c = s.charAt(index)) > 57){ ls.add(""+c); // ""+c可以将字符串c转为字符串 index++; } else { //若c是数字,则需要考虑多位数问题 str = ""; //每次赋值前将str清空 while( index < s.length() && (c = s.charAt(index)) >= 48 && (c = s.charAt(index)) <= 57 ){ str += c; index++; } ls.add(str); } }while (index < s.length()); return ls; } //将得到的中缀表达式List转为后缀表达式对应的List public static List parseSuffixexpressionList(List ls){ //定义两个栈 Stack s1 = new Stack ();//符号栈 List s2 = new ArrayList (); //存储中间结果 //遍历ls for(String item: ls){ //若item为数,则直接加入s2 if( item.matches("\d+")){ s2.add(item); } else if(item.equals("(")){ s1.push(item); } else if(item.equals(")")){ //若item为右括号,则依次d出s1栈顶的运算符,并压入s2,直到遇到左括号,此时将这一对括号丢弃 while (!s1.peek().equals("(")){ s2.add(s1.pop()); } s1.pop();//将左括号d出 } else { //当item的优先级小于s1栈顶的运算符,将s1栈顶运算符d出并压入s2中,再与s1中新的栈顶运算符进行比较 while ( s1.size() != 0 && Operation.getValue(item) <= Operation.getValue(s1.peek()) ){ s2.add(s1.pop()); } //将item压入栈s1 s1.push(item); } } //将s1中剩余的运算符依次弹出并压入s2 while( s1.size() != 0 ){ s2.add(s1.pop()); } return s2; } //将一个逆波兰表达式,依次将数据和运算符放入到ArrayList中 public static List getListString(String suffixexpression){ String[] split = suffixexpression.split(" "); List list = new ArrayList (); for(String s: split){ list.add(s); } return list; } public static int cal(List ls){ Stack stack = new Stack<>(); //遍历ls for(String s: ls){ if(s.matches("\d+")){ stack.push(s); } else { int num2 = Integer.parseInt(stack.pop()); int num1 = Integer.parseInt(stack.pop()); int res = 0; if(s.equals("+")){ res = num1 + num2; } else if(s.equals("-")){ res = num1 - num2; } else if(s.equals("*")){ res = num1 * num2; } else if(s.equals("/")){ res = num1 / num2; } else { throw new RuntimeException("运算符有误!"); } stack.push(res+""); } } return Integer.parseInt(stack.pop()); } } //编写一个类,返回对应的优先级数字 class Operation { private static int ADD = 1; private static int SUB = 1; private static int MUL = 1; private static int DIV = 1; //写一个方法,返回对应的优先级数字 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; default: System.out.println("不存在该运算符!"); break; } return result; } }
欢迎分享,转载请注明来源:内存溢出
评论列表(0条)