多路查找树

多路查找树

将讲多路查找树之前先讲一下二叉树和B树的关系。

二叉树的操作效率较高,但也存在问题。

加入二叉树的节点数量很多的时候会存在以下问题:

  1. 构建二叉树时需要多次进行I/O操作。
  2. 查找时效率降低

解决方法 : 多叉树

在二叉树中,每个节点有数据项和最多两个子节点,如果允许每个节点有更多的数据项和子节点,就是多叉树。

后面讲解的2-3树,2-3-4树就是多叉树,多叉树通过重新组织节点,减少树的高度,能对二叉树进行优化。
在这里插入图片描述

例如上面就是一棵2-3树,有三个子节点的就是3节点,两个子节点的就是2节点

所以上面的树叫2-3树, 2-3-4树自然也很好理解。

B树的基本介绍

B树(B-树)是一种平衡的多路查找树。2-3树和2-3-4树都是B树的特例。节点最大的孩子数组称为B树的阶(order),因此,2-3树是3阶B树,2-3-4树是4阶B树。

B树通过重新组织节点降低树的高度(即一个节点存储多个数据)

文件系统及数据库系统的设计者利用了磁盘预读原理,将一个节点的大小设计为一个页(页大小通常为4K),这样一次I/O只需要一次只需要载入一个节点就行。

如果将树的度M设置为1024(一棵树的度是所有节点的度中的最大值,例如二叉树的度为2, 2-3树的度为3,2-3-4树的度为4),在600亿个元素中最多只需要4次I/O操作就可以读取到想要的元素,B树(B+树)广泛应用于文件存储系统以及数据库系统中。

2-3树

2-3树是最简单的B树,具有以下特点:

  1. 2-3树的所有叶子节点都在同一层(所有B树都满足这个条件)
  2. 有两个子节点的节点叫做二节点,二节点要么没有子节点,要么有两个子节点。
  3. 有三个子节点的节点叫做三节点,三节点要么没有子节点,要么有三个子节点。
  4. 2-3树是由二节点和三节点构成的树。
构建2-3树

构建一棵排序树其实就是从一棵空树开始不断的往里面添加元素,且每次添加的元素必定为叶子节点。

2-3树具有所有叶子节点都在同一层的特点,所以不可能每次插入的元素都作为一个二节点放入新的一行,而是要和其他元素合并(添加第一个元素时除外)。

  1. 对于空树,插入一个2节点即可。

  2. 插入节点到一个二节点的叶子上,只需将其升级为三节点即可

  3. 插入节点到一个三节点的叶子上,因为三节点本身容量最大,因此需要拆分。在节点中两元素或新加的元素中选择一个向上移动一层(由于所有叶子节点都必须在同一层,所以不可能选择一个元素移动到下一层,这样就不符合所有叶子节点都在同一层的限制了)。

    向上移动又可以分为多种情况:

    1. 如果该三节点的父节点为二节点,则将父节点变为三节点即可
      在这里插入图片描述

    2. 如果父节点为三节点,则观察父节点的父节点……以此类推,如果存在某个节点为二节点,则将该二节点变为三节点。。
      在这里插入图片描述

    3. 如果在第二种情况下所有的父节点,父节点的父节点……都为三节点,则只能够增加树的高度
      在这里插入图片描述

对于上面构建2-3树的情况可能看懂了 ,但是具体的代码怎么实现呢?特别是什么由二节点点变为三节点,听起来很简单,但是到底怎么变啊,它下面的子树那么处理? 拿上面第一种小情况来说。

5 要插入到 有6 和7 两个元素的三节点中,显然不行,又因为父节点为二节点,所以在这三个元素中选择一个和父节点合并。选择哪一个呢?三个元素中第二大的那个。为什么?因为只有这样才能符合排序树的标准,5 大于 4 小于 6 ,7 大于 6。和父节点合并后谁在前谁在后呢?这很简单,符合排序树标准,小的在前面,大的在后面。然后将剩下的两个元素分为两个叶子节点。
在这里插入图片描述

第二种情况,如果父节点为三节点,则看父节点的父节点。如果父节点的父节点为二节点,则将父节点的父节点变为三节点,具体过程如下:将 11 添加到 有9,10 的三节点中,只能向上合并,选中第二大的10元素进入上一层,剩下的两个元素拆分为二节点,发现父节点也是三节点,所以只能选中10,12,14 中的第二大的元素继续向上进行合并,也就是 12 进入上层进行合并,发现上层为二节点,可以合并,于是合并。但是我们观察到不仅是二节点变成了三节点,其他很多节点也发生了变化,那么是如何变化的呢。首先,由于我们是一层层向上推进的,所以既然能递进到 8 这一层,则说明下层的某个节点一定已经满员了,也就是存在某个节点为三节点。我们需要将该三节点拆分为两个二节点。这时候又分两种情况:1. 我们要拆分的三节点已经是叶子节点了,直接拆分就行了 。 2. 我们要拆分的三节点不是叶子节点,也就是下面还有三个子节点,同理,这三个子节点中必定存在一个为三节点,我们只需要将该三节点拆分为两个二节点作为父节点对应元素的左右节点即可。

我们可以发现构建树的过程中其实就俩步操作 , 将二节点合并为三节点 和 将三节点拆分为二节点。

当需要添加一个元素时,根据排序树的规则找到该元素应该存在的位置,该位置必定在某个已经存在的节点中(空树除外),如果该节点没满,就将二节点合并为三节点,否则,从三个元素中选择第二大的元素添加到该节点的父节点中(这里其实是一个循环),如果找到了某个父节点符合要求,则合并,如果最终找到根节点都不符合要求,则拆分根节点。

合并:将两节点合并为三节点
  1. 如果合并的节点为叶子节点,直接合并
  2. 如果合并的节点不为叶子节点,说明子节点中存在至少一个三节点,将该三节点拆分成两个
拆分:将三节点拆分为两个两节点
  1. 如果拆分的节点为叶子节点,直接拆分
  2. 如果拆分的节点不为叶子节点,说明子节点中存在至少一个三节点,将该三节点拆分成两个二节点

拆分:将三节点拆分为两个两节点

  1. 如果拆分的节点为叶子节点,直接拆分
  2. 如果拆分的节点不为叶子节点,说明子节点中存在至少一个三节点,将该三节点拆分成两个二节点
  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Little BigUs

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值