参考博客:前缀、中缀、后缀表达式
一、表达式的三种表示法
− × ÷ 15 − 7 2 3 + 2 + 1 1 =
− × ÷ 15 5 3 + 2 + 1 1 =
− × 3 3 + 2 + 1 1 =
− 9 + 2 + 1 1 =
− 9 + 2 2 =
− 9 4 =
5
等价的中缀表达式: ((15 ÷ (7 − (1 + 1))) × 3) − (2 + (1 + 1)) = 5
扫描到的元素 | 栈(栈底到栈顶) | 说明 |
5 | 5 | 操作数直接入栈 |
3 | 5 3 | 操作数直接入栈 |
2 | 5 3 2 | 操作数直接入栈 |
* | 5 6 | 遇到操作符,弹出两个实数,求值,压栈 |
+ | 11 | 遇到操作符,弹出两个实数,求值,压栈 |
4 | 11 4 | 操作数直接入栈 |
- | 7 | 遇到操作符,弹出两个实数,求值,压栈 |
5 | 7 5 | 操作数直接入栈 |
+ | 12 | 计算结果为12 |
二 、 算法实现
public static final Pattern UNSIGNED_DOUBLE =
Pattern.compile("((\\d+\\.?\\d*)|(\\.\\d+))([Ee][-+]?\\d+)?.*?");
public static final Pattern CHARACTER =
Pattern.compile("\\S.*?");
/**
* 后缀表达式的求值算法
* @param expression
* @return
*/
public static double evaluateReversePolishNotation(String expression)
{
// 使用一个栈来保存表达式中的数值
Stack<Double> numbers = new Stack<Double>();
// 将表达式转换成一个Scanner类的对象,以便更易于处理
Scanner input = new Scanner(expression);
// next存储的是表达式的下一个片段:数值、运算符或括号
String next;
while (input.hasNext())
{
if (input.hasNext(UNSIGNED_DOUBLE))
{
next = input.findInLine(UNSIGNED_DOUBLE);
numbers.push(new Double(next));
} else {
next = input.findInLine(CHARACTER);
double operand1, operand2;
if (numbers.size() < 2)
{
throw new IllegalArgumentException("Illegal expression.");
}
switch (next.charAt(0))
{
case '+':
operand2 = numbers.pop();
operand1 = numbers.pop();
numbers.push(operand1 + operand2);
break;
case '-':
operand2 = numbers.pop();
operand1 = numbers.pop();
numbers.push(operand1 - operand2);
break;
case '*':
operand2 = numbers.pop();
operand1 = numbers.pop();
numbers.push(operand1 * operand2);
break;
case '/':
operand2 = numbers.pop();
operand1 = numbers.pop();
numbers.push(operand1 / operand2);
break;
default:
throw new IllegalArgumentException("Illegal input expression.");
}
}
}
if (numbers.size() != 1)
{
throw new IllegalArgumentException("Illegal input expression.");
}
return numbers.pop();
}
String s3 = "5 3 2 *+4-5+";
double value3 = CalculateUtils.evaluateReversePolishNotation(s3);
System.out.println(value3);
5 3 2 *+4-5+的计算结果为:12.0
// 中缀表达式转换为波兰后缀表达式的算法
public static String infixToReversePolishNotation(String expression)
{
StringBuffer outStrBuffer = new StringBuffer();
// 使用一个栈来存储运算符和括号
Stack<Character> operations = new Stack<Character>();
// 将表达式转换成一个Scanner类的对象,以便更易于处理
Scanner input = new Scanner(expression);
// next存储的是表达式的下一个片段:数值、运算符或括号
String next;
while (input.hasNext())
{
// 如果输入为数值或其他操作数,读取操作数并将它
if (input.hasNext(UNSIGNED_DOUBLE))
{
next = input.findInLine(UNSIGNED_DOUBLE);
outStrBuffer.append(next);
outStrBuffer.append(" ");
} else {
next = input.findInLine(CHARACTER);
switch (next.charAt(0))
{
case '(':
operations.push(next.charAt(0));
break;
case '+':
case '-':
case '*':
case '/':
while (true)
{
if (operations.empty() || operations.peek().equals('(') ||
priorityCompare(operations.peek(), next.charAt(0)) == -1)
{
operations.push(next.charAt(0));
break;
}
else {
outStrBuffer.append(operations.pop());
outStrBuffer.append(" ");
}
}
break;
case ')':
while (true)
{
if (!operations.peek().equals('('))
{
outStrBuffer.append(operations.pop());
outStrBuffer.append(" ");
} else {
operations.pop();
break;
}
}
break;
default:
throw new IllegalArgumentException("Illegal input expression.");
}
}
}
String s4 = "5*(9.1+3.2)/(1-5+4.88)";
String outStr = infixToReversePolishNotation(s4);
System.out.println(outStr);
double value4 = CalculateUtils.evaluateReversePolishNotation(outStr);
System.out.println(value4);
结果:5 9.1 3.2 + * 1 5 - 4.88 + /
69.88636363636364