@

1、二叉搜索树

1.1、 基本概念

二叉树的一个性质是一棵平均二叉树的深度要比节点个数N小得多。分析表明其平均深度为\(\mathcal{O}(\sqrt{N})\),而对于特殊类型的二叉树,即二叉查找树(binary search tree),其深度的平均值为\(\mathcal{O}(log N)\)。

二叉查找树的性质: 对于树中的每个节点X,它的左子树中所有项的值小于X中的项,而它的右子树中所有项的值大于X中的项。

由于树的递归定义,通常是递归地编写那些操作的例程。因为二叉查找树的平均深度为\(\mathcal{O}(log N)\),所以一般不必担心栈空间被用尽。

1.2、树的节点(BinaryNode)

二叉查找树要求所有的项都能够排序,有两种实现方式;

  1. 对象实现接口 Comparable, 树中的两项使用compareTo方法进行比较;
  2. 使用一个函数对象,在构造器中传入一个比较器;

本篇文章采用了构造器重载,并定义了myCompare方法,使用了泛型,因此两种方式都支持,在后续的代码实现中可以看到。

节点定义:

    /**
* 节点
*
* @param <AnyType>
*/
private static class BinaryNode<AnyType> {
BinaryNode(AnyType theElement) {
this(theElement, null, null);
} BinaryNode(AnyType theElement, BinaryNode<AnyType> left, BinaryNode<AnyType> right) {
element = theElement;
left = left;
right = right;
} AnyType element; // the data in the node
BinaryNode<AnyType> left; // Left child
BinaryNode<AnyType> right; // Right child
}

1.3、构造器和成员变量

    private BinaryNode<AnyType> root;
private Comparator<? super AnyType> cmp; /**
* 无参构造器
*/
public BinarySearchTree() {
this(null);
} /**
* 带参构造器,比较器
*
* @param c 比较器
*/
public BinarySearchTree(Comparator<? super AnyType> c) {
root = null;
cmp = c;
}

关于比较器的知识可以参考下面这篇文章:

Java中Comparator的使用

关于泛型的知识可以参考下面这篇文章:

如何理解 Java 中的 <T extends Comparable<? super T>>

1.3、公共方法(public method)

主要包括插入,删除,找到最大值、最小值,清空树,查看元素是否包含;


/**
* 清空树
*/
public void makeEmpty() {
root = null;
} public boolean isEmpty() {
return root == null;
} public boolean contains(AnyType x){
return contains(x,root);
} public AnyType findMin(){
if (isEmpty()) throw new BufferUnderflowException();
return findMin(root).element;
} public AnyType findMax(){
if (isEmpty()) throw new BufferUnderflowException();
return findMax(root).element;
} public void insert(AnyType x){
root = insert(x, root);
} public void remove(AnyType x){
root = remove(x,root);
}

1.4、比较函数

如果有比较器,就使用比较器,否则要求对象实现了Comparable接口;

    private int myCompare(AnyType lhs, AnyType rhs) {
if (cmp != null) {
return cmp.compare(lhs, rhs);
} else {
return lhs.compareTo(rhs);
}
}

1.5、contains 函数

本质就是一个树的遍历;

    private boolean contains(AnyType x, BinaryNode<AnyType> t) {
if (t == null) {
return false;
} int compareResult = myCompare(x, t.element);
if (compareResult < 0) {
return contains(x, t.left);
} else if (compareResult > 0) {
return contains(x, t.right);
} else {
return true;
}
}

1.6、findMin

因为二叉搜索树的性质,最小值一定是树的最左节点,要注意树为空的情况。

    /**
* Internal method to find the smallest item in a subtree
* @param t the node that roots the subtree
* @return node containing the smallest item
*/
private BinaryNode<AnyType> findMin(BinaryNode<AnyType> t) {
if (t == null) {
return null;
}
if (t.left == null) {
return t;
}
return findMin(t.left);
}

1.7、findMax

最右节点;

    /**
* Internal method to find the largest item in a subtree
* @param t the node that roots the subtree
* @return the node containing the largest item
*/
private BinaryNode<AnyType> findMax(BinaryNode<AnyType> t){
if (t == null){
return null;
}
if (t.right == null){
return t;
}
return findMax(t.right);
}

1.8、insert

这个主要是根据二叉搜索树的性质,注意当树为空的情况,就可以加入新的节点了,还有当该值已经存在时,默认不进行操作;

    /**
* Internal method to insert into a subtree
* @param x the item to insert
* @param t the node that roots the subtree
* @return the new root of the subtree
*/
private BinaryNode<AnyType> insert(AnyType x, BinaryNode<AnyType> t){
if (t == null){
return new BinaryNode<>(x,null,null);
}
int compareResult = myCompare(x,t.element); if (compareResult < 0){
t.left = insert(x,t.left);
}
else if (compareResult > 0){
t.right = insert(x,t.right);
}
else{
//Duplicate; do nothing
} return t;
}

1.9、remove







注意当空树时,返回null;

最后一个三元表达式,是在之前已经排除掉节点有两个儿子的情况下使用的。

    /**
* Internal method to remove from a subtree
* @param x the item to remove
* @param t the node that roots the subtree
* @return the new root of the subtree
*/
private BinaryNode<AnyType> remove(AnyType x, BinaryNode<AnyType> t){
if (t == null){
return t; // Item not found ,do nothing
}
int compareResult = myCompare(x,t.element); if (compareResult < 0){
t.left = remove(x,t.left);
}
else if (compareResult > 0){
t.right = remove(x,t.right);
}
else if (t.left !=null && t.right!=null){
//Two children
t.element = findMin(t.right).element;
t.right = remove(t.element,t.right);
}
else
t = (t.left !=null) ? t.left:t.right;
return t;
}

二、完整代码实现(Java)

/**
* @author LongRookie
* @description: 二叉搜索树
* @date 2021/6/26 19:41
*/ import com.sun.source.tree.BinaryTree; import java.nio.BufferUnderflowException;
import java.util.Comparator; /**
* 二叉搜索树
*/
public class BinarySearchTree<AnyType extends Comparable<? super AnyType>> { /**
* 节点
*
* @param <AnyType>
*/
private static class BinaryNode<AnyType> {
BinaryNode(AnyType theElement) {
this(theElement, null, null);
} BinaryNode(AnyType theElement, BinaryNode<AnyType> left, BinaryNode<AnyType> right) {
element = theElement;
left = left;
right = right;
} AnyType element; // the data in the node
BinaryNode<AnyType> left; // Left child
BinaryNode<AnyType> right; // Right child
} private BinaryNode<AnyType> root;
private Comparator<? super AnyType> cmp; /**
* 无参构造器
*/
public BinarySearchTree() {
this(null);
} /**
* 带参构造器,比较器
*
* @param c 比较器
*/
public BinarySearchTree(Comparator<? super AnyType> c) {
root = null;
cmp = c;
} /**
* 清空树
*/
public void makeEmpty() {
root = null;
} public boolean isEmpty() {
return root == null;
} public boolean contains(AnyType x){
return contains(x,root);
} public AnyType findMin(){
if (isEmpty()) throw new BufferUnderflowException();
return findMin(root).element;
} public AnyType findMax(){
if (isEmpty()) throw new BufferUnderflowException();
return findMax(root).element;
} public void insert(AnyType x){
root = insert(x, root);
} public void remove(AnyType x){
root = remove(x,root);
} private int myCompare(AnyType lhs, AnyType rhs) {
if (cmp != null) {
return cmp.compare(lhs, rhs);
} else {
return lhs.compareTo(rhs);
}
} private boolean contains(AnyType x, BinaryNode<AnyType> t) {
if (t == null) {
return false;
} int compareResult = myCompare(x, t.element);
if (compareResult < 0) {
return contains(x, t.left);
} else if (compareResult > 0) {
return contains(x, t.right);
} else {
return true;
}
} /**
* Internal method to find the smallest item in a subtree
* @param t the node that roots the subtree
* @return node containing the smallest item
*/
private BinaryNode<AnyType> findMin(BinaryNode<AnyType> t) {
if (t == null) {
return null;
}
if (t.left == null) {
return t;
}
return findMin(t.left);
} /**
* Internal method to find the largest item in a subtree
* @param t the node that roots the subtree
* @return the node containing the largest item
*/
private BinaryNode<AnyType> findMax(BinaryNode<AnyType> t){
if (t == null){
return null;
}
if (t.right == null){
return t;
}
return findMax(t.right);
} /**
* Internal method to remove from a subtree
* @param x the item to remove
* @param t the node that roots the subtree
* @return the new root of the subtree
*/
private BinaryNode<AnyType> remove(AnyType x, BinaryNode<AnyType> t){
if (t == null){
return t; // Item not found ,do nothing
}
int compareResult = myCompare(x,t.element); if (compareResult < 0){
t.left = remove(x,t.left);
}
else if (compareResult > 0){
t.right = remove(x,t.right);
}
else if (t.left !=null && t.right!=null){
//Two children
t.element = findMin(t.right).element;
t.right = remove(t.element,t.right);
}
else
t = (t.left !=null) ? t.left:t.right;
return t;
} /**
* Internal method to insert into a subtree
* @param x the item to insert
* @param t the node that roots the subtree
* @return the new root of the subtree
*/
private BinaryNode<AnyType> insert(AnyType x, BinaryNode<AnyType> t){
if (t == null){
return new BinaryNode<>(x,null,null);
}
int compareResult = myCompare(x,t.element); if (compareResult < 0){
t.left = insert(x,t.left);
}
else if (compareResult > 0){
t.right = insert(x,t.right);
}
else{
//Duplicate; do nothing
} return t;
} }

二叉搜索树(Binary Search Tree)(Java实现)的更多相关文章

  1. 编程算法 - 二叉搜索树(binary search tree) 代码(C)

    二叉搜索树(binary search tree) 代码(C) 本文地址: http://blog.csdn.net/caroline_wendy 二叉搜索树(binary search tree)能 ...

  2. 数据结构 《5》----二叉搜索树 ( Binary Search Tree )

    二叉树的一个重要应用就是查找. 二叉搜索树 满足如下的性质: 左子树的关键字 < 节点的关键字 < 右子树的关键字 1. Find(x) 有了上述的性质后,我们就可以像二分查找那样查找给定 ...

  3. [Data Structure] 二叉搜索树(Binary Search Tree) - 笔记

    1. 二叉搜索树,可以用作字典,或者优先队列. 2. 根节点 root 是树结构里面唯一一个其父节点为空的节点. 3. 二叉树搜索树的属性: 假设 x 是二叉搜索树的一个节点.如果 y 是 x 左子树 ...

  4. 二叉搜索树(Binary Search Tree)实现及测试

    转:http://blog.csdn.net/a19881029/article/details/24379339 实现代码:  Node.java  //节点类public class Node{ ...

  5. 数据结构之Binary Search Tree (Java)

    二叉查找树简介 二叉查找树(Binary Search Tree), 也成二叉搜索树.有序二叉树(ordered binary tree).排序二叉树(sorted binary tree), 是指一 ...

  6. leetcode 98 Validate Binary Search Tree ----- java

    Given a binary tree, determine if it is a valid binary search tree (BST). Assume a BST is defined as ...

  7. 二叉搜索树详解(Java实现)

    1.二叉搜索树定义 二叉搜索树,是指一棵空树或者具有下列性质的二叉树: 若任意节点的左子树不空,则左子树上所有节点的值均小于它的根节点的值: 若任意节点的右子树不空,则右子树上所有节点的值均大于它的根 ...

  8. 剑指Offer-26.二叉搜索树与双向链表(C++/Java)

    题目: 输入一棵二叉搜索树,将该二叉搜索树转换成一个排序的双向链表.要求不能创建任何新的结点,只能调整树中结点指针的指向. 分析: 创建两个指针,分别指向要处理的当前元素和当前元素的前一个元素.利用中 ...

  9. leetcode 99 Recover Binary Search Tree ----- java

    Two elements of a binary search tree (BST) are swapped by mistake. Recover the tree without changing ...

随机推荐

  1. Tracert 命令

    Tracert 命令 Tracert 命令的作用 Tracert命令诊断实用程序通过向目标计算机发送具有不同生存时间的ICMP数据包,来确定至目标计算机的路由,也就是说用来跟踪一个消息从一台计算机到另 ...

  2. 测试 USB 存储设备读写性能(Mb/s),平均读写速度等

    1.将U盘(USB3.0)插入被测试机器,假定识别设备为sdc2.创建vfat文件系统分区/dev/sdb1分区容量大于30GBumount /dev/sdc1mkfs -t vfat /dev/sd ...

  3. Redis 为什么使用跳跃表

    引言 跳跃表是一种有序的数据结构,它通过在每个节点中维持多个指向其他节点的指针,从而达到快速访问节点的目的. 什么是跳跃表 对于一个单链表来讲,即便链表中存储的数据是有序的,如果我们要想在其中查找某个 ...

  4. Socket编程——(转载)

    我们深谙信息交流的价值,那网络中进程之间如何通信,如我们每天打开浏览器浏览网页时,浏览器的进程怎么与web服务器通信的?当你用QQ聊天时,QQ进程怎么与服务器或你好友所在的QQ进程通信?这些都得靠so ...

  5. 提高IO输出速度

    用DMA内存到内存的模式,直接把Gpio_data的数据循环的搬到GPIOC的BSRR寄存器上来控制GPIOC上电平的翻转,这样使得GPIO的速度达到了最快,输出70ns的脉宽,这已经是达到了DMA总 ...

  6. eclispe--tomcat配置

    eclipse安装tomcat方法: 1.下载tomcat,从官网下载,地址:http://tomcat.apache.org/download-70.cgi 2.将下载下来的压缩包解压,放在自己想放 ...

  7. Docker学习(13) Docker容器的网络连接

    Docker容器的网络连接 Docker容器的网络基础 先安装网桥管理工具 Docker容器的互联 默认 Docker容器与外部网络的连接

  8. java中的Class.forName的作用

    Class.forName有什么作用 Class.forName(xxx.xx.xx) 返回的是一个类 首先你要明白在java里面任何class都要装载在虚拟机上才能运行.这句话就是装载类用的(和ne ...

  9. 视觉SLAM技术应用

    视觉SLAM技术应用 SLAM技术背景 SLAM技术全称Simultaneous localization and mapping,中文为"同时定位与地图构建".SLAM可以在未知 ...

  10. 广播 (broadcasting)

    广播 (broadcasting) 飞桨(PaddlePaddle,以下简称Paddle)和其他框架一样,提供的一些API支持广播(broadcasting)机制,允许在一些运算时使用不同形状的张量. ...