@

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. Linux学习之路-Linux-at及cron命令【7】---20171215

    Linux学习之路-Linux-at及cron命令[7]---20171215 DannyExia000人评论986人阅读2017-12-24 17:28:03   ntpdate 命令 [root@ ...

  2. VMware vCenter重置web console SSO登录密码

    On a Windows Platform Services Controller or vCenter Server with Embedded Platform Services Controll ...

  3. 遇到问题 DS1302读取数据有问题

    读出的数据 错误的原因 是因为  DS1302的初始化函数中 移植的时候  没有改要使能的端口号 但是我的板子用另一个(如下的工程单独下载进板子后可以运行)还是可以用的 原因是 而我那个  读数据全为 ...

  4. F5 api接口开发实战(一)

    本人从18年下旬,开始从事F5负载均衡的自动化开发工作,主要使用python编程语言,开发的F5功能模块为LTM和GTM. F5开发简介 1.F5管理模式 F5的管理模式主要有4种(不包含snmp), ...

  5. Cannot resolve class or package 'mysql’处理方法

    在application.properties中配置mybatis_plus碰见报了这个错误 Cannot resolve class or package 'jdbc' 错误产生的原因 其实这个问题 ...

  6. Nginx的配置参数中文说明

    Nginx的配置参数中文说明   前言 Nginx是一款轻量级的Web 服务器/反向代理服务器及电子邮件(IMAP/POP3)代理服务器,在BSD-like 协议下发行.其特点是占有内存少,并发能力强 ...

  7. Step By Step(Lua-C API简介)

    Step By Step(Lua-C API简介) Lua是一种嵌入式脚本语言,即Lua不是可以单独运行的程序,在实际应用中,主要存在两种应用形式.第一种形式是,C/C++作为主程序,调用Lua代码, ...

  8. Java读取SQL server数据库

    要打开SQL server 的三个服务,然后再执行代码. package com.sql; import java.sql.SQLException; import java.sql.Statemen ...

  9. Echarts-2.2.7中统计出来的统计图保存为图片

    今天在做一个图形报表,有个需求是要把展现的统计图保存为图片, 图形报表用的Echarts-2.2.7, 以前有用过 Echarts,记得echarts插件是可以帮助我们把统计图保存为图片的. 只是不记 ...

  10. 用Auto-TensorCore代码生成优化matmul

    用Auto-TensorCore代码生成优化matmul 将演示如何使用TVM Auto TensorCore CodeGen在Volta/Turing GPU上编写高性能matmul调度.这是一个透 ...