树、二叉树、二叉搜索树

1.写在前面

前面的博客,我简单的介绍的一维的结构,数组、链表、跳表,主要是一些一维的数据结构,今天我们来介绍一下,二维结构的数据,我们就先来简单的介绍下树的类型。

2.树、二叉树、二叉搜索树

由于链表的查找速度比较慢,所以我们想出了跳表的结构,同样的是一维的结构,但是我们可以通过升维的思想,来提高的链表的访问的速度。一般的链表的如下所示:

在这里插入图片描述

查找的速度慢,是因为我们每一次只能一个节点一个节点往下的访问,我们是不是可以通过增加next的个数来达到加速访问的节点的效果,于是就有了树,于是有了如下的结构:

在这里插入图片描述

如上图,树有个根节点A,然后B相对A就是儿子节点,然后BC就是兄弟节点,然后H、I、E、F、G就是这颗树的叶子节点。这就是一个简单的树的结构。那么什么是二叉树呢?就是在树的基础上规定了树只能有两个儿子节点,于是二叉树的结构就如下图所示:

在这里插入图片描述

那么讲到的升维,我们这儿必须要提及一下我们的图了,图和树的区别就是,图能形成一个闭环。所以这儿有一个很重要的话就是:链表是特殊的化的树,树是特殊化图。

那么什么是二叉搜索树呢?具体的看下图:

在这里插入图片描述

二叉搜索树,也称为二叉搜索树、有序二叉树、排序二叉树,是指一颗空树或者具有下列性质的二叉树:

  • 左子树上所有节点的值均小于它的根节点的值;
  • 右子树上所有节点的值均大于它的根节点的值;
  • 依次类推:左、右子树也分别为二叉查找树。
  • 中序遍历:升序排列

3.二叉树的例子

例如我们求解斐波那契数列的数列的时候,我们利用递归解决问题的时候,就是一个递归树,具体的如下:

在这里插入图片描述

还有一些围棋的程序,例如阿尔法狗,还有我们的人生也是一颗树,选择不同,人生的岔路口也是不一样的。

4.二叉树的定义的结构

那么二叉树的定义的结构如何呢?由于我是java的开发的程序员,所以这儿只展示java的数据格式定义,具体的如下:

private class TreeNode{
  private int value;
  private TreeNode left, right;
  public TreeNode(int value){
    this.value = value;
    this.left = null;
    this.right = null;
  }
}

5.二叉树的遍历

  • 前序(pre-order) 根-左-右
  • 中序(in-order) 左-根-右
  • 后序(post-order) 左-右-根

对应的实例代码如下:

def preorder(self, root):
  if root:
    self.traverse_path.append(root.val)
    self.preorder(root.left)
    self.preorder(root.right)

def inorder(self, root):
  if root:
    self.inorder(root.left)
    self.traverse_path.append(root.val)
    self.inorder(root.right)
    
def postorder(self, root):
  if root:
    self.postorder(root.left)
    self.inorder(root.right)
    self.traverse_path.append(root.val)

6.二叉搜索树的常见的操作

现在假设生成的二叉搜索树如下:

在这里插入图片描述

  1. 搜索的操作

    比如我现在要查找’5’的值,这个时候第一步和根节点比较,发现5比15小,这个时候就会进入左边,然后和6比较,发现还是比6小,这个时候去左边,这个时候会和4比较,发现5比4大,这个时候就去4的右边找,这个时候发现5真好等于我们要查找的节点,于是就直接返回。具体的路径如下:

    在这里插入图片描述

    但是我们如果查找的值,不存在这个树中呢?比如我们要查找24,于是走来先和15比较,发现比15大,于是去右边去找,这个时候找到是23,然后发现24比23大,于是又去右边去找,这个时候找到的是71,发现24比71小,于是去左边找,这个时候是50,发现24比50小,这个时候去左边找,发现没有了,于是就是返回没有找到,具体的路径如下:

    在这里插入图片描述

  2. 插入的操作

    其实插入的操作和搜索的操作差不多,就是找到对应的位置,然后进行插入,我们还是选择上面生成的二叉搜索树,具体的如下:

    在这里插入图片描述

    假设我们现在插入一个3进去,走来3比15小,然后去左边,发现3比6小,于是又是左边,这个时候发现3还是4小,于是又是去左边,然后发现4的左边没有东西,于是就将3插入到这个位置,具体的路径如下:

    在这里插入图片描述

  3. 删除的操作

    删除的操作,可能会破坏二叉搜索树的结构,这个时候,我们就需要维护二叉搜索树的结构了,具体的树的结构,还是和原来的一样的具体的如下:

    在这里插入图片描述

    这个时候比如说,我们要删除5这个节点,这个时候我们还是和之前的查找的操作一样,先查找到5这个节点,然后删除,因为5是叶子节点,所以不需要变换树的结构,具体的如下:

    在这里插入图片描述

    如果我们删除的是6的节点,会发生什么情况呢?很显然有两种的方式,一种就是找到第一个比6大的节点作为这个根节点,另外一种就是找到第一个比6小的节点作为这个根节点。这儿我们采取的是第一种的方式,这儿删除6后,第一个比6大的节点就是7,于是7变成根节点,于是最终的树变成如下:

    在这里插入图片描述

7.二叉搜索树的时间复杂度

搜索、插入、删除的时间的复杂度都是O(log(n)),但是也有一些比较特殊的情况,就是二叉搜索树退还成了链表的接口,具体的如下:

在这里插入图片描述

这样他的时间复杂度就和链表的是一样的了。

8.写在最后

这篇博客主要讲了一下树、二叉树、二叉搜索树的一些简单的概念,后面我会继续讲HashMap的1.8的源码。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值