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

原题大意:表达式求值

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

# 输入:
1+2*(6/2)-4
# 输出:
3.0

数据保证:

  1. 保证表达式合法(含除数不为0)。
  2. 保证运算数是非负整数。

双栈版

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

  1. 数字直接入栈
  2. 符号入栈

    a. 符号栈为空

    b. 当前符号优先于栈顶符号

    c. 栈顶为'('
  3. 符号出栈计算: 栈顶符号非'(' 且 优先级更高.
class ExpStack {
private static final String LEVEL_OPTS = ")+-*/("; public double solve(String input) {
Stack<Character> optStack = new Stack<>();
Stack<Double> 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;
}
}

二叉树版

构建二叉树: 非叶子节点为符号,叶子节点为数字. 最终后序搜索计算

二分点: 表达式中最后一个计算的运算符

  1. 排除括号后
  2. 优先取 + | -
  3. 再考虑 * | /
class ExpTree {
private String mInput;
private java.util.LinkedList<Node> 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);
}
}

Java描述表达式求值的两种解法:双栈结构和二叉树的更多相关文章

  1. [Java]算术表达式求值之三(中序表达式转二叉树方案 支持小数)

    Entry类 这个类对表达式的合法性进行了粗筛: package com.hy; import java.io.BufferedReader; import java.io.IOException; ...

  2. 蓝桥杯算法训练 java算法 表达式求值

    问题描述 输入一个只包含加减乖除和括号的合法表达式,求表达式的值.其中除表示整除. 输入格式 输入一行,包含一个表达式. 输出格式 输出这个表达式的值. 样例输入 1-2+3*(4-5) 样例输出 - ...

  3. [Java]算术表达式求值之二(中序表达式转后序表达式方案,支持小数)

    Inlet类,入口类,这个类的主要用途是验证用户输入的算术表达式: package com.hy; import java.io.BufferedReader; import java.io.IOEx ...

  4. java实现表达式求值 (20 分)-------非递归版

    Dr.Kong设计的机器人卡多掌握了加减法运算以后,最近由学会了一些简单的函数求值.比如,它知道函数min(20, 23)的值是20, add(10, 98)的值是108等等.经过训练,Dr.Kong ...

  5. [Java]算术表达式求值之一(中序表达式转后序表达式方案)

    第二版请见:https://www.cnblogs.com/xiandedanteng/p/11451359.html 入口类,这个类的主要用途是粗筛用户输入的算术表达式: package com.h ...

  6. 《EOPL》: 实现了惰性求值的两种参数传递策略

    call-by-need 不过是比 call-by-name 多了一个 memorization 的步骤

  7. hdu 4192 (表达式求值)

    <题目链接> <转载于 >>>  > 题目大意: 给你n个数,和一个最终的结果,再给你一个含有n个不同变量的式子,问你这个式子最终能否得到指定的答案. 解题分 ...

  8. 利用栈实现算术表达式求值(Java语言描述)

    利用栈实现算术表达式求值(Java语言描述) 算术表达式求值是栈的典型应用,自己写栈,实现Java栈算术表达式求值,涉及栈,编译原理方面的知识.声明:部分代码参考自茫茫大海的专栏. 链栈的实现: pa ...

  9. java实现算术表达式求值

    需要根据配置的表达式(例如:5+12*(3+5)/7.0)计算出相应的结果,因此使用java中的栈利用后缀表达式的方式实现该工具类. 后缀表达式就是将操作符放在操作数的后面展示的方式,例如:3+2 后 ...

随机推荐

  1. 「Sqlserver」数据分析师有理由爱Sqlserver之九-无利益关系推荐Sqlserver书单

    在前面系列文章的讲述下,部分读者有兴趣进入Sqlserver的世界的话,笔者不太可能在自媒体的载体上给予全方位的带领,最合适的方式是通过系统的书籍来学习,此篇给大家梳理下笔者曾经看过的自觉不错值得推荐 ...

  2. [NLP-ASR] 语音识别项目整理(一) 语音预处理

      简介 之前参与过114对话系统的项目,中间搁置很久,现在把之前做过的内容整理一下,一是为自己回顾,二是也希望分享自己看的内容,中间也遇到一些问题,如果您可以提一些建议将不胜感激. 114查询主要分 ...

  3. luogu题解 P3388 【【模板】割点(割顶)】

    外加定义:在一个无向图中,如果删掉点 x 后图的连通块数量增加,则称点 x 为图的割点. 外加图示 开始思路为割桥上的点为割点,后来证明的确正确. 不过可惜的是他的逆定理错了(gg了),不过数据很弱以 ...

  4. python找质数对

    python找质数对 编写python脚本,输入一个正整数,输出有几对质数的和等于这个正整数. 例如输入一个正整数10,可以找出有“3+7=10”.“5+5=10”两个质数对的和为10. 要实现这个功 ...

  5. 【Unity游戏开发】不接SDK也能在游戏内拉起加QQ群操作?

    一.引子 一般在游戏进行对外测试的时候都会有一个玩家QQ群,方便玩家反馈问题.交流游戏心得等.那么为了增加玩家加QQ群的欲望,可能会在游戏里面设计一个小功能,点击一下可以直接拉起手Q加群的操作,加了Q ...

  6. 实现跳转的jsp小例子

    <%@page import="java.io.UnsupportedEncodingException"%> <%@ page language="j ...

  7. 【Mac】解压文件夹中文乱码

    Mac 用的英文系统,发现下载含中文的文件后,解压为乱码,如图所示: 解决方法: 下载一个解压软件:"The Unarchiver" 安装后设置下,如图: 之后设置压缩文件的默认打 ...

  8. K8S 部署 Web UI

    在早期的版本中 Kubernetes可以在 Dashboard 中看到 heapster 提供的一些图表信息, 在后续的版本中会陆续移除掉 heapster,现在更加流行的监控工具是 promethe ...

  9. 实时同步lsyncd

    实时同步lsyncd 1 lsyncd 1.1 lsyncd 简介 Lsyncd使用文件系统事件接口(inotify或fsevents)来监视对本地文件和目录的更改.Lsyncd将这些事件整理几秒钟, ...

  10. 放出一批jsp图书管理系统图书借阅系统源码代码运行

    基于jsp+mysql的JSP图书销售管理系统 https://www.icodedock.com/article/105.html基于jsp+Spring+Spring MVC的Spring图书借阅 ...