NYOJ467 中綴式轉後綴式 java

題目鏈接:打開題目

表達式,我們一般喜歡於寫中綴形式的,也就是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;

}

        


發佈了38 篇原創文章 · 獲贊 2 · 訪問量 1萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章