前、中、后缀表达式【待完成】
这里所谓的前缀,中缀,后缀是根据操作符的位置来定的,如果操作符在操作数前面,则称为前缀表达式,例如“- + 1 × + 2 3 4 5”;如果操作符在操作数之间,则称为中缀表达式,例如
“1+((2+3)×4)-5”;如果操作符在操作数后面,则称为后缀表达式,例如“1 2 3 + 4 × + 5 -”。
虽然中缀表达式符合人类的日常思维习惯,但是计算机在存储中缀表达式时,需要使用树这种数据结构,如果表达式过于复杂,那么树的高度会变得很高,大大增加了时间复杂度和空间复杂度。如果转换成线性结构,那么效率将变得高很多,所以需要将中缀表达式先转换成前缀或者后缀表达式,然后依靠栈这种线性数据结构来进行计算。
前缀表达式又叫波兰表达式,后缀表达式又叫逆波兰表达式。前缀表达式基本没有在商业计算机中使用过,所以现实中用的更多的是后缀表达式。
1,前缀表达式
2,中缀表达式
2.1 中缀表达式转后缀表达式
中缀表达式为:1+(2-3)*4+4/2
对应后缀表达式为:1 2 3 - 4* + 4 2 / +
如何将一个中缀表达式转化为后缀表达式?我们需要借助栈的力量,用它来存放运算符。算法流程如下:
首先将各种运算符(包括括号)的优先级排列如下(数字越大,优先级越高):
1:(
2:+ -
3:* /
4:)
对输入的中缀表达式从左到右遍历:
1)如果遇到数字,直接添加到后缀表达式末尾;
2)如果遇到运算符+、-、*、/:
先判断栈是否为空。若是,则直接将此运算符压入栈。若不是,则查看当前栈顶元素。若栈顶元素优先级大于或等于此操作符级别,则弹出栈顶元素,将栈顶元素添加到后缀表达式中,并继续进行上述判断。如果不满足上述判断或者栈为空,将这个运算符入栈。要注意的是,经过上述步骤,这个运算符最终一定会入栈。
3)如果遇到括号:
如果是左括号,直接入栈。如果是右括号,弹出栈中第一个左括号前所有的操作符,并将左括号弹出。(右括号别入栈)。
4)字符串遍历结束后,如果栈不为空,则弹出栈中所有元素,将它们添加到后缀表达式的末尾,直到栈为空。
2.2 中缀表达式直接计算
3,后缀表达式【很简单,一个Stack解决问题】
也称为逆波兰表达式
package com.cnblogs.mufasa.Main_last; import org.junit.Test; import java.util.Scanner; import java.util.Stack; public class Main { public static void Solution(String str){ Stack<Float> stack=new Stack<>(); String[] strs=str.split(" "); for(int i=0;i<strs.length;i++){ if(strs[i].matches("([0-9]+)\\.?([0-9]*)")){//是一个数字,可能是多位的 stack.add(Float.valueOf(strs[i])); }else { float num1=stack.pop(); float num2=stack.pop(); stack.add(dealCalcu(num1,num2,strs[i])); } } System.out.print(stack.pop()); } private static float dealCalcu(float num1,float num2,String str){ switch (str){ case "+":return num1+num2; case "-":return num1-num2; case "*":return num1*num2; case "×":return num1*num2; case "X":return num1*num2; case "/":return num1/num2; default:throw new UnsupportedOperationException("非法运算符"); } } @Test public void LastCalcu (){ String str="1.11 2 3 + 4 * + 5 -"; Solution(str); } public static void main(String[] args) { Scanner sc=new Scanner(System.in); Solution(sc.nextLine()); } } /* 1 2 3 + 4 * + 5 - */