【数据结构】什么是二叉查找树(BST)
什么是二叉查找树(BST)
1. 什么是BST
对于二叉树中的每个节点X,它的左子树中所有项的值都小于X中的项,它的右子树中所有项的值大于X中的项。这样的二叉树是二叉查找树。

以上是一颗二叉查找树,其特点是:
(1)若它的左子树不为空,则左子树上的所有节点的值都小于它的根节点的值;
(2)若它的右子树不为空,则右子树上所有节点的值都大于它的根节点的值;
(3)其他的左右子树也分别为二叉查找树;
(4)二叉查找树是动态查找表,在查找的过程中可见添加和删除相应的元素,在这些操作中需要保持二叉查找树的以上性质。
2. 二叉查找树的定义
根据二叉查找树的要求,我们首先让BinaryNode实现Comparable接口。
// 树节点
class BinaryNode implements Comparable {
Integer element;
BinaryNode left;
BinaryNode right;
public BinaryNode{
}
public BinaryNode(Integer element, BinaryNode left, BinaryNode right) {
this.element = element;
this.left = left;
this.right = right;
}
@Override
public int compareTo(@NonNull Object o) {
return this.element - (Integer) o;
}
}
下面我们完成对BinarySearchTree的定义(只定义关键轮廓,具体接口后续进行分析)。
public class BinarySearchTree {
//定义树的根节点
BinaryNode root;
public BinarySearchTree() {
this.root = null;
}
public void makeEmpty() {
this.root = null;
}
public boolean isEmpty() {
return this.root == null;
}
// 判断是否包含某个元素
public boolean contains(Integer x) {
//TODO:后续讲解
return false;
}
// 查找最小值
public BinaryNode findMin(){
//TODO:后续讲解
return null;
}
// 查找最大值
public BinaryNode findMax(){
//TODO:后续讲解
return null;
}
// 按照顺序插入值
public void insert(Integer x){
//TODO:后续讲解
}
// 删除某个值
public void remove(Integer x){
//TODO:后续讲解
}
// 打印树
public void printTree(){
//TODO:后续讲解
}
}
3. contaions操作
如果在树T中包含项X的节点,那么该操作返回true,否则返回false。
树的结构使得这种操作变得非常简单,如果T为空集,直接返回false;否则我们就对T的左子树或右子树进行递归查找,直到找到该项X。
代码实现如下:
/**
* 是否包含某个元素
* @param x 待查找对象
* @return 查找结果
*/
public boolean contains(Integer x) {
// 首次查找从根节点开始
return contains(x,root);
}
private boolean contains(Integer x, BinaryNode node) {
// 根节点为空的情况,不需要再查找
if (node == null) {
return false;
}
// 与当前节点进行比较
int compareResult = x.compareTo(node.element);
// 小于当前节点的值,就递归遍历左子树
if (compareResult < 0) {
return contains(x, node.left);
}
// 大于当前节点的值,就递归遍历右子树
else if (compareResult > 0) {
return contains(x, node.right);
}
// 等于当前节点值,直接返回
else {
return true;
}
}
4. 查找最小节点
从根开始并且只要有左子树就向左进行,终止点就是最小元素节点。
// 查找最小值
public BinaryNode findMin() {
return findMin(root);
}
private BinaryNode findMin(BinaryNode node) {
// 当前节点为null,直接返回null
if (node == null) {
return null;
}
// 不存在左子树,返回当前节点
if (node.left == null) {
return node;
}
// 递归遍历左子树
return findMin(node.left);
}
5. 查找最大节点
从根开始并且只要有右子树就向右进行,终止点就是最大元素节点。作为与findMin的对比,findMax方法我们抛弃了常用的递归,使用了常见的while循环来查找。
// 查找最大值
public BinaryNode findMax() {
return findMax(root);
}
private BinaryNode findMax(BinaryNode node) {
if (node != null) {
while (node.right != null) {
node = node.right;
}
}
return node;
}
6. insert操作
插入操作在概念上是简单的,为了将X插入树T中,我们像contains一样沿着树查找。
如果找到X,那么我们可以什么都不做,也可以做一些更新操作。
否则,就将X插入到遍历路径上的最后一个节点。(这个做法有待商榷)
代码实现如下:
public void insert(Integer x) {
root = insert(x, root);
}
// 返回的插入节点的根节点
private BinaryNode insert(Integer x, BinaryNode node) {
// 如果当前节点为null,新建节点返回
if (node == null) {
return new BinaryNode(x, null, null);
}
// 与当前节点比较
int compareResult = x.compareTo(node.element);
// 小于当前节点值,递归插入左子树,并将返回值设置为当前节点的left
if (compareResult < 0) {
node.left = insert(x, node.left);
}
// 大于当前节点值,递归插入右子树,并将返回值设置为当前节点的right
if (compareResult > 0) {
node.right = insert(x, node.right);
}
// 等于当前的值,不做任何处理
if (compareResult == 0) {
// do some update or do noting
}
return node;
}
7. 删除操作
正如许多数据结构一样,最难的操作是remove,一旦我们发现了要删除的元素,就要考虑几种可能的情况:
当待删除的节点为叶子节点时,直接删除。
当待删除节点只有一个儿子节点时,把儿子节点代替该节点的位置,然后删除该节点。
当待删除的节点有两个儿子节点时,一般的删除策略是用其右子树的最小的数据代替该节点的数据并递归删除那个节点(现在它是空的);因为右子树的最小节点不可能有左儿子,所以第二次Delete要容易。
// 删除某个值
public void remove(Integer x) {
remove(x, root);
}
private BinaryNode remove(Integer x, BinaryNode node) {
if (node == null) {
return null;
}
int compareResult = x.compareTo(node.element);
if (compareResult < 0) {
node.left = remove(x, node.left);
}
if (compareResult > 0) {
node.right = remove(x, node.right);
}
if (compareResult == 0) {
if (node.left != null && node.right != null) {
node.element = findMin(node.right).element;
node.right = remove(node.element, node.right);
} else {
node = (node.left != null) ? node.left : node.right;
}
}
return node;
}
8. 二叉查找树的局限
同样的数据,可以对应不同的二叉搜索树,如下:

二叉搜索树可能退化成链表,相应的,二叉搜索树的查找操作是和这棵树的高度相关的,而此时这颗树的高度就是这颗树的节点数n,同时二叉搜索树相应的算法全部退化成 O(n) 级别。
显然,说二叉搜索树的查找、插入、删除这三个操作都是O(lgn) 级别的,只是一个大概的估算,具体要和二叉搜索树的形状相关。但总的来说时间复杂度在o(logn)
到o(n)之间。
9. 简单总结
二叉搜索树的节点查询、构造和删除性能,与树的高度相关,如果二叉搜索树能够更“平衡”一些,避免了树结构向线性结构的倾斜,则能够显著降低时间复杂度。二叉搜索树的存储方面,相对于线性结构只需要保存元素值,树中节点需要额外的空间保存节点之间的父子关系,所以在存储消耗上要高于线性结构。
【数据结构】什么是二叉查找树(BST)的更多相关文章
- 查找系列合集-二叉查找树BST
一. 二叉树 1. 什么是二叉树? 在计算机科学中,二叉树是每个结点最多有两个子树的树结构. 通常子树被称作“左子树”(left subtree)和“右子树”(right subtree). 二叉树常 ...
- [学习笔记] 二叉查找树/BST
平衡树前传之BST 二叉查找树(\(BST\)),是一个类似于堆的数据结构, 并且,它也是平衡树的基础. 因此,让我们来了解一下二叉查找树吧. (其实本篇是作为放在平衡树前的前置知识的,但为了避免重复 ...
- 二叉查找树(BST)
二叉查找树(BST):使用中序遍历可以得到一个有序的序列
- 二叉查找树BST 模板
二叉查找树BST 就是二叉搜索树 二叉排序树. 就是满足 左儿子<父节点<右儿子 的一颗树,插入和查询复杂度最好情况都是logN的,写起来很简单. 根据BST的性质可以很好的解决这些东 ...
- 【查找结构 2】二叉查找树 [BST]
当所有的静态查找结构添加和删除一个数据的时候,整个结构都需要重建.这对于常常需要在查找过程中动态改变数据而言,是灾难性的.因此人们就必须去寻找高效的动态查找结构,我们在这讨论一个非常常用的动态查找树— ...
- 数据结构☞二叉搜索树BST
二叉查找树(Binary Search Tree),(又:二叉搜索树,二叉排序树)它可以是一棵空树,也可以是具有下列性质的二叉树: 若它的左子树不空,则左子树上所有结点的值均小于它的根结点的值: 若它 ...
- 数据结构-自平衡二叉查找树(AVL)详解
介绍: 在计算机科学中,AVL树是最先发明的自平衡二叉查找树. 在AVL树中任何节点的两个子树的高度最大差别为一,所以它也被称为高度平衡树. 查找.插入和删除在平均和最坏情况下都是O(log n).增 ...
- 二叉查找树(BST)的实现
一.二叉树介绍 二叉查找树(Binary Search Tree,BST),又称二叉排序树,也称二叉搜索树,它或者是一颗空树,或者具有如下性质的树:若它的左子树不为空,则左子树上所有节点的值都小于根节 ...
- K:二叉查找树(BST)
相关介绍: 二叉查找树(英语:Binary Search Tree),也称二叉搜索树.有序二叉树(英语:ordered binary tree),排序二叉树(英语:sorted binary tre ...
- 3.2 符号表之二叉查找树BST
一.插入和查找 1.二叉查找树(Binary Search Tree)是一棵二叉树,并且每个结点都含有一个Comparable的键,保证每个结点的键都大于其左子树中任意结点的键而小于其右子树的任意结点 ...
随机推荐
- 表删除时 Cannot delete or update a parent row: a foreign key constraint fails 异常处理
有两张表,结构如下: t_item: t_bid: id int id int n ...
- 【ES6】函数的扩展
1.函数参数默认值[详情例子参照ESMAScript 6入门 (阮一峰)] 允许为函数的参数设置默认值,即直接写在参数定义的后面.[例子1] 参数变量是默认声明的,所以不能用let或const再次声明 ...
- 在Docker中跑Hadoop与镜像制作
重复造轮子,这里使用重新打包生成一个基于Docker的Hadoop镜像: Hadoop集群依赖的软件分别为:jdk.ssh等,所以只要这两项还有Hadoop相关打包进镜像中去即可: 配置文件准 ...
- 创建基于ASP.NET core 3.1 的RazorPagesMovie项目(一)-创建和使用默认的模板
声明:参考于asp.net core 3.1 官网(以后不再说明) 本教程是系列教程中的第一个教程,介绍生成 ASP.NET Core Razor Pages Web 应用的基础知识. 在本系列结束时 ...
- 关于EXIT和BADI增强的查找
EXIT出口的查找: 方法一: 第一步:通过SE30,输入TCODE(例如ME21N),执行EXCUTE,前台创建一张采购订单.点击TIMES页签,查找EXIT开头的SAP程序. 第二步:这些fun ...
- sonar安装和使用
安装 1. 从官网下载,https://www.sonarqube.org/downloads/ 2. 下载之前要看好要求,我安装的是7.6的版本,要求是jdk1.8,mysql 5.6 到8 ,我使 ...
- 常用的数据压缩lib
最近项目需要使用数据压缩,下面针对数据压缩库进行调研,并进行简单记录,对于关于库的介绍,可以在官网阅读最新的文档,我就不在这里重复了: A fast compressor/decompressor: ...
- 剑指offer-47:不用加减乘除做加法
参考:https://www.cnblogs.com/zhangziqiu/archive/2011/03/30/ComputerCode.html <原码,反码,补码 详解> 题目描述 ...
- ASP.NET Core on K8S深入学习(11)K8S网络知多少
本篇已加入<.NET Core on K8S学习实践系列文章索引>,可以点击查看更多容器化技术相关系列文章. 一.Kubernetes网络模型 我们都知道Kubernetes作为容器编排引 ...
- SpringSession 独立使用
疯狂创客圈 Java 高并发[ 亿级流量聊天室实战]实战系列 [博客园总入口 ] 架构师成长+面试必备之 高并发基础书籍 [Netty Zookeeper Redis 高并发实战 ] 前言 Crazy ...