中缀表达式转后缀表达式(逆波兰表达式)
http://0xmiracle.sinaapp.com/blog/?p=449
package com.line100;
import java.util.Stack;
// 将一个普通的中序表达式转换为逆波兰表达式的一般算法是:
// (1)首先构造一个运算符栈,此运算符在栈内遵循越往栈顶优先级越高的原则。
// (2)读入一个用中缀表示的简单算术表达式,为方便起见,设该简单算术表达式的右端多加上了优先级最低的特殊符号“#”。
// (3)从左至右扫描该算术表达式,从第一个字符开始判断,如果该字符是数字,则分析到该数字串的结束并将该数字串直接输出。
// (4)如果不是数字,该字符则是运算符,此时需比较优先关系。
// 做法如下:将该字符与运算符栈顶的运算符的优先关系相比较。如果,该字符优先关系高于此运算符栈顶的运算符,则将该运算符入栈。倘若不是的话,则将栈顶的运算符从栈中弹出,直到栈顶运算符的优先级低于当前运算符,将该字符入栈。
// (5)重复上述操作(3)-(4)直至扫描完整个简单算术表达式,确定所有字符都得到正确处理,我们便可以将中缀式表示的简单算术表达式转化为逆波兰表示的简单算术表达式。
//操作符 # ^ *,/,% +,- ( )
//isp 0 7 5 3 1 8
//icp 0 6 4 2 8 1
public class InfixToPostfix {
private static int priority(char c, boolean inStack) {
if (inStack) {
switch (c) {
case '+':
case '-':
return 3;
case '*':
case '/':
return 5;
}
} else {
switch (c) {
case '+':
case '-':
return 2;
case '*':
case '/':
return 4;
}
}
return 0;
}
public static boolean checkPush(StringBuilder sb,char follow)
{
if (follow == '-')
{
sb.append("-");
return true;
}
return false;
}
public static String toPostfix(String mid) {
StringBuilder sb = new StringBuilder();
Stack<Character> s = new Stack<Character>();
boolean printBlank = false;
for (int i = 0; i < mid.length(); i++) {
if (i == 0 && mid.charAt(i) == '-')
{
sb.append(" -");
printBlank = true;
continue;
}
char c = mid.charAt(i);
char follow = ' ';
while (c <= '9' && c >= '0' || c == '.') {
if (!printBlank) {
sb.append(" ");
printBlank = true;
}
sb.append(c);
c = mid.charAt(++i);
}
printBlank = false;
if (i< mid.length() -1)
{
follow = mid.charAt(i+1);
}
if (s.empty() || c == '(' || (!s.empty() && s.peek() == '(')) {
s.push(c);
if (follow == '-')
{
sb.append(" -");
printBlank = true;
++i;
}
continue;
}
if (c == ')') {
while (!s.empty() && s.peek() != '(') {
sb.append(" " + s.pop());
}
if (!s.empty()) {
s.pop();
}
continue;
}
if (priority(c, false) > priority(s.peek(), true)) {
s.push(c);
if (follow == '-')
{
sb.append(" -");
printBlank = true;
++i;
}
continue;
}
while (!s.empty() && priority(c, false) <= priority(s.peek(), true)) {
sb.append(" " + s.pop());
}
s.push(c);
if (follow == '-')
{
sb.append(" -");
printBlank = true;
++i;
}
}
while (!s.empty()) {
sb.append(" " + s.pop());
}
return sb.toString();
}
/**
* @param args
*/
public static void main(String[] args) {
String rpn = toPostfix("-0.5+8*(-9.7+(3+8)/-2.0)");
System.out.println(rpn);
}
}
package com.line100;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Map;
import java.util.Stack;
//http://andreinc.net/2010/10/05/converting-infix-to-rpn-shunting-yard-algorithm/
public class ReversePolishNotation {
// Associativity constants for operators
private static final int LEFT_ASSOC = 0;
private static final int RIGHT_ASSOC = 1;
// Supported operators
private static final Map<String, int[]> OPERATORS = new HashMap<String, int[]>();
static {
// Map<"token", []{precendence, associativity}>
OPERATORS.put("+", new int[] { 0, LEFT_ASSOC });
OPERATORS.put("-", new int[] { 0, LEFT_ASSOC });
OPERATORS.put("*", new int[] { 5, LEFT_ASSOC });
OPERATORS.put("/", new int[] { 5, LEFT_ASSOC });
OPERATORS.put("%", new int[] { 5, LEFT_ASSOC });
OPERATORS.put("^", new int[] { 10, RIGHT_ASSOC });
}
/**
* Test if a certain is an operator .
* @param token The token to be tested .
* @return True if token is an operator . Otherwise False .
*/
private static boolean isOperator(String token) {
return OPERATORS.containsKey(token);
}
/**
* Test the associativity of a certain operator token .
* @param token The token to be tested (needs to operator).
* @param type LEFT_ASSOC or RIGHT_ASSOC
* @return True if the tokenType equals the input parameter type .
*/
private static boolean isAssociative(String token, int type) {
if (!isOperator(token)) {
throw new IllegalArgumentException("Invalid token: " + token);
}
if (OPERATORS.get(token)[1] == type) {
return true;
}
return false;
}
/**
* Compare precendece of two operators.
* @param token1 The first operator .
* @param token2 The second operator .
* @return A negative number if token1 has a smaller precedence than token2,
* 0 if the precendences of the two tokens are equal, a positive number
* otherwise.
*/
private static final int cmpPrecedence(String token1, String token2) {
if (!isOperator(token1) || !isOperator(token2)) {
throw new IllegalArgumentException("Invalied tokens: " + token1
+ " " + token2);
}
return OPERATORS.get(token1)[0] - OPERATORS.get(token2)[0];
}
public static String[] infixToRPN(String[] inputTokens) {
ArrayList<String> out = new ArrayList<String>();
Stack<String> stack = new Stack<String>();
// For all the input tokens [S1] read the next token [S2]
for (String token : inputTokens) {
if (isOperator(token)) {
// If token is an operator (x) [S3]
while (!stack.empty() && isOperator(stack.peek())) {
// [S4]
if ((isAssociative(token, LEFT_ASSOC) && cmpPrecedence(
token, stack.peek()) <= 0)
|| (isAssociative(token, RIGHT_ASSOC) && cmpPrecedence(
token, stack.peek()) < 0)) {
out.add(stack.pop()); // [S5] [S6]
continue;
}
break;
}
// Push the new operator on the stack [S7]
stack.push(token);
} else if (token.equals("(")) {
stack.push(token); // [S8]
} else if (token.equals(")")) {
// [S9]
while (!stack.empty() && !stack.peek().equals("(")) {
out.add(stack.pop()); // [S10]
}
stack.pop(); // [S11]
} else {
out.add(token); // [S12]
}
}
while (!stack.empty()) {
out.add(stack.pop()); // [S13]
}
String[] output = new String[out.size()];
return out.toArray(output);
}
public static void main(String[] args) {
String[] input = "( 1 + -2 ) * ( 3 / 4 ) ^ ( 5 + 6 )".split(" ");
String[] output = infixToRPN(input);
for (String token : output) {
System.out.print(token + " ");
}
}
}