Java实现二分搜索树的示例代码
作者:爱干饭的猿 发布时间:2023-08-05 10:43:40
标签:Java,二分搜索树
1.概念
a.是个二叉树(每个节点最多有两个子节点)
b.对于这棵树中的节点的节点值
左子树中的所有节点值 < 根节点 < 右子树的所有节点值
二分搜索树中一般不考虑值相等的情况(元素不重复)JDK中的搜索树就不存在相同的值(TreeMap-key)
最大特点:也是判断是否是搜索树的方法
对该树进行中序遍历,就可以得到一个升序集合0 1 2 3 4 5 6 7 8 9
在一个有序区间上进行二分查找的时间复杂度? logn不断将集合/2/2 / 2 ==1为止logN
logN =》联想到"树"
2.重点操作
当删除58时,此节点左右子树都不为空
Hibbard Deletion 1962
在BST中删除一个左右子树都存在的节点
找到当前以58为根节点的前驱或者后继节点作为删除后的新节点
前驱:在以58为根的BST中最后一个小于58的节点->53
后继:在以58为根的BST中第一个大于58的节点->59
当我们使用后继节点时,先连removeMin(root.right),在连root.left
TreeNode successor = findMin(root.right);
successor.right = removeMin(root.right);
successor.left = root.left;
3.完整代码
import java.util.NoSuchElementException;
/**
* 基于整型的
* 普通的二分搜索树
*/
public class BST {
private class TreeNode{
private int val;
private TreeNode left;
private TreeNode right;
public TreeNode(int val) {
this.val = val;
}
}
private int size;
private TreeNode root;
/**
* 向以root为根的BST中插入一个新的结点val
* @param val
*/
public void add(int val){
root = add(root,val);
}
private TreeNode add(TreeNode root, int val) {
if(root == null){
//创建一个新节点
TreeNode newNode = new TreeNode(val);
size++;
return newNode;
}
//左子树插入
if(val < root.val){
root.left = add(root.left,val);
}
//右子树插入
if(val > root.val){
root.right = add(root.right,val);
}
return root;
}
/**
* 判断当前以root为根的BST中是否包含了val
* @param val
* @return
*/
public boolean contains(int val){
return contains(root,val);
}
private boolean contains(TreeNode root, int val) {
if(root == null){
return false;
}
if(val == root.val){
//找到了
return true;
}else if(val < root.val){
//递归左子树查找
return contains(root.left,val);
}else{
//递归右子树查找
return contains(root.right,val);
}
}
/**
* 找到最小值
* @return
*/
public int findMin(){
//判空
if(root == null){
//抛出一个空指针异常
throw new NoSuchElementException("root is empty! cannot find min");
}
TreeNode minNode = findMin(root);
return minNode.val;
}
private TreeNode findMin(TreeNode root) {
//当此节点左子树为空,说明此节点是最小值
if(root.left == null){
return root;
}
//递归访问左子树
return findMin(root.left);
}
/**
* 找到最大值
* @return
*/
public int findMax(){
//判空
if(root == null){
throw new NoSuchElementException("root is empty! cannot find max");
}
TreeNode maxNode = findMax(root);
return maxNode.val;
}
private TreeNode findMax(TreeNode root) {
//当此节点右子树为空,说明此节点是最大值
if(root.right == null){
return root;
}
//递归访问右子树
return findMax(root.right);
}
/**
* 在当前BST中删除最小值节点,返回删除的最小值
* @return
*/
public int removeMin(){
int min =findMin();
root = removeMin(root);
return min;
}
private TreeNode removeMin(TreeNode root) {
if(root.left == null){
TreeNode right = root.right;
//找到最小值,删除节点
root = root.left = null;
size--;
return right;
}
root.left = removeMin(root.left);
return root;
}
/**
* 在当前BST中删除最大值节点,返回删除的最大值
* @return
*/
public int removeMax(){
int max = findMax();
root = removeMax(root);
return max;
}
//在当前以root为根的BST中删除最小值所在的节点,返回删除后的树根
private TreeNode removeMax(TreeNode root) {
if(root.right == null){
TreeNode right = root.right;
//找到最大值,删除节点
root = root.right = null;
size--;
return right;
}
root.right = findMax(root.right);
return root;
}
/**
* 在当前以root为根节点的BST中删除值为val的节点
* 返回删除后的新的根节点
* @return
*/
public void removeValue(int value){
root = removeValue(root,value);
}
private TreeNode removeValue(TreeNode root, int value) {
if(root == null){
throw new NoSuchElementException("root is empty! cannot find remove");
}else if(value < root.val){
root.left = removeValue(root.left,value);
return root;
}else if(value > root.val){
root.right = removeValue(root.right,value);
return root;
}else {
//此时value == root.value
if(root.left == null){
//删除最小数
TreeNode right = root.right;
root = root.right = null;
size--;
return right;
}
if(root.right == null){
//删除最大数
TreeNode left = root.left;
root = root.left =null;
size--;
return left;
}
//找到当前该删除节点的前驱或者后继节点作为删除后的新节点
//当我们使用后继节点时,先连removeMin(root.right),在连root.left
TreeNode successor = findMin(root.right);
successor.right = removeMin(root.right);
successor.left = root.left;
return successor;
}
}
@Override
public String toString() {
StringBuilder sb = new StringBuilder();
generateBSTString(root,0,sb);
return sb.toString();
}
//直观打印,可以看到树的深度
private void generateBSTString(TreeNode root, int height, StringBuilder sb) {
if(root == null){
sb.append(generateHeightString(height)).append("NULL\n");
return;
}
sb.append(generateHeightString(height)).append(root.val).append("\n");
generateBSTString(root.left,height+1,sb);
generateBSTString(root.right,height+1,sb);
}
private String generateHeightString(int height) {
StringBuilder sb = new StringBuilder();
for (int i = 0; i < height; i++) {
sb.append("--");
}
return sb.toString();
}
}
来源:https://blog.csdn.net/m0_62218217/article/details/123517541
0
投稿
猜你喜欢
- 了解过spring-Boot这个技术的,应该知道Spring-Boot的核心配置文件application.properties,当然也可以
- 应用场景有些时候项目中会用到很多路径,并且很可能多个路径在同一个根目录下,那为了方便配置的修改,达到只修改根目录即可达到一改全改的效果,此时
- 在使用JDBC的时候,数据库据连接是非常宝贵的资源。为了复用这些资源,可以将连接保存在一个队列中。当需要的时候可以从队列中取出未使用的连接。
- 前言:什么是多数据源?最常见的单一应用中最多涉及到一个数据库,即是一个数据源(Datasource)。那么顾名思义,多数据源就是在一个单一应
- 1、认识XML解析技术1.1、XML相关概念(1)DTD:XML语法规则,是XML文件的验证机制,可以通过比较XML文档和DTD文件看文档是
- 本文介绍了Java实现动态获取图片验证码的示例代码,分享给大家,具体如下:import javax.imageio.ImageIO;impo
- 这篇文章介绍了Java+Nginx实现POP、IMAP、SMTP邮箱代理服务,我们本次使用的环境为Centos7下,java程序我们通过ec
- 前言悬浮窗是一种比较常见的需求。例如把视频通话界面缩小成一个悬浮窗,然后用户可以在其他界面上处理事情。本文给出一个简单的应用内悬浮窗实现。可
- 本篇紧接上一篇内容继续,还是从继承里的细节开始1.代码块初始化关于代码块的定义和使用因为之前已经进行过介绍,所以这里就不再赘述,我们所关注的
- 本文实例为大家分享了javaOpenCV-4.0.0 实时人脸识别,供大家参考,具体内容如下package com.xu.opencv;im
- 由于我们在eclipse ee中把项目部署在web端经常会出现报404错误。原因为:404状态码是一种http状态码,其意思是: 所请求的页
- 假定你已经了解了运行时的数据区域和常用的垃圾回收算法,也了解了Hotspot支持的垃圾回收器。一、cpu占用过高cpu占用过高要分情况讨论,
- MediaQuery通常情况下,不会直接将MediaQuery当作一个控件,而是使用MediaQuery.of获取当前设备的信息,用法如下:
- Java中线程分为两种类型:用户线程和守护(服务)线程。通过Thread.setDaemon(false)设置为用户线程;通过Thread.
- 部分同学在使用 idea 时可能会遇到输入 sout 无法出现自动补全 System.out.println();的情况,其实 idea 默
- 一、导入和导出导入:通过解析excel表格中的数据,然后将数据放到一个集合中,接着通过对持久层操作,将数据插入到数据库中,再加载一下页面,从
- 1.在res上面右键->New->Android resource directory2.点击之后,出现下图Resource t
- mysql实现配置中心本公司配置数据的管理是通过mysql进行配置管理,因为已经搭建好了,所以自己动手重新搭建一遍,熟悉整个流程。有关项目源
- 本文实例为大家分享了C++实现俄罗斯方块的具体代码,供大家参考,具体内容如下先是效果图:主菜单:游戏:设置:错误处理:代码:#include
- 一. 概述参考开源项目https://github.com/xkcoding/spring-boot-demo在系统运维中, 有时候为了避免