问题描述:输入一个只包含加减乘除和括号的合法表达式,求表达式的值。其中除表示整数。
输入格式:输入一行,包含一个表达式。
输出格式:输出这个表达式的值。
样例输入:1-2+3*(4-5)
样例输出:-4
数据规模和约定:表达式长度不超过100,表达式运算合法且运算过程都在int内进行。
思路描述:主要用栈实现。创建两个栈:数字栈和符号栈,将字符串的字符一个一个进行判断,如果是数字就进入数字栈,如果是符号就先与符号栈栈顶的符号比较优先级,优先级更大就进展,更小或相等就先把栈内符号出栈进行运算(运算时数字栈出栈两个数),再将当前符号进栈。直到字符串判别完成再进行符号栈的检查看是否为空,不为空就可以一次出栈运算(因为符号栈内的符号已经是按优先级顺序排好了的),最后数字栈中剩一个数字,即表示结果。
本代码参照网站代码撰写:
package kuaishou;
import java.util.Scanner;
import java.util.Stack;
public class Code10 {
public static void main(String[] args) {
// TODO Auto-generated method stub
Scanner sc = new Scanner(System.in);
while (sc.hasNext()) {
String str = sc.nextLine();
solution(str);
}
sc.close();
}
private static void solution(String str) {
// TODO Auto-generated method stub
Stack<Integer> numStack = new Stack<>();
Stack<Character> signalStack = new Stack<>();
int index = 0;// 记录已经执行的符号数
int len = str.length();
// System.out.println("多项式字符串长度:" + len);
while (index < len) {
// System.out.println("第" + index + "步++++++++++");
char c = str.charAt(index); // 取出这一步的符号
if (c == '(') {
// System.out.println(c + "------------进栈");
signalStack.push(c);// 若是左括号就进栈
}
// 否则要先判断优先级
else if (c == '+' || c == '-' || c == '*' || c == '/') {
int currOperLevel = getOperlevel(c);// 当前符号的优先级
while (true) {
int stackOperLevel = 0;// 栈顶元素的优先级
if (signalStack.isEmpty() == false) {
Object obj = signalStack.peek();
stackOperLevel = getOperlevel((char) obj);
}
// 若当前元素优先级大于栈顶元素的优先级则入栈
if (currOperLevel > stackOperLevel) {
// System.out.println(c + "------------进栈");
signalStack.push(c);
break;// 直到让比自己优先级高的符号都出栈运算了再把自己进栈
} else {// 不能入栈就进行计算
try {
char optemp = '0';
int num1 = 0;
int num2 = 0;
if (signalStack.isEmpty() == false) {
optemp = (char) signalStack.pop();// 取出优先级大的那个符号
}
if (numStack.isEmpty() == false) {
num1 = (int) numStack.pop();
num2 = (int) numStack.pop();// 取出数据栈中的两个数
}
/*
* System.out .println(optemp + " " + num1 + " " +
* num2); System.out.println(caculateResult(optemp,
* num2, num1) + "---------------进栈");
*/
numStack.push(caculateResult(optemp, num2, num1));// 将算出来的结果数据再次进入数据栈
} catch (Exception e) {
// TODO: handle exception
System.out.println("多项式不正确1" + str + " " + c);
e.printStackTrace();
}
}
}
} else if (c == ')') {// 右括号就返回栈顶元素,右括号是不进栈的
while (true) {
char theop = (char) signalStack.pop();
if (theop == '(') {
break;
} else {
try {
int num1 = (int) numStack.pop();
int num2 = (int) numStack.pop();
/*
* System.out.println(" " + num1 + " " + num2);
* System.out .println(caculateResult(theop, num2,
* num1) + "------------进栈");
*/
numStack.push(caculateResult(theop, num2, num1));// 运算括号内的内容
} catch (Exception e) {
// TODO: handle exception
System.out.println("多项式不正确2" + str);
e.printStackTrace();
}
}
}
} else if (c >= '0' && c <= '9') {
int tempIndex = index + 1;
while (tempIndex < len) {
char temp = str.charAt(tempIndex);// 取字符串中处于当前字符的下一位
if (temp >= '0' && temp <= '9') {
tempIndex++;// 若为数字则继续向后取
} else {
break;// 证明数字去完
}
}
String numstr = str.substring(index, tempIndex);// 截取这个字符串则为两个符号之间的数字
/*
* System.out.println("-------------" + numstr +
* "----------------");
*/
try {
int numnum = Integer.parseInt(numstr);// 将数字转换成整型便于运算
// System.out.println(numnum + "-----------进栈");
numStack.push(numnum);
index = tempIndex - 1;
} catch (Exception e) {
// TODO: handle exception
System.out.println("多项式不正确3:" + str);
e.printStackTrace();
}
}
index++;
}
// 检查符号栈是否为空
while (true) {
Object obj = null;
if (signalStack.isEmpty() == false) {
obj = signalStack.pop();
}
if (obj == null) {
break;// 为空证明运算已结束
} else {// 不为空就出栈运算
char opterTemp = (char) obj;
int num1 = (int) numStack.pop();
int num2 = (int) numStack.pop();
/*
* System.out.println(caculateResult(opterTemp, num2, num1) +
* "--------------进栈");
*/
numStack.push(caculateResult(opterTemp, num2, num1));
}
}
int result = 0;
try {
result = (int) numStack.pop();
} catch (Exception e) {
// TODO: handle exception
System.out.println("多项式不正确4" + str);
e.printStackTrace();
}
System.out.println(result);
}
/*
* 计算加减乘除余
*/
private static Integer caculateResult(char optemp, int num1, int num2) {
// TODO Auto-generated method stub
switch (optemp) {
case '+':
return num1 + num2;
case '-':
return num1 - num2;
case '*':
return num1 * num2;
case '/':
return num1 / num2;
}
return 0;
}
/*
* 返回符号优先级
*/
private static int getOperlevel(char c) {
// TODO Auto-generated method stub
switch (c) {
case '(':
return 0;
case '+':
case '-':
return 1;
case '*':
case '/':
return 2;
default:
return 0;
}
}
}