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


猜你喜欢
- 需求:假设我们的APP有3个页面AActivity,BActivity,CActivity,我们的APP需要一直运行在前台(特殊设备),要求
- java 遍历listpackage com.tiandy.core.rest;import java.util.ArrayList;imp
- 如果有哪一个做程序员的小伙伴说自己没有遇到中文乱码问题,我是不愿意相信的。今天在做微信订阅号的智能回复时,又一时迷乱的跳进了中文乱码这个火坑
- java 中 System.out.println()和System.out.write()的区别.这两个函数一个是System
- Spring3中加强了注解的使用,其中计划任务也得到了增强,现在创建一个计划任务只需要两步就完成了:创建一个Java类,添加一个无参无返回值
- Quartz是一款开源的定时任务调度框架,Quartz的官网是:http://www.quartz-s
- 单独一个变量直接使用 @a 的形式,无需加分号,一般是直接使用已有变量,注意在使用 html 标签时
- 题意Description相信大家都做过"A+B Problem"了吧,这道题是它的加强版。输入两个整数 A , B ,
- Android 中ScrollView嵌套GridView,ListView的实例在Android开发中,经常有一些UI需要进行固定styl
- 一、万能的字符串当然,任何时候都可以使用字符串作为属性的值,从配置文件里读取出来,如下:配置文件内容为:pkslow.admin=larry
- 1,Java中操作方法:import java.io.*; public class FileInputStreamTest &
- 背景今天我们来谈一下我们自定义的一组WPF控件Form和FormItem,然后看一下如何自定义一组完整地组合WPF控件,在我们很多界面显示的
- package cn.response;import java.awt.Color;import java.awt.Font;import
- 还记得我们之前说的ListView吗,(这个难用的控件-。+)我们在用他的同时也用到了一个叫做适配器Adapter的东西。一般我们用一个类继
- MyBatis中PageHelper不生效今天使用pageHelper,发现设置了PageHelper.startPage(page, pa
- java解析json数组最简单的json数组[ { &quo
- 本文实例为大家分享了Android实现背景图滑动变大松开回弹的具体代码,供大家参考,具体内容如下原图放大后1、自定义view继承Scroll
- 在Thread中注入Bean无效在Spring项目中,有时需要新开线程完成一些复杂任务,而线程中可能需要注入一些服务。而通过Spring注入
- Android数据库中存取图片通常使用两种方式,一种是保存图片所在路径,二是将图片以二进制的形式存储(sqlite3支持BLOB数据类型)。
- 本文实例讲述了Android判断设备网络连接状态及判断连接方式的方法。分享给大家供大家参考,具体如下:在Android开发过程中,对于一个需