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;
}
表达式,我们一般喜欢于写中缀形式的,也就是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;
}
相关文章推荐
- NYOJ 467 中缀式变后缀式【栈】
- NYOJ467 中缀式变后缀式 【栈】
- NYOJ-467 中缀式变后缀式【逆波兰法】
- nyoj 467 中缀式变后缀式 nyoj 257 郁闷的C小加(一)
- 中缀式变后缀式(nyoj 467)
- nyoj-409 郁闷的C小加(三) (表达式求值,中缀式转前缀式,中缀式转后缀式)
- nyoj 467 中缀事变后缀式
- NYOJ-35-表达式求值(中缀式转后缀式 逆波兰表达式)
- nyoj 1272 表达式求值(中缀式转后缀式)
- 第九届河南省程序设计大赛-NYOJ-1272-表达式求值(中缀式转后缀式 逆波兰表达式)
- nyoj467 中缀式变后缀式
- NYOJ 144 某种序列 java
- [转]手工转换中缀式与前、后缀式
- 数据结构实验之栈二:一般算术表达式转换成前缀式,中缀式,后缀式
- NYOJ-88-汉诺塔(一)(大数,java)
- NYOJ 467
- 中缀式转换为后缀式(逆波兰式)方法
- 后缀式中中缀式
- [原]NYOJ-括号匹配-2(java)
- 中缀式转后缀表达式 -NYOJ 题目267郁闷的C小加(二)