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;

}

        


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值