參考博客:前綴、中綴、後綴表達式
一、表達式的三種表示法
− × ÷ 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