您的位置:首页 > 编程语言 > Java开发

NYOJ467 中缀式转后缀式 java

2014-11-15 11:33 225 查看
题目链接:打开题目

表达式,我们一般喜欢于写中缀形式的,也就是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;

}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: