2+(3*5)/4+8 这个运算表达式相信大家觉得很简单吧,但通过程序怎么实现一位数四则运算的功能呢?这里,我们需要用到一种经典的数据结构,那就是栈。大家都知道,栈是先进后出(FILO)型的,正是这个特性,才能帮助我们实现四则运算功能。
另外,有一个很重要的概念,那就是后序表达式,说到这里,不知道大家还知道前序表达式,中序表达式吗,举个例子:
3+(5-2)/2这是个中序表达式,这正是我们日常用到的,它的后序表达式是352-2/+,如何由中序表达式得到后序表达式呢?是这样的,遍历表达式的每一个字符,遇到数字则直接打印;遇到运算符或者括号就要判断了,如果是高优先级的运算符,如*,/则直接压入栈中,如果是低优先级,如+,-则要判断此时栈顶元素是否是高优先的运算符了,如果是则弹栈,弹出的运算符直接打印,然后再判断栈顶元素是否是高优先级运算符,直到栈顶不是高优先级运算符,此时就可以将这个低优先级算符压入栈中了;如果是 ( 则压栈,如果是)则要将(与其上的其它运算符弹出,记住,此时按弹出顺序打印,(与)不用打印,记住如果遍历运算串后,栈中还有元素,则需要全部按弹出顺序打印。这样,就完成了转换过程。我们发现后序表达式没有(与),而且没有二异性,前序表达式和它很类似,这里就不做介绍了。
得到后序表达式,那怎么计算出最后结果呢?还是上面的那个例子,后序表达式是352-2/+,这里我们还是要用到栈,要遍历后序表达式,遇到数字就压入栈,遇到运算符就弹出栈顶的两个元素进行运算,将计算结果在压入栈。我们来分析一下,3,5,2依序压入栈,然后是-,此时弹出5,2计算结果是3,将3压入栈,此时栈中元素的3,3现在把后面的2再压栈就是3,3,2了,然后是/弹出3,2计算结果1再压栈,栈中元素现在是3,1最后是+,很简单就得到结果4。
过程就是这样,下面是代码
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.Stack;
/**
* 利用栈实现一位数四则运算
*
* @author Administrator
*
*/
public class ArithmeticOperation {
public static void main(String[] args) {
StringBuffer buffer = new StringBuffer();
BufferedReader reader = new BufferedReader(new InputStreamReader(
System.in));
// 创建栈对象
Stack<Character> s1 = new Stack<>();
Stack<Integer> s2 = new Stack<>();
try {
String line = reader.readLine();
getBackExpression(buffer, line, s1);
System.out.println(line = buffer.toString());
System.out.println(getResult(s2, line));
} catch (IOException e) {
e.printStackTrace();
}
}
private static int getResult(Stack<Integer> s, String line) {
char[] array = line.toCharArray();
for (int i = 0; i < array.length; i++) {
char c = array[i];
if (c >= '0' && c <= '9') {
// 为数字则压栈
s.push((int)(c-'0'));
} else {
int b = s.pop();
int a = s.pop();
switch (c) {
case '+':
s.push(a + b);
break;
case '-':
s.push(a - b);
break;
case '*':
s.push(a * b);
break;
case '/':
s.push(a / b);
break;
default:
break;
}
}
}
return s.pop();
}
/**
* 中序表达式得到后序表达式
*
* @param buffer
* @param line
* @param s
* @throws IOException
*/
private static void getBackExpression(StringBuffer buffer, String line,
Stack<Character> s) throws IOException {
// 将中缀表达式转换为后缀表达式
char[] array = line.toCharArray();
Character temp;
for (int i = 0; i < array.length; i++) {
char c = array[i];
if (c >= '0' && c <= '9') {
// 是数字则直接打印
buffer.append(c);
} else if (c == '*' || c == '/' || c == '(') {
// 直接压栈
s.push(c);
} else if (c == '+' || c == '-') {
if (s.size() != 0) {
temp = s.peek();
for (; temp == '*' || temp == '/';) {
buffer.append(s.pop());
if (s.size() != 0) {
temp = s.peek();
} else {
break;
}
}
}
// 将优先级高的运算符弹栈后再压栈
s.push(c);
} else if (c == ')') {
while ((temp = s.pop()) != '(') {
buffer.append(temp);
}
}
}
// 将栈中余下的数弹出
while (s.size() != 0 && (temp = s.pop()) != null) {
buffer.append(temp);
}
}
}