java 栈建立二叉树,Java描述表达式求值的两种解法:双栈结构和二叉树

Java描述表达式求值的两种解法:双栈结构和二叉树

原题大意:表达式求值

求一个非负整数四则混合运算且含嵌套括号表达式的值。如:

# 输入:

1+2*(6/2)-4

# 输出:

3.0

数据保证:

保证表达式合法(含除数不为0)。

保证运算数是非负整数。

双栈版

维护两个栈: 符号栈,数字栈,遍历输入串过程中计算

数字直接入栈

符号入栈 a. 符号栈为空 b. 当前符号优先于栈顶符号 c. 栈顶为'('

符号出栈计算: 栈顶符号非'(' 且 优先级更高.

class ExpStack {

private static final String LEVEL_OPTS = ")+-*/(";

public double solve(String input) {

Stack optStack = new Stack<>();

Stack numStack = new Stack<>();

int i = 0;

while (i < input.length()) {

if (Character.isDigit(input.charAt(i))) { // 如果是数字直接入栈

int t = 0;

for (; i < input.length() && Character.isDigit(input.charAt(i)); i++) {

t = t * 10 + input.charAt(i) - '0';

}

numStack.push((double) t);

} else {// 如果是操作符

//栈为空 或 当前优先于栈顶: 入栈

if (optStack.isEmpty() || compPriority(input.charAt(i), optStack.peek()) > 0) {

optStack.push(input.charAt(i++));

} else if (optStack.peek() == '(') { // 栈顶为左括号 '('

if (input.charAt(i) == ')') { // 括号完成: 弹出'('

optStack.pop();

} else { // 括号开始 : 入栈

optStack.push(input.charAt(i));

}

i++;

} else { // 栈顶优先级更高且非 '(' : 运算

double top = numStack.pop();

numStack.push(calc(numStack.pop(), optStack.pop(), top));

}

}

}

while (!optStack.isEmpty()) {

double top = numStack.pop();

numStack.push(calc(numStack.pop(), optStack.pop(), top));

}

return numStack.pop();

}

private int compPriority(char c1, char c2) {

return LEVEL_OPTS.indexOf(c1) - LEVEL_OPTS.indexOf(c2);

}

private double calc(double x, char o, double y) {

switch (o) {

case '+':

return x + y;

case '-':

return x - y;

case '*':

return x * y;

case '/':

return x / y;

}

return 0;

}

}

二叉树版

构建二叉树: 非叶子节点为符号,叶子节点为数字. 最终后序搜索计算 二分点: 表达式中最后一个计算的运算符

排除括号后

优先取 + | -

再考虑 * | /

class ExpTree {

private String mInput;

private java.util.LinkedList mTree;

public double solve(String input) {

mInput = input;

mTree = new java.util.LinkedList<>();

buildTree(0, mInput.length());

return dfs(mTree.size() - 1);

}

private int buildTree(int li, int ri) {

try { // 先尝试吧表达式解析为叶子节点(纯运算数)

int n = Integer.parseInt(mInput.substring(li, ri));

Node node = new Node(n, -1, -1);

mTree.addLast(node);

return mTree.size() - 1;

} catch (Exception ignore) {

}

// 找到最外层的运算符(最后一个计算的运算符,优先级最低的符号)

int opt, as = -1, md = -1, bracket = 0;

for (int i = li; i < ri; i++) {

switch (mInput.charAt(i)) {

case '(':

bracket++;

break;

case ')':

bracket--;

break;

case '+':

case '-':

if (bracket == 0) {

as = i;

}

break;

case '*':

case '/':

if (bracket == 0) {

md = i;

}

break;

}

}

opt = as < 0 ? md : as;

if (opt < 0) { // 发现这是一个被括号包裹的表达式(去掉括号重新构造)

return buildTree(li + 1, ri - 1);

}

// 依次构造左右子树

Node node = new Node(mInput.charAt(opt), buildTree(li, opt), buildTree(opt + 1, ri));

mTree.addLast(node);

return mTree.size() - 1;

}

private double dfs(int i) { // 后序遍历求解

if (mTree.get(i).lch == -1 && mTree.get(i).rch == -1) {

return mTree.get(i).num;

}

switch (mTree.get(i).opt) {

case '+':

return dfs(mTree.get(i).lch) + dfs(mTree.get(i).rch);

case '-':

return dfs(mTree.get(i).lch) - dfs(mTree.get(i).rch);

case '*':

return dfs(mTree.get(i).lch) * dfs(mTree.get(i).rch);

case '/':

return dfs(mTree.get(i).lch) / dfs(mTree.get(i).rch);

}

return 0;

}

private static class Node {

double num;

char opt;

int lch, rch;

Node(double n, int l, int r) {

num = n;

initChild(l, r);

}

Node(char o, int l, int r) {

opt = o;

initChild(l, r);

}

private void initChild(int l, int r) {

lch = l;

rch = r;

}

}

}

测试驱动函数

public class Main {

public static void main(String[] args) {

Scanner cin = new Scanner(System.in);

String input = cin.nextLine();

double t = new ExpTree().solve(input);

T.d(t);

double s = new ExpStack().solve(input);

T.d(s);

}

}

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值