栈
栈是一种插入和删除操作都只能在尾端进行的线性表。它具有后进先出的性质,在各种软件系统中有着广泛的应用。
运用栈将中缀表达式转化为后缀表达式
-
中缀表达式:
一个二元运算符对应的运算量分别放在其两端,这是人们惯用且容易理解的写法。 -
后缀表达式:
一个二元运算符对应的运算量依次放在其左端(即运算符放在两运算量之后)。这一种方法不需要括号来提升子表达式的优先级,且运算符依照出现的先后顺序进行运算,不需要关心后续的表达式,非常适合计算机的计算和存储。
中缀表达式转换为后缀表达式的方法:
-
手动转换
- 将所有子表达式按照优先级加上圆括号 - 在每一个子表达式中,移动运算符的位置到两个运算量之后 - 去除所有圆括号
-
编程转换
- 建一个存放运算符的空栈 - 创建存放后缀表达式的空串 - 从左往右扫描中缀表达式: * 如果是运算量:进入空串 * 如果是运算符: 如此时栈为空:进栈 如此时非空:当前运算符优先级高于栈顶运算符:进栈 如此时非空:当前运算符优先级低于栈顶运算符:将栈顶依次追加到后缀表达式,直到栈为空或者栈顶优先级低于当前运算符 如为 “(” :直接入栈 如为 “)” :将栈顶依次出栈追加到后缀表达式,直到出现 "(“ ,则一并丢弃。 -扫描结束后,若栈非空,将栈顶依次出栈追加到后缀表达式。
简易计算器实现
此计算器能够将用户输入的中缀表达式转化为后缀表达式,完成带有括号的浮点数和多位数的加、减、乘、除、乘方、模运算。
public class Example3_3 {
public static void main(String[] args) throws Exception {
Example3_3 p = new Example3_3();
Scanner sc = new Scanner(System.in);
System.out.print("请输入中缀表达式:");
String inFix = sc.nextLine();
System.out.println();
String postFix = p.covertToPostFix(inFix);
System.out.println("\n后缀表达式为:" + postFix);
System.out.println("\n表达式运算结果为:" + p.numberCalculate(postFix));
}
public int priority(char operator)
{
switch(operator)
{
case '^': return 3;
case '%':
case '*':
case '/': return 2;
case '+':
case '-': return 1;
}
return 0;
}
public String covertToPostFix(String inFix) throws Exception{
if ("".equals(inFix) || inFix == null)
throw new Exception("错误:算术表达式不能为空");// 抛出异常
LinkStack<Character> stack = new LinkStack();
String postFix = "";
char token=' ',topToken=' ';
for (int i = 0; i < inFix.length(); i++) {
token = inFix.charAt(i);
if (token == '(') {
stack.push(token);
}
else if (token == ')') {
topToken = stack.pop();
while (topToken != '(') {
postFix = postFix + topToken;
topToken = stack.pop();
}
}
else if (isOperator(token)) {
while (!stack.isEmpty() && (priority(token) <= priority(stack.peek()))) {
topToken = stack.pop();
postFix = postFix + topToken;
}
stack.push(token);
}
else{
String number = String.valueOf(token);
while(i<inFix.length()-1){
if((inFix.charAt(i+1)>='0'&&inFix.charAt(i+1)<='9')||inFix.charAt(i+1)=='.'){
number=number.concat(String.valueOf(inFix.charAt(i+1)));
i=i+1;
}
else
break;
}
postFix = postFix + number + " ";
}
}
while (!stack.isEmpty()) {
token = stack.pop();
postFix = postFix + token;
}
return(postFix);
}
public double numberCalculate(String postFix) throws Exception{
if ("".equals(postFix) || postFix == null)
throw new Exception("错误:后缀算术表达式不能为空");// 抛出异常
LinkStack<Double> stack = new LinkStack();
for (int i = 0; i < postFix.length(); i++){
char token = postFix.charAt(i);
if (isOperator(token)){
Double d2 = stack.pop();
Double d1 = stack.pop();
double result = 0;
if (token == '+') result = d1 + d2;
if (token == '-') result = d1 - d2;
if (token == '*') result = d1 * d2;
if (token == '^') result = Math.pow(d1,d2);
if (token == '/' && d2 != 0) result = d1 / d2;
if (token == '%' && d2 != 0) result = d1 % d2;
stack.push(result);
i++;
}else {
int j = postFix.indexOf(" ",i);
String number = postFix.substring(i,j);
stack.push(Double.valueOf(number));
i=j;
}
}
return stack.pop();
}
public boolean isOperator(char c){
return (c == '+' || c == '-' || c == '*' || c == '/' || c == '^' || c == '%' );
}
}