为了账号安全,请及时绑定邮箱和手机立即绑定

【九月打卡】第18天 二分搜索树

课程名称:算法与数据结构
课程章节:二分搜索树
课程讲师: Liuyubobobo

课程内容

二叉树 Binary Tree

为什么要有树结构

  • 对于大量的输入数据,链表的线性访问时间 太慢,不宜使用
  • 树结构本身是一种天然的组织结构
  • 将数据使用树结构存储后,出奇的高效

二叉树的定义

二叉树

  • 和链表一样,动态数据结构
  • 二叉树具有唯一根节点
  • 二叉树每个节点最多有两个孩子,一个孩子都没有的节点通常称为叶子节点
  • 二叉树每个节点最多只有一个父亲节点,整个二叉树中只有一个节点是没有父亲节点的,就是根节点

class Node {
E e;
Node left;//左孩子
Node right;//右孩子
}

二叉树具有天然递归结构

链表也具有天然的递归结构,但由于链表是线性的,所以对于链表相关的操作,使用循环的方式完全可以处理;但对于树来说,使用递归的写法要比非递归的写法要简单很多的

二叉树具有天然的递归结构

  • 每个节点的左子树也是二叉树
  • 每个节点的右子树也是二叉树

每一棵二叉树它的左侧和右侧又分别连接了两颗二叉树,这两颗二叉树都是节点个数更小的两颗二叉树。

二叉树不一定是满二叉树

  • 二叉树不一定是满二叉树,满二叉树是指除了叶子节点之外,都有两个孩子
  • 一个节点也可以二叉树,只有一个节点也可以是链表
  • null 空也可以是二叉树,空节点也可以是链表

二分搜索树 Binary Search Tree

二分搜索树的定义

  • 二分搜索树是二叉树 二分搜索树
  • 二分搜索树每个节点的值:
    • 大于其左子树的所有节点的值
    • 小于其右子树所有节点的值
  • 存储的元素必须具有可比较性 (如果要加快搜索的话,就必须对数据有一定的要求)

二分搜索树添加新元素

本二分搜索树不包含重复元素,如果想包含重复元素的话,有两种实现方式

  1. 定义左子树小于等于节点;或者右子树大于等于节点
  2. 定义节点的count > 注意:数组和链表,可以有重复元素

二分搜索树查询元素

二分搜索树的遍历

  • 遍历操作就是把所有的节点都访问一遍
  • 访问的原因和业务相关
  • 在线性结构性下,遍历是极其容易的

二叉树的遍历操作

  • 从根节点开始看,是不是查找的元素。如果小于根节点就在左子树中继续进行这个操作,如果大于根节点,就在右子树中继续进行操作
  • 对于遍历操作,两棵子树都要顾及

前序遍历

  • 访问节点的时机放在了访问左子树和右子树的前面

中序遍历

  • 访问节点的时机放在了访问左子树和右子树的中间

中序遍历

  • 二分搜索树的中序遍历结果是顺序的,正因为这种性质,二分搜索树也称为排序树

后序遍历

  • 访问节点的时机放在了访问左子树和右子树的后面
  • 应用场景:必须处理完节点的孩子节点之后再来处理这个节点,比如 为二分搜索树释放内存(Java语言有GC,所以用不到)

如何快速写出树结构中前中后序的遍历结果

二分搜索树的递归结构

  • 对于每一个节点都连接着左子树和右子树,在具体遍历的时候,每一个节点都有三次的访问机会,遍历完左子树之后会回到该节点;然后继续去遍历右子树,遍历完右子树后会继续回到该节点。

二分搜索树的访问机会

  • 二分搜索树的前中后遍历其实就对应着每个节点的三个紫色的点,在哪里进行真正的访问操作

遍历示例

  • 前序遍历就是在第一次访问节点的时候访问节点值
  • 中序遍历就是在第二次访问节点的时候访问节点值
  • 中序遍历就是在第三次访问节点的时候访问节点值

二分搜索树的层序遍历

广度优先遍历

  • 二分搜索树的前序、中序、后序遍历其实上都是深度优先的遍历。
  • 根节点为深度为0的节点,一层一层的进行遍历
  • 需要借助队列这种数据结构,从根节点开始,排队进入队列,队列中存储的就是待遍历的元素;每次遍历一个元素之后,将它的左右孩子也进行入队操作
  • 广度优先遍历的意义:主要用于搜索策略上,而不是用于遍历操作上(对于遍历来说,深度优先遍历和广度优先遍历是没有区别的),常用于算法设计中-最短路径

删除二分搜索树中的最大值和最小值

  1. 找到二分搜索树中的最大值和最小值

删除任意元素

1962年,Hibbard提出-Hibbard Deletion

  • 删除左右都有孩子的节点,取比要删除节点要大的最小元素节点代替被删除节点,即找要删除元素的后继

  • 需要找到对于要删除元素d的右子树来说相应的最小值的点,我们称这个点为s,s是d的后继

  • s->right=delMin(d->right);

  • s->left=d->left

  • 删除d,s是新的子树的根节点

  • 也可以通过找d的前去p来取代d,无论是使用前驱还是后继,都能继续保持二分搜索树的性质

删除左右都有孩子的节点

更多二分搜索树相关的问题

  • 二分搜索树具有顺序性,放在二分搜索树中的所有元素都是有序的(中序遍历得到的结果就是有序的),可以非常轻易地得到最大值 minimum 和最小值 maximum,包括给定一个值拿到它的前驱 successor 和后继 predecessor,
  • floor,ceil ,比如寻找45的floor和ceil,floor是比45小的最大的元素,ceil是比45大的最小的元素
  • rank,select,rank是查看元素排名第几 rank 58 求58是排名第几的元素;select是一个反向的操作,排名是第10名的元素是谁;实现rank和select最好的方式是每一个节点同时维护一个size,size表示以这个节点为根的二分搜索树有多少个元素,有了这个size之后就可以移除整体size 了
  • 维护depth的二分搜索树 维护depth的二分搜索树
  • 支持重复元素的二分搜索树;1. 定义左子树或右子树等于父节点即可;2.在Node作用域中定义count,记录重复元素,–后等于0,才彻底删除元素

学习收获

今天学习了经典树结构中的二叉树和二分搜索树。收获巨大。
图片描述

点击查看更多内容
TA 点赞

若觉得本文不错,就分享一下吧!

评论

作者其他优质文章

正在加载中
JAVA开发工程师
手记
粉丝
6
获赞与收藏
11

关注作者,订阅最新文章

阅读免费教程

  • 推荐
  • 评论
  • 收藏
  • 共同学习,写下你的评论
感谢您的支持,我会继续努力的~
扫码打赏,你说多少就多少
赞赏金额会直接到老师账户
支付方式
打开微信扫一扫,即可进行扫码打赏哦
今天注册有机会得

100积分直接送

付费专栏免费学

大额优惠券免费领

立即参与 放弃机会
意见反馈 帮助中心 APP下载
官方微信

举报

0/150
提交
取消