问题描述
程序设计中经常使用表达式,现在需要编写程序,设计算法,利用栈,计算合法表达式结果。本题中表达式由含运算符+、-、*、/、(、)和整形常量复合而成。
程序代码
import java.util.Scanner;
import java.util.Stack;
public class Main {
public static String convert2Postfix(String infix) {
char[] chars = infix.toCharArray(); //转换为字符数组
Stack<Character> stack = new Stack<Character>(); //存放操作符
StringBuilder ans = new StringBuilder(infix.length()); //存放后缀表达式。用stringbuilder方便拼接
Character ch;
for (int i=0;i<chars.length;i++) {
Character c = chars[i];
switch (c) {
case '(':
stack.push(c);
break; //左括号直接入栈
case '*':
case '/':
while (!stack.isEmpty()) {
ch = stack.pop();
if (getPriority(ch) < 2) { //为+-操作或者(的时候,此时运算优先级低,停止弹出
stack.push(ch);
break;
} else ans.append(" " + ch);
}
stack.push(c);
ans.append(" ");
break;
case '+':
case '-':
Boolean a2 = (i!=0)&&(c=='-')&&(Character.isDigit(chars[i-1])); //表示-号前面为数字的时候
Boolean a3 = (i!=0)&&(c=='-')&&(chars[i-1]==')'); //表示-号前面为)的时候
if(a2.booleanValue()||a3.booleanValue()||c=='+') { //表示这是操作符意义上的-号或者这是加号
while (!stack.isEmpty()) {
ch = stack.pop();
if (ch == '(') { //+-的时候优先级比它低的只有(
stack.push('(');
break;
}
ans.append(" " + ch);
}
stack.push(c);
ans.append(" ");
break;
}else
{
ans.append("-"); //如果是表示负数的-号直接加到后缀表达式里面
}
case ')':
while(!stack.isEmpty()){
ch = stack.pop();
if(ch =='(')
break;
else
ans.append(" "+ch);
} //直到出现(号停止弹出
break;
default:ans.append(c); //普通数字字符直接拼接到后缀表达式里面
}
}
while (!stack.empty()) {
ans.append(" "+stack.pop());
}
return ans.toString();
}
public static int getPostfixValue(String postfix) {
String[] tokes = postfix.split(" "); //将后缀表达式按照空格分开
Stack<Integer> stack = new Stack<Integer>();
int value = 0;
for (String c : tokes) {
if (c.length()!=1 || Character.isDigit(c.charAt(0))) { //如果长度不等于1(包括-1)或者说长度为1的数就压入到栈里
stack.push(Integer.parseInt(c));
} else if (c.length()==1 && isOperator(c.charAt(0))) { //为操作符的时候
int op1 = stack.pop();
int op2 = stack.pop();
int result;
switch (c.charAt(0)) {
case '*':
result = op1 * op2;
stack.push(result);
break;
case '/':
result = op2 / op1;
stack.push(result);
break;
case '+':
result = op1 + op2;
stack.push(result);
break;
case '-':
result = op2 - op1;
stack.push(result);
break;
}
}
}
return stack.pop();
}
private static int getPriority(char operator) {
int t = 0;
if (operator == '-' || operator == '+') {
t = 1;
} else if (operator == '*' || operator == '/') {
t = 2;
}
return t;
}//获取优先级
private static boolean isOperator(char x) {
if(x=='-' || x=='+' || x=='*' || x=='/')
return true;
else
return false;
}//判断是否为操作符
public static void main(String[] args)
{
Scanner cin = new Scanner(System.in);
String expression = cin.nextLine();
System.out.println(getPostfixValue(convert2Postfix(expression)));
}//主程序
}
程序说明
将中缀表达式转换为后缀表达式后进行计算,以下引自百度百科
a. 若为 '(',入栈;
b. 若为 ')',则依次把栈中的的运算符加入后缀表达式中,直到出现'(',从栈中删除'(' ;
c. 若为 除括号外的其他运算符, 当其优先级高于除'('以外的栈顶运算符时,直接入栈。否则从栈顶开始,依次弹出比当前处理的运算符优先级高和优先级相等的运算符,直到一个比它优先级低的或者遇到了一个左括号为止。
·当扫描的中缀表达式结束时,栈中的的所有运算符出栈;
转换成后缀表达式再进行相应计算,详见注释