当前位置: 首页 > news >正文

【Java】构建表达式二叉树和表达式二叉树求值

问题背景

1. 实现一个简单的计算器。通过键盘输入一个包含圆括号、加减乘除等符号组成的算术表达式字符串,输出该算术表达式的值。要求:

(1)系统至少能实现加、减、乘、除等运算;

(2)利用二叉树算法思想求解表达式的值,先构造由表达式构成的二叉树,按中序、后序遍历的方式输出二叉树中的结点,然后再利用通过对二叉树进行后序遍历求解算术表达式的值。

思路描述

  • 构建表达式二叉树:先用栈将算术表达式转成后缀表达式(具体思路参考),再根据后缀表达式构建表达式二叉树,构建过程:从左到右扫描后缀表达式的每个元素:如果当前元素是操作数,则创建一个只包含该操作数的节点,并将该节点压入栈中;如果当前元素是操作符,则创建一个只包含该操作符的节点,并从栈中弹出两个节点作为其左右子节点,再将该节点压入栈中。最后栈中唯一的节点即为根节点。
  • 表达式二叉树求值:后序遍历二叉树,递归计算左右子树的值,代入运算符计算

 代码实现

//二叉链表存储二叉树
public class TreeNode {String value;TreeNode left;TreeNode right;public TreeNode(String value){this.value=value;}public TreeNode(String value, TreeNode left, TreeNode right) {this.value = value;this.left = left;this.right = right;}
}
public class Calculator {private TreeNode root;public Calculator() {root = null;}public Calculator(TreeNode root) {this.root = root;}//中缀转后缀,List中每个元素就是后缀表达式中每个操作数或运算符public static List<String> infixToPostfix(String infixExpression){Stack<Character> operatorStack=new Stack<>();List<String> postfixExpression=new ArrayList<>();for(int i=0;i<infixExpression.length();i++){//如果是数字if(Character.isDigit(infixExpression.charAt(i))){//可能是多位的数StringBuilder temp=new StringBuilder();temp.append(infixExpression.charAt(i));while (++i<infixExpression.length()&&Character.isDigit(infixExpression.charAt(i))){temp.append(infixExpression.charAt(i));}postfixExpression.add(temp.toString());i--;//while判断完后,i多往后挪了一位,所以要-1}//如果是左括号else if(infixExpression.charAt(i)=='('){operatorStack.push(infixExpression.charAt(i));}//如果是右括号,去匹配左括号else if(infixExpression.charAt(i)==')'){while (!operatorStack.empty()&&operatorStack.peek()!='('){postfixExpression.add(operatorStack.pop()+"");}operatorStack.pop();}//如果是+-*/else {//将优先级<=当前运算符优先级的运算符pop出来,追加到后缀表达式中while (!operatorStack.empty()&&getPrecedence(infixExpression.charAt(i))<=getPrecedence(operatorStack.peek())){postfixExpression.add(operatorStack.pop()+"");}operatorStack.push(infixExpression.charAt(i));}}//将栈中剩余的运算符依次pop出来追加到结果中while (!operatorStack.empty()){postfixExpression.add(operatorStack.pop()+"");}return postfixExpression;}//在中缀转后缀时要判断符号优先级private static int getPrecedence(char operator) {switch (operator) {case '+':case '-':return 1;case '*':case '/':case '%':return 2;default:return 0;}}//利用后缀表达式构建表达式二叉树public static TreeNode buildExpressionTree(List<String> postfixExpression){Stack<TreeNode> stack=new Stack<>();//从左至右遍历后缀表达式for(String str:postfixExpression){//如果是运算数if(str.charAt(0)>=48&&str.charAt(0)<=57){TreeNode treeNode = new TreeNode(str, null, null);stack.push(treeNode);} else {//如果是运算符//从栈中弹出两个节点TreeNode pop1 = stack.pop();TreeNode pop2 = stack.pop();TreeNode treeNode = new TreeNode(str, pop1, pop2);stack.push(treeNode);}}//最后栈中剩余的节点就是二叉树根节点return stack.peek();}//中序遍历表达式二叉树(左根右)public static void inorderTraversal(TreeNode treeNode){if(treeNode==null)return;inorderTraversal(treeNode.left);System.out.print(treeNode.value+" ");inorderTraversal(treeNode.right);}//后序遍历表达式二叉树(左右根)public static void postorderTraversal(TreeNode treeNode){if(treeNode==null)return;postorderTraversal(treeNode.left);postorderTraversal(treeNode.right);System.out.print(treeNode.value+" ");}//后序遍历表达式二叉树求值public int evaluateExpression(){return evaluateExpression(root);}public int evaluateExpression(TreeNode root){if(root==null){return 0;}// 递归计算左右子树的值int leftValue = evaluateExpression(root.left);int rightValue = evaluateExpression(root.right);switch (root.value){case "+":return leftValue+rightValue;case "-":return leftValue-rightValue;case "*":return leftValue*rightValue;case "/":return leftValue/rightValue;default:// 如果是操作数,则返回对应的整数值return Integer.valueOf(root.value);}}
}

 运行效果

public class Main {public static void main(String[] args) {System.out.println("请输入你要计算的表达式:");Scanner sc = new Scanner(System.in);String infixExpression = sc.next();List<String> postfixExpression = Calculator.infixToPostfix(infixExpression);//中缀转后缀TreeNode binaryTree = Calculator.buildExpressionTree(postfixExpression);//利用后缀表达式构建表达式二叉树System.out.print("中序遍历:");Calculator.inorderTraversal(binaryTree);//中序遍历System.out.println();System.out.print("后序遍历:");Calculator.postorderTraversal(binaryTree);//后序遍历System.out.println();Calculator calculator = new Calculator(binaryTree);int i = calculator.evaluateExpression();System.out.println("值为:"+i);}
}

 

相关文章:

【Java】构建表达式二叉树和表达式二叉树求值

问题背景 1. 实现一个简单的计算器。通过键盘输入一个包含圆括号、加减乘除等符号组成的算术表达式字符串&#xff0c;输出该算术表达式的值。要求&#xff1a; &#xff08;1&#xff09;系统至少能实现加、减、乘、除等运算&#xff1b; &#xff08;2&#xff09;利用二叉…...

采用Python 将PDF文件按照页码进行切分并保存

工作中经常会遇到 需要将一个大的PDF文件 进行切分&#xff0c;比如仅需要大PDF文件的某几页 或者连续几页&#xff0c;一开始都是用会员版本的WPS&#xff0c;但是对于程序员&#xff0c;就是要采用技术白嫖 这里就介绍一个 python的PDF 包 PyPDF2 其安装方式也很简单 p…...

H264视频编码原理

说到视频&#xff0c;我们首先想到的可能就是占内存。我们知道一个视频是由一连串图像序列组成的&#xff0c;视频中图像一般是 YUV 格式。假设有一个电影视频&#xff0c;分辨率是 1080P&#xff0c;帧率是 25fps&#xff0c;并且时长是 2 小时&#xff0c;如果不做视频压缩的…...

UDP实现群聊

代码&#xff1a; import java.awt.*; import java.awt.event.*; import javax.swing.*; import java.net.*; import java.io.IOException; import java.lang.String;public class liaotian extends JFrame{private static final int DEFAULT_PORT8899;private JLabel stateLB…...

服务器部署网易开源TTS | EmotiVoice部署教程

一、环境 ubuntu 20.04 python 3.8 cuda 11.8二、部署 1、docker方式部署 1.1、安装docker 如何安装docker&#xff0c;可以参考这篇文章 1.2、拉取镜像 docker run -dp 127.0.0.1:8501:8501 syq163/emoti-voice:latest2、完整安装 安装python依赖 conda create -n Emo…...

贪心算法和动态规划

目录 一、简介 二、贪心算法案例&#xff1a;活动选择问题 1.原理介绍 三、动态规划案例&#xff1a;背包问题 1.原理介绍 四、贪心算法与动态规划的区别 五、总结 作者其他文章链接 正则表达式-CSDN博客 深入理解HashMap&#xff1a;Java中的键值对存储利器-CSDN博客…...

jsp 设备预约管理系统Myeclipse开发mysql数据库web结构java编程计算机网页项目

一、源码特点 JSP 设备预约管理系统是一套完善的java web信息管理系统&#xff0c;对理解JSP java编程开发语言有帮助&#xff0c;系统具有完整的源代码和数据库&#xff0c;系统主要采用B/S模式开发。开发环境为 TOMCAT7.0,Myeclipse8.5开发&#xff0c;数据库为Mysql5.0…...

Python:核心知识点整理大全10-笔记

目录 5.4 使用 if 语句处理列表 5.4.1 检查特殊元素 toppings.py 5.4.2 确定列表不是空的 5.4.3 使用多个列表 5.5 设置 if 语句的格式 5.6 小结 第6章 字 典 6.1 一个简单的字典 alien.py 6.2 使用字典 6.2.1 访问字典中的值 6.2.2 添加键—值对 6.2.3 先创建一…...

Hive数据库系列--Hive数据类型/Hive字段类型/Hive类型转换

文章目录 一、Hive数据类型1.1、数值类型1.2、字符类型1.3、日期时间类型1.4、其他类型1.5、集合数据类型1.5.1、Struct举例1.5.2、Array举例1.5.3、Map举例 二、数据类型转换2.1、隐式转换2.2、显示转换 三、字段类型的使用3.1、DECIMAL(precision&#xff0c;scale) 本章主要…...

在Spring Cloud中使用组件Ribbon和Feign,并分别创建子模块注册到Eureka中去

ok&#xff0c;在上篇文章中我们讲了在Spring cloud中使用Zuul网关&#xff0c;这篇文章我们将Spring Cloud的五大核心组件的Ribbon和Feign分别创建一个微服务模块。 题外话&#xff0c;本篇博客就是配置子模块&#xff0c;或者说是微服务&#xff0c;然后将微服务正式启动之前…...

(JAVA)-缓冲流

缓冲流能高效的读取数据 缓冲流底层自带了8192的缓冲区提高性能&#xff0c;他在原有的流上进行了包装&#xff0c;加上了缓冲效果 原理&#xff1a; 读入时首先会将内存中缓冲区大小的数据读入缓冲区中&#xff0c;接着下次读取直接从缓冲区中读取数据&#xff0c;当缓冲区…...

Autosar UDS-CAN诊断开发02-1(CAN诊断帧格式类型详解、CANFD诊断帧格式类型详解、15765-2(CANTP层)的意义)

目录 前言 CANTP层&#xff08;15765-2协议&#xff09;存在的意义 CANTP层&#xff08;15765-2协议&#xff09;帧类型详细解读&#xff08;普通CAN格式&#xff09; 四种诊断报文类型 单帧SingleFrame(SF) 首帧&#xff1a;FirstFrame(FF) 流控帧&#xff1a;FlowCont…...

swing快速入门(三)

解答一下上一篇关于留下的关于布局管理器的疑问 上一篇 几种常见的布局管理器 看不懂&#xff1f;看不懂没关系&#xff0c;这篇是概念篇&#xff0c;大概了解一下就行~ 1.FlowLayout&#xff08;流式布局&#xff09;&#xff1a;按照从左到右、从上到下的顺序依次排列组件。…...

Swagger PHP Thinkphp 接口文档

安装 1. 安装依赖 composer require zircote/swagger-php 2. 下载Swagger UI git clone https://github.com/swagger-api/swagger-ui.git 3. 复制下载好的Swagger UI 中的dist目录到public目录中&#xff0c;修改目录名称 cp -rf swagger-ui/dist /home/htdocs/public/ m…...

12.9每日一题(备战蓝桥杯循环结构)

12.9每日一题&#xff08;备战蓝桥杯循环结构&#xff09; 题目 2165: 求平均年龄题目描述输入输出样例输入样例输出来源/分类 题解 2165: 求平均年龄题目 2166: 均值题目描述输入输出样例输入样例输出来源/分类 题解 2166: 均值题目 2167: 求整数的和与均值题目描述输入输出样…...

与时代共进退

还记得当初自己为什么选择计算机&#xff1f; 当初你问我为什么选择计算机&#xff0c;我笑着回答&#xff1a;“因为我梦想成为神奇的码农&#xff01;我想像编织魔法一样编写程序&#xff0c;创造出炫酷的虚拟世界&#xff01;”谁知道&#xff0c;我刚入门的那天&#xff0…...

Python 云服务器应用,Https,定时重启

Python 云服务器应用,Https,定时重启 环境搭建Python模块模块导入生成Flask实例GET处理启动服务器打开网页验证 GET接入证书 支持https申请证书下载证书保留 xxx.crt 和 xxx.key文件就可以了 copy到python项目目录ssl_context 配置 宝塔面板操作在www目录下新建python工作目录在…...

pytorch 笔记:dist 和 cdist

1 dist 1.1 基本使用方法 torch.dist(input, other, p2) 计算两个Tensor之间的p-范数 1.2 主要参数 input输入张量other另一个输入张量p范数 input 和 other的形状需要是可广播的 1.3 举例 import torchxtorch.randn(4) x #tensor([ 1.2698, -0.1209, 0.0462, -1.3271…...

Java的List中的各种浅拷贝和深拷贝问题

先来看一组代码 public class Temp{public static void main(String[] args) {List<Integer> list new ArrayList<>();list.add(1);list.add(2);list.add(3);List<Integer> temp list;list.add(4);System.out.println(list.toString());System.out.print…...

20231207_最新已测_Centos7.4安装nginx1.24.0_安装详细步骤---Linux工作笔记066

以前安装的太模糊了,干脆重新写一个: 1.首先下载对应的nginx-1.24.0.tar.gz安装文件 2.然后: 去执行命令 安装依赖 yum install -y gcc yum install -y pcre pcre-devel yum install -y zlib zlib-devel yum install -y openssl openssl-devel 3.然后:去解压 tar -zxvf ngi…...

【OSG学习笔记】Day 18: 碰撞检测与物理交互

物理引擎&#xff08;Physics Engine&#xff09; 物理引擎 是一种通过计算机模拟物理规律&#xff08;如力学、碰撞、重力、流体动力学等&#xff09;的软件工具或库。 它的核心目标是在虚拟环境中逼真地模拟物体的运动和交互&#xff0c;广泛应用于 游戏开发、动画制作、虚…...

【Redis技术进阶之路】「原理分析系列开篇」分析客户端和服务端网络诵信交互实现(服务端执行命令请求的过程 - 初始化服务器)

服务端执行命令请求的过程 【专栏简介】【技术大纲】【专栏目标】【目标人群】1. Redis爱好者与社区成员2. 后端开发和系统架构师3. 计算机专业的本科生及研究生 初始化服务器1. 初始化服务器状态结构初始化RedisServer变量 2. 加载相关系统配置和用户配置参数定制化配置参数案…...

postgresql|数据库|只读用户的创建和删除(备忘)

CREATE USER read_only WITH PASSWORD 密码 -- 连接到xxx数据库 \c xxx -- 授予对xxx数据库的只读权限 GRANT CONNECT ON DATABASE xxx TO read_only; GRANT USAGE ON SCHEMA public TO read_only; GRANT SELECT ON ALL TABLES IN SCHEMA public TO read_only; GRANT EXECUTE O…...

sqlserver 根据指定字符 解析拼接字符串

DECLARE LotNo NVARCHAR(50)A,B,C DECLARE xml XML ( SELECT <x> REPLACE(LotNo, ,, </x><x>) </x> ) DECLARE ErrorCode NVARCHAR(50) -- 提取 XML 中的值 SELECT value x.value(., VARCHAR(MAX))…...

C# 类和继承(抽象类)

抽象类 抽象类是指设计为被继承的类。抽象类只能被用作其他类的基类。 不能创建抽象类的实例。抽象类使用abstract修饰符声明。 抽象类可以包含抽象成员或普通的非抽象成员。抽象类的成员可以是抽象成员和普通带 实现的成员的任意组合。抽象类自己可以派生自另一个抽象类。例…...

GitFlow 工作模式(详解)

今天再学项目的过程中遇到使用gitflow模式管理代码&#xff0c;因此进行学习并且发布关于gitflow的一些思考 Git与GitFlow模式 我们在写代码的时候通常会进行网上保存&#xff0c;无论是github还是gittee&#xff0c;都是一种基于git去保存代码的形式&#xff0c;这样保存代码…...

多模态图像修复系统:基于深度学习的图片修复实现

多模态图像修复系统:基于深度学习的图片修复实现 1. 系统概述 本系统使用多模态大模型(Stable Diffusion Inpainting)实现图像修复功能,结合文本描述和图片输入,对指定区域进行内容修复。系统包含完整的数据处理、模型训练、推理部署流程。 import torch import numpy …...

【MATLAB代码】基于最大相关熵准则(MCC)的三维鲁棒卡尔曼滤波算法(MCC-KF),附源代码|订阅专栏后可直接查看

文章所述的代码实现了基于最大相关熵准则(MCC)的三维鲁棒卡尔曼滤波算法(MCC-KF),针对传感器观测数据中存在的脉冲型异常噪声问题,通过非线性加权机制提升滤波器的抗干扰能力。代码通过对比传统KF与MCC-KF在含异常值场景下的表现,验证了后者在状态估计鲁棒性方面的显著优…...

【 java 虚拟机知识 第一篇 】

目录 1.内存模型 1.1.JVM内存模型的介绍 1.2.堆和栈的区别 1.3.栈的存储细节 1.4.堆的部分 1.5.程序计数器的作用 1.6.方法区的内容 1.7.字符串池 1.8.引用类型 1.9.内存泄漏与内存溢出 1.10.会出现内存溢出的结构 1.内存模型 1.1.JVM内存模型的介绍 内存模型主要分…...

Ubuntu Cursor升级成v1.0

0. 当前版本低 使用当前 Cursor v0.50时 GitHub Copilot Chat 打不开&#xff0c;快捷键也不好用&#xff0c;当看到 Cursor 升级后&#xff0c;还是蛮高兴的 1. 下载 Cursor 下载地址&#xff1a;https://www.cursor.com/cn/downloads 点击下载 Linux (x64) &#xff0c;…...