简介

树是类似于链表的数据结构,和链表的线性结构不同的是,树是具有层次结构的非线性的数据结构。

树是由很多个节点组成的,每个节点可以指向很多个节点。

如果一个树中的每个节点都只有0,1,2个子节点的话,这颗树就被称为二叉树,如果我们对二叉树进行一定的排序。

比如,对于二叉树中的每个节点,如果左子树节点的元素都小于根节点,而右子树的节点的元素都大于根节点,那么这样的树被叫做二叉搜索树(Binary Search Tree)简称BST。

今天我们来探讨一下BST的性质和对BST的基本操作。

BST的基本性质

刚刚我们已经讲过BST的基本特征了,现在我们再来总结一下:

  1. BST中任意节点的左子树一定要比该节点的值要小
  2. BST中任意节点的右子树一定要比该节点的值要大
  3. BST中任意节点的左右子树一定要是一个BST。

看一张图直观的感受一下BST:

BST的构建

怎么用代码来构建一个BST呢?

首先,BST是由一个一个的节点Node组成的,Node节点除了保存节点的数据之外,还需要指向左右两个子节点,这样我们的BST完全可以由Node连接而成。

另外我们还需要一个root节点来表示BST的根节点。

相应的代码如下:

public class BinarySearchTree {

    //根节点
Node root; class Node {
int data;
Node left;
Node right; public Node(int data) {
this.data = data;
left = right = null;
}
}
}

BST的搜索

先看下BST的搜索,如果是上面的BST,我们想搜索32这个节点应该是什么样的步骤呢?

先上图:

搜索的基本步骤是:

  1. 从根节点41出发,比较根节点和搜索值的大小
  2. 如果搜索值小于节点值,那么递归搜索左侧树
  3. 如果搜索值大于节点值,那么递归搜索右侧树
  4. 如果节点匹配,则直接返回即可。

相应的java代码如下:

//搜索方法,默认从根节点搜索
public Node search(int data){
return search(root,data);
} //递归搜索节点
private Node search(Node node, int data)
{
// 如果节点匹配,则返回节点
if (node==null || node.data==data)
return node; // 节点数据大于要搜索的数据,则继续搜索左边节点
if (node.data > data)
return search(node.left, data); // 如果节点数据小于要搜素的数据,则继续搜索右边节点
return search(node.right, data);
}

BST的插入

搜索讲完了,我们再讲BST的插入。

先看一个动画:

上的例子中,我们向BST中插入两个节点30和55。

插入的逻辑是这样的:

  1. 从根节点出发,比较节点数据和要插入的数据
  2. 如果要插入的数据小于节点数据,则递归左子树插入
  3. 如果要插入的数据大于节点数据,则递归右子树插入
  4. 如果根节点为空,则插入当前数据作为根节点

相应的java代码如下:

// 插入新节点,从根节点开始插入
public void insert(int data) {
root = insert(root, data);
} //递归插入新节点
private Node insert(Node node, int data) { //如果节点为空,则创建新的节点
if (node == null) {
node = new Node(data);
return node;
} //节点不为空,则进行比较,从而递归进行左侧插入或者右侧插入
if (data < node.data)
node.left = insert(node.left, data);
else if (data > node.data)
node.right = insert(node.right, data); //返回插入后的节点
return node;
}

BST的删除

BST的删除要比插入复杂一点,因为插入总是插入到叶子节点,而删除可能删除的是非叶子节点。

我们先看一个删除叶子节点的例子:

上面的例子中,我们删除了30和55这两个节点。

可以看到,删除叶子节点是相对简单的,找到之后删除即可。

我们再来看一个比较复杂的例子,比如我们要删除65这个节点:

可以看到需要找到65这个节点的右子树中最小的那个,替换掉65这个节点即可(当然也可以找到左子树中最大的那个)。

所以删除逻辑是这样的:

  1. 从根节点开始,比较要删除节点和根节点的大小
  2. 如果要删除节点比根节点小,则递归删除左子树
  3. 如果要删除节点比根节点大,则递归删除右子树
  4. 如果节点匹配,又有两种情况
  5. 如果是单边节点,直接返回节点的另外一边
  6. 如果是双边节点,则先找出右边最小的值,作为根节点,然后将删除最小值过后的右边的节点,作为根节点的右节点

看下代码的实现:

 // 删除新节点,从根节点开始删除
void delete(int data)
{
root = delete(root, data);
} //递归删除节点
Node delete(Node node, int data)
{
//如果节点为空,直接返回
if (node == null) return node; //遍历左右两边的节点
if (data < node.data)
node.left = delete(node.left, data);
else if (data > root.data)
node.right = delete(node.right, data); //如果节点匹配
else
{
//如果是单边节点,直接返回其下面的节点
if (node.left == null)
return node.right;
else if (node.right == null)
return node.left; //如果是双边节点,则先找出右边最小的值,作为根节点,然后将删除最小值过后的右边的节点,作为根节点的右节点
node.data = minValue(node.right); // 从右边删除最小的节点
node.right = delete(node.right, node.data);
}
return node;
}

这里我们使用递归来实现的删除双边节点,大家可以考虑一下有没有其他的方式来删除呢?

本文的代码地址:

learn-algorithm

本文收录于 www.flydean.com

最通俗的解读,最深刻的干货,最简洁的教程,众多你不知道的小技巧等你来发现!

欢迎关注我的公众号:「程序那些事」,懂技术,更懂你!

看动画学算法之:二叉搜索树BST的更多相关文章

  1. 70 数组的Kmin算法和二叉搜索树的Kmin算法对比

    [本文链接] http://www.cnblogs.com/hellogiser/p/kmin-of-array-vs-kmin-of-bst.html [分析] 数组的Kmin算法和二叉搜索树的Km ...

  2. C++版 - 剑指offer 面试题24:二叉搜索树BST的后序遍历序列(的判断) 题解

    剑指offer 面试题24:二叉搜索树的后序遍历序列(的判断) 题目:输入一个整数数组,判断该数组是不是某二叉搜索树的后序遍历的结果.如果是则返回true.否则返回false.假设输入的数组的任意两个 ...

  3. 萌新笔记之二叉搜索树(BST)

    前言,以前搞过线段树,二叉树觉得也就那样= =.然后数据结构的课也没怎么听过,然后下周期中考... 本来以为今天英语考完可以好好搞ACM了,然后这个数据结构期中考感觉会丢人,还是好好学习一波. 二叉搜 ...

  4. 给定一个二叉搜索树(BST),找到树中第 K 小的节点

    问题:给定一个二叉搜索树(BST),找到树中第 K 小的节点. 出题人:阿里巴巴出题专家:文景/阿里云 CDN 资深技术专家. 考察点: 1. 基础数据结构的理解和编码能力 2.  递归使用 参考答案 ...

  5. 看动画学算法之:平衡二叉搜索树AVL Tree

    目录 简介 AVL的特性 AVL的构建 AVL的搜索 AVL的插入 AVL的删除 简介 平衡二叉搜索树是一种特殊的二叉搜索树.为什么会有平衡二叉搜索树呢? 考虑一下二叉搜索树的特殊情况,如果一个二叉搜 ...

  6. 二叉搜索树(BST)学习笔记

    BST调了一天,最后遍历参数错了,没药救了-- 本文所有代码均使用数组+结构体,不使用指针! 前言--BFS是啥 BST 二叉搜索树是基于二叉树的一种树,一种特殊的二叉树. 二叉搜索树要么是一颗空树, ...

  7. 二叉搜索树(BST)

    (第一段日常扯蛋,大家不要看)这几天就要回家了,osgearth暂时也不想弄了,毕竟不是几天就能弄出来的,所以打算过完年回来再弄.这几天闲着也是闲着,就掏出了之前买的算法导论看了看,把二叉搜索树实现了 ...

  8. 数据结构-二叉搜索树(BST binary search tree)

    本文由@呆代待殆原创,转载请注明出处:http://www.cnblogs.com/coffeeSS/ 二叉搜索树简介 顾名思义,二叉搜索树是以一棵二叉树来组织的,这样的一棵树可以用一个链表数据结构来 ...

  9. [LeetCode] Convert BST to Greater Tree 将二叉搜索树BST转为较大树

    Given a Binary Search Tree (BST), convert it to a Greater Tree such that every key of the original B ...

随机推荐

  1. EasyX安装教程

    Easyx是什么 就是一款可以在Windows里让你的C++程序里显示图片等的工具. 注意:EasyX不支持Linux.MacOS.不过还有Qt等可以选择. 安装VC/VS Easyx只支持Visua ...

  2. 精准测试系列分享之一:JaCoCo 企业级应用的优缺点分析

    一.JaCoCo简介 JaCoCo是Eclipse平台下的开源产品,以小型,轻量化著称,常见集成在Eclipse Workbench中,除此之外的启动方式包括对接Ant和Maven,或是命令行的方式进 ...

  3. python numpy版本报错: File "*\numpy\__init__.py", line 305, in <module> _win_os_check()

    具体代码如下所示: from numpy import * import operator a = random.rand(4, 4) print(a) 具体报错内容如下所示: Traceback ( ...

  4. 『动善时』JMeter基础 — 57、Linux系统中运行JMeter脚本

    目录 1.Linux系统中安装Java环境 (1)解压Java安装包 (2)配置Java环境变量 (3)验证Java环境是否配置成功 2.Linux系统中安装JMeter (1)下载JMeter (2 ...

  5. C++ 函数模板实现原理剖析

    C++ 函数模板实现机制原理剖析 重点 编译器并不是把函数模板处理成能够处理任意类的函数 编译器从函数模板通过具体类型来产生不同的函数 编译器会对函数模板进行两次编译 (1)在声明的位置对模板代码进行 ...

  6. JDK 工具 HSDB 查看动态生成类

    前置工作 1. 复制 JDK 安装目录\jre\bin\sawindbg.dll 到 JDK 安装目录同级的 jre\bin 目录下,否则会报错找不到 sawindbg.dll 文件. 比如我的 sa ...

  7. QT6 源码杂记

    菜鸡一个,随便写写,勿喷.好记性不如烂笔头. 了解qt,第一个绕不过的坎便是qt的元对象系统 QMetaObject. 1 class Object : public QObject 2 { 3 Q_ ...

  8. 树莓派4b安装Ubuntu20.04

    树莓派4b安装Ubuntu20.04 下载Ubuntu20.04镜像 下载地址 安装Raspberry Pi Imager 下载地址 烧录系统 打开Raspberry Pi Imager,选择自己刚刚 ...

  9. 天冷了,任务栏养只猫吧「GitHub 热点速览 v.21.46」

    作者:HelloGitHub-小鱼干 运动能带来热量,盘猫也是,RunCat_for_windows 是一只奔跑在任务栏的猫,一定能给你的电脑带来一丝冬日的温暖.当然送温暖的除了任务栏小猫咪之外,还有 ...

  10. java自定义序列化

    自定义序列化 1.问题引出 在某些情况下,我们可能不想对于一个对象的所有field进行序列化,例如我们银行信息中的设计账户信息的field,我们不需要进行序列化,或者有些field本省就没有实现Ser ...