NYOJ 267郁闷的C小加(二)

题目大意:将一个中缀表达式转为后缀表达式,并计算结果,这个中缀转后缀和表达式求值的结合!!


我的理解:先说一下,我对表达式的中缀、后缀的理解。中缀式符合人们的书写习惯,但是需要考虑运算符的优先级,括号也是有优先级的,

虽然它不参加运算,但是它改变了局部表达式的优先级!!!!!而后缀变大时,是不需要考虑优先级别的,它的书写顺序和计算

顺序是一致的,我们手算的顺序其实和后缀变大时的书写顺序是一样的!!!


思路:遍历表达式,遇到数字和小数点就直接输出(多次试验,发现后缀中数字的顺序和中缀式一样的),遇到运算符就利用栈来确定它们的顺序。

数字在输出的时候也要进到数据栈里,以便求出整个表达式的值!!!


数据结构:一个运算符栈,一个数据栈


上码:

import java.io.BufferedInputStream;
import java.util.Scanner;
import java.util.Stack;

public class 郁闷的新小加二 {
	public static void main(String[] args) {
		Scanner sc = new Scanner(new BufferedInputStream(System.in));
		int cases, len;
		String input, numStr;

		Stack<Double> num = new Stack<Double>();
		Stack<Character> op = new Stack<Character>();

		cases = sc.nextInt();
		while (cases-- > 0) {
			op.clear();
			num.clear();

			input = sc.next();
			len = input.length() - 1;// 去掉'='
			numStr = "";

			for (int i = 0; i < len; i++) {
				char c = input.charAt(i);
				if (Character.isDigit(c) || c == '.') {// 数字和.
					numStr += c;
					System.out.print(c);
				} else if (c == '(') {// '('
					op.push(c);
				} else if (isSymbol(c)) {// 运算符
					if (!numStr.equals("")) {//避免遇到前面是')',(此时numStr已经被清空了),当前c是运算符!!!
						num.push(Double.valueOf(numStr));
						numStr = "";
					}

					if (!op.isEmpty() && rank(op.peek()) >= rank(c)) {
						while (!op.isEmpty() && rank(op.peek()) >= rank(c)) {
							double num2 = num.pop();
							double num1 = num.pop();
							char op1 = op.pop();
							System.out.print(op1);
							num.push(cal(num1, num2, op1));
						}
					}
					op.push(c);
				} else {// ')'
					if (!numStr.equals("")) {//避免是'))',因为遇到第一个')'时,numStr就是空了!!
						num.push(Double.valueOf(numStr));
						numStr = "";
					}
					while (op.peek() != '(') {//一直运算,直到遇到'('
						double num2 = num.pop();
						double num1 = num.pop();
						char op1 = op.pop();
						System.out.print(op1);
						num.push(cal(num1, num2, op1));
					}
					op.pop();// 弹出'('
				}
			}
			if (!numStr.equals("")) {//避免表达式的最后就是数字!!!因为只有遇到'-+*/)'时,才会把数字压入栈
				num.push(Double.valueOf(numStr));
			}
			while (!op.isEmpty()) {//当只有一个运算符的时候!!!
				double num2 = num.pop();
				double num1 = num.pop();
				char op1 = op.pop();
				System.out.print(op1);
				num.push(cal(num1, num2, op1));
			}
			System.out.printf("=\n%.2f", num.pop());
			if (cases > 0) {
				System.out.println();
			}
		}

		sc.close();
	}

	static boolean isSymbol(char c) {
		return c == '+' || c == '-' || c == '*' || c == '/';
	}

	static int rank(char c) {
		if (c == '-' || c == '+') {
			return 1;
		}
		if (c == '*' || c == '/') {
			return 2;
		}
		return 0;//把'('也当成一个运算符!!!!
	}

	static double cal(double num1, double num2, char op) {
		switch (op) {
		case '-':
			num1 -= num2;
			break;
		case '+':
			num1 += num2;
			break;
		case '*':
			num1 *= num2;
			break;
		case '/':
			num1 /= num2;
			break;
		}
		return num1;
	}
}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值