題目鏈接:打開題目
表達式,我們一般喜歡於寫中綴形式的,也就是num1 op num2,但是計算的時候是要考慮優先級的。而後綴表達式num1 num2 op是不需要考慮優先級的。
網上很多都是用棧來實現的,我這個是用二叉樹的結構來實現的。可以很容易想到,中綴表達式就是一個表達式二叉樹的中序遍歷的結果,而後續表達式則是後序遍歷的結果。
好,那麼我們的思路出來了,就是根據中綴式構建二叉樹,再後續遍歷輸出二叉樹。
做ACM題到現在,覺得大多數題都是一個模擬的過程,說白了,就是人思考清楚了,那麼就能編程實現。那我們想一想該怎麼轉呢? 舉個例子:
1*(1-2)-5=
1.構建二叉樹
a) 找到當前表達式運算符級別最低的(pos=k)
b) Substring(0,k)爲左子樹,遞歸建立
c) Substring(k+1)爲右子樹,遞歸建立
2.postorder()
上碼:
import java.io.BufferedInputStream;
import java.util.Scanner;
public class Main {
public static void main(String[] args) {
Scanner scanner = new Scanner(new BufferedInputStream(System.in));
int cases;
String input;
Tree T = null;// 根指針
cases = scanner.nextInt();//多少組測試數據
while (cases-- != 0) {
input = scanner.next();
input = input.substring(0, input.length() - 1);
// 去掉多餘的括號,例如((1-2))
while (canDo(input)) {
input = input.substring(1, input.length() - 1);
}
T = createTree(T, input);
postOrder(T);
System.out.println("=");
}
scanner.close();
}
private static void postOrder(Tree t) {
if (t == null) {
return;
}
postOrder(t.leftTree);
postOrder(t.rightTree);
System.out.print(t.root + " ");
}
private static Tree createTree(Tree T, String str) {
if (str.equals("")) {//當前表達式爲空
return null;
}
String[] trees = parseTree(str);// 根,左,右
T = new Tree();
T.root = trees[0];
T.leftTree = createTree(T.leftTree, trees[1]);
T.rightTree = createTree(T.rightTree, trees[2]);
return T;
}
private static String[] parseTree(String str) {
String[] res = new String[3];
char opRoot = ' ';
int k = -1, num = 0;// 括號數
for (int i = 0; i < str.length(); i++) {
char c = str.charAt(i);
// 括號外的運算符,是操作符,運算符級別低
if (num == 0 && isOp(c) && rank(c) <= rank(opRoot)) {//一定要注意這個<=,例如3/4/5,應該先計算3/4!!!!
opRoot = c;
k = i;//記錄當前表達式中優先級最低的那個運算符的位置
} else if (c == '(') {
num++;
} else if (c == ')') {
num--;
}
}
// 找到運算符了
if (k != -1) {
res[0] = new String("" + str.charAt(k));
String leftTree = str.substring(0, k);
while (canDo(leftTree)) {//去括號
leftTree = leftTree.substring(1, leftTree.length() - 1);
}
res[1] = new String(leftTree);
String rightTree = str.substring(k + 1);
// 去掉子樹兩邊的括號
while (canDo(rightTree)) {
rightTree = rightTree.substring(1, rightTree.length() - 1);
}
res[2] = new String(rightTree);
} else {// 沒找到
res[0] = str;
res[1] = "";
res[2] = "";
}
return res;
}
private static boolean canDo(String tree) {
int num = 0;
boolean flag = false;
for (int i = 0; i < tree.length() - 1; i++) {
char c = tree.charAt(i);
if (c == '(') {
num++;
flag = true;
} else if (c == ')') {
num--;
}
if (flag && num == 0) {
return false;
}
}
if (flag && tree.charAt(0) == '(')
return true;
return false;
}
private static boolean isOp(char c) {
return c == '-' || c == '+' || c == '/' || c == '*';
}
private static int rank(char c) {
if (c == '-' || c == '+') {
return 1;
} else if (c == '/' || c == '*') {
return 2;
}
return 3;
}
}
//二叉樹的類
class Tree {
String root;
Tree leftTree;
Tree rightTree;
}