问题描述
输入一个只包含加减乖除和括号的合法表达式,求表达式的值。其中除表示整除。
输入格式
输入一行,包含一个表达式。
输出格式
输出这个表达式的值。
样例输入
1-2+3*(4-5)
样例输出
-4
数据规模和约定
表达式长度不超过100,表达式运算合法且运算过程都在int内进行。
这道题需要用到数据结构中栈的应用,利用栈的先进后出原理,先把中缀表达式转换成后缀表达式,然后进行计算;例如:
1+2+3*5+6 // 中缀表达式,意思是说运算符号在两个数的中间
1#2#+3#5#*+6#+ // 后缀表达式。符号在两个运算数后面,# 是为了区分数。
转换为后缀表达式的过程为:
- 先定义两个栈s1 和s2。s1表示用来存储数字,s2 用来存储符号。
- 遍历表达式中的字符。
- 如果为数字,则直接入s1栈,如果当前下一个字符为符号的话需要在数字后面加上’#’,来区分数字;
- 如果为字符,当为’(’ 或 当前运算符的权值大于s2栈顶的符号元素的权值时可以直接入 s2 栈。
- 当遇到 ‘)’ 时,将s2 的栈顶元素依次出栈,然后依次保存到s1 中,知道遇到 ‘(’ 时,‘(’出栈后停止出栈,‘(’不保存到 s1 中。‘)’也不保存到s2 中。就等于消去括号。
- 当权值小于栈顶元素时,也是s2 的元素依次出栈,知道当前元素大于栈顶元素后停止出栈,然后当前元素入s2 栈。
- 重复步骤 3~6,知道遍历完所有元素。
- 将s2 中的所有元素依次出栈到 s1 栈中。转换完毕。
得到运算结果的过程
- 颠倒s1 中的元素位置,s1依次出栈到s2 中。此时s1 为空,s2为后最表达式,下面将用s1保存运算的数,s2 为表达式,声明一个文本型变量num,用来拼接数字(用法见步骤3)。
- 将s2中的元素依次出栈。
- 如果是数字,并且s2栈顶元素是‘#’,那么将元素转换字符添加到num中,然后成后入s1栈并清空num用于下一个数字。如果还是数字,则用num加上当前数组继续下一次遍历。
- 如果遇到运算符号,则将s1 中从栈顶出栈两个元素,然后根据符号进行相应的运算(需要注意的是栈顶元素是第二个运算数,例如从栈顶依次出栈的数字为x , y, 在进行除运算时,需要y/x),然后将结果入s1 栈
- 重复上述步骤,直到s2 为空时,运算结束。
下面献上渣渣代码:
import java.util.Scanner;
import java.util.Stack;
public class Main {
//进行运算
public static int yunSuan(char f,int x, int y){
switch(f){
case '-':
return x-y;
case '+':
return x+y;
case '*':
return x*y;
case '/':
if(y == 0) {
new ArithmeticException().printStackTrace();
System.exit(0);
}else{
return x/y;
}
default :
return 0;
}
}
/**
* 判断是否为数字
*
* @param n
* @return
*/
public static boolean judgeNum(char n) {
if (n >= '0' && n <= '9')
return true;
return false;
}
/**
* 返回各个符号的权值
*
* @param c
* @return
*/
public static int quanZhi(char c) {
int quan = 0;
if (c == '+' || c == '-')
quan = 1;
else if (c == '*' || c == '/')
quan = 2;
else if(c == '(')
quan = 3;
return quan;
}
public static void main(String[] args) {
Scanner scan = new Scanner(System.in);
char[] biaodashi = scan.next().toCharArray();
scan.close();
Stack s1 = new Stack(); // 存储数字 48~57
Stack s2 = new Stack(); // 存储符号
for (int i = 0; i < biaodashi.length; i++) {
// 判断是符号还是数字
if (judgeNum(biaodashi[i])) {
s1.push(biaodashi[i]);
// System.out.println(biaodashi[i]);
if (i == biaodashi.length - 1 || (!judgeNum(biaodashi[i + 1])))
s1.push('#');
} else {
if (s2.empty() || biaodashi[i] == '(' || quanZhi(biaodashi[i]) > quanZhi((char) s2.peek())) {
s2.push(biaodashi[i]);
// System.out.println(11111111);
}else if(biaodashi[i] == ')'){
while (!s2.empty()) {
char c = (char)s2.pop();
if(c == '(')
break;
else{
s1.push(c);
// System.out.println(c+" 2 s1 push");
}
}
}else if(quanZhi(biaodashi[i]) <= quanZhi((char) s2.peek())){
while (!s2.empty()) {
char c = (char)s2.peek();
if(quanZhi(biaodashi[i]) > quanZhi(c) || c == '('){
break;
}else{
s1.push((char)s2.pop());
}
// System.out.println(c+" 3 s1 push");
}
s2.push(biaodashi[i]);
}
}
}
// 将s2 中的 所有元素添加到s1 末尾
while (!s2.empty()) {
s1.push((char)s2.pop());
}
// 颠倒s1 的顺序 保存到s2 中
while (!s1.empty()) {
s2.push((char)s1.pop());
}
// String s1Str = "", s2Str="";
// System.out.println("s1");
// while (!s1.empty()) {
s1Str = s1.pop() + s1Str;
// System.out.print(s1.pop());
s1Str += s1.pop();
// }
// System.out.println(s1Str);
// System.out.println("s2");
// while (!s2.empty()) {
s2Str = s2.pop() + s2Str;
// System.out.print(s2.pop());
// }
// System.out.println(s2Str);
int result = 0;
String num = "";
while(!s2.empty()){
char c = (char) s2.pop();
if(judgeNum(c)){
num += String.valueOf(c);
continue;
}
if(c == '#') {
s1.push(Integer.parseInt(num));
// System.out.println("s1 push "+num);
num = "";
}else{
int y =(int) s1.pop();
int x =(int) s1.pop();
result = yunSuan(c, x, y);
s1.push(new Integer(yunSuan(c, x, y)));
// System.out.println("s1 push "+result);
}
}
System.out.println(result);
}
}