栈---1、中缀表达式到后缀表达式的转化 2、求解后缀表达式的值
一、中缀表达式及后缀表达式
例:典型的计算顺序为2+2*3+5=?
上面这个表达式也被成为中缀表达式。
它可以表示为2*3的乘积存为a1,让a1与2相加得到a2,最后5和a2相加得到a3,a3即为该表达式的值。
这种计算顺序可书写成:223*+5+。这便是后缀表达式。
二、实现代码
中缀表达式到后缀表达式的转化:
public class Question {
public static void getResult() {
Stack<Character> stack = new Stack<>();
String expression;
Character token;
int i = 0;
Scanner scanner = new Scanner(System.in);
expression = scanner.next();
while ((token = expression.charAt(i++)) != '=') {
if (token >= 'a' && token <= 'z') {
System.out.print(token + " ");// 非操作符直接输出
} else {
switch (token) {
case ')':// 1、移除栈中元素直到(,包括(
while (!stack.isEmpty() && stack.peek() != '(') {
System.out.print(stack.pop() + " ");
}
stack.pop();// 移除(
break;
case '(':// 2、(的优先级最高,直接放入
stack.push(token);
break;
case '^':// 取幂运算符//3、除了(,其它操作符均弹出
while (!stack.isEmpty() && !(stack.peek() == '^') && !(stack.peek() == '(')) {
System.out.print(stack.pop() + " ");
}
break;
case '*':
case '/':
// 弹出栈元素,碰见比*,/优先级低的为止
while (!stack.isEmpty() && stack.peek() != '+' && stack.peek() != '-' && stack.peek() != '(') {
System.out.print(stack.pop() + " ");
}
stack.push(token);
break;
case '+':
case '-':
// 除了(外,从栈中弹出元素,直至遇见一个优先级更低的元素
while (!stack.isEmpty() && stack.peek() != '(') {
System.out.print(stack.pop() + " ");
}
stack.push(token);
break;
}
}
}
while (!stack.isEmpty()) {
System.out.print(stack.pop());
}
System.out.println();
}
public static void main(String[] args) {
// 中缀:a+b*c+(d*e+f)*g=
// 后缀:a b c * + d e * f + g *+
getResult();
}
}
后缀表达式的计算:
public class Question {
public static double getResult(){
Stack<Double> stack=new Stack<>();
String token;
Double a,b,result=0.0;
boolean isNumber;
Scanner scanner=new Scanner(System.in);
token=scanner.next();
//等于号作为结束符号
while(token.charAt(0)!='='){
try {
isNumber=true;
result=Double.parseDouble(token);
} catch (Exception e) {
isNumber=false;//发生异常说明输入的为字母,否则为数字
}
if(isNumber){
stack.push(result);//数字放入栈中
}else{
//如果是运算符,则从栈中取出两个数完成对象的操作再放入栈中
switch (token.charAt(0)) {
case '+':
a=stack.pop();
b=stack.pop();
stack.push(a+b);
break;
case '-':
a=stack.pop();
b=stack.pop();
stack.push(a-b);
break;
case '*':
a=stack.pop();
b=stack.pop();
stack.push(a*b);
break;
case '/':
a=stack.pop();
b=stack.pop();
stack.push(a/b);
break;
case '^'://取幂运算
a=stack.pop();
b=stack.pop();
stack.push(Math.pow(b, a));
break;
default:
break;
}
}
token=scanner.next();
}
return stack.peek();//返回栈顶元素
}
public static void main(String[] args) {
System.out.println(getResult());
/*
* 1
* 2
* 1
* +
* =
* 3.0
*/
}
}
三、总结
1、中缀到后缀的转化主要就是:(特别情况)除非处理一个)时,否则绝对不会弹出(;(普通)弹出优先级大于等于要处理的元素,直到遇见优先级更低的为止。
2、通过栈的后进先出特性可以很好地计算后缀表达式的值。遇见一个数时就把它放入栈中,遇见一个运算符时,则该运算符就作用于该栈弹出的两各数上,并把得到的结果放入栈中。
Life is a journey. What we should care about is not where it’s headed but what we see and how we feel.
唯一永远不改变,是不停地改变~