高级数据结构与算法 | B树、B+树、B*树


搜索结构

如果我们有大量的数据需要永久存储,就需要存储到硬盘之中,但是硬盘的访问速度远远小于内存,并且由于数据量过大,无法一次性加载到内存中。此时,就可以考虑将数据存储在硬盘中,而数据的地址则加载到内存中,通过某种搜索结构进行存储,使用时只需要通过该结构查找到地址,在通过地址去找到对应的数据即可。

之前我博客中介绍了几种搜索结构:二叉搜索树、AVL树、红黑树、哈希、位图、布隆过滤器。
考虑到查找性能以及内存消耗,其中适合这种场景的只有平衡二叉搜索树(AVL、红黑树)
在这里插入图片描述

但即使平衡二叉搜索树的搜索性能能达到logN,由于数据量过于庞大,例如存储了10亿个数,则可能最多需要查找30次。这个数字看起来不是很多,因为之前我们比较的是内存的速度,即使是10亿个数也能一瞬间查找完。但是对于硬盘来说,由于硬盘的速率低,每一次IO都意味这大量的损耗,所以这种方法也不太合适。

如果想要提高查找的效率,那么唯一的方法就是压缩树的高度,而压缩的方法,就是将二叉树变为M叉树,也就是使用到M路平衡搜索树,B树。


B树

B树即一棵平衡的M路平衡搜索树(M > 2),可以是空树或者满足以下性质

  • 根节点至少有两个孩子
  • 每个非根节点至少有M/2(上取整)个孩子,至多有M个孩子
  • 每个非根节点至少有M/2-1(上取整)个关键字,至多有M-1个关键字,并且以升序排列
  • key[i]和key[i+1]之间的孩子节点的值介于key[i]、key[i+1]之间
  • 所有的叶子节点都在同一层

节点设计

template<class K, int M = 3>
struct BTreeNode
{
	K _keys[M]; // 存放元素
	BTreeNode<K, M>* _pSub[M+1]; // 存放孩子节点,注意:孩子比数据多一个
	BTreeNode<K, M>* _pParent; // 在分裂节点后可能需要继续向上插入,为实现简单增加parent域
	size_t _size; // 节点中有效元素的个数
	
	BTreeNode()
		: _pParent(NULL)
		, _size(0)
	{
		for(size_t i = 0; i <= M; ++i)
		_pSub[i] = NULL;
	}
};

B树的插入

下面拿一个M=3的三叉B树来举例子。(ps:三叉树即每个节点至多3个孩子,2个key,key的数量永远比孩子少一个)

假设使用以下数据构建B树{63, 131, 85, 39, 148, 31, 111}(B树从叶子节点的位置进行插入
在这里插入图片描述
首先依次插入前三个节点,当插入到第三个时,由于三叉树的key只能有2个,所以此时会采取分裂的方法来维持树的平衡

B树分裂的规则是:创建一个兄弟节点,拷贝右半区间的数据到兄弟节点,左半区间保留,中位数放到父亲节点(如果没有则创建新的根节点)。
B树与AVL的旋转,红黑树的旋转+变色不一样,它使用了分裂的方法来维持树的平衡这样的好处是既能做到平衡,也保证了非根节点至少有一半的空间利用率

所以此时按照上面的规则进行分裂
在这里插入图片描述
接着插入39, 148。
在这里插入图片描述
此时插入31,开始分裂
在这里插入图片描述
接着插入111,此时再次发生分裂
在这里插入图片描述
此时可以看到,叶子节点已经分裂成了四个,并且根节点的key也达到了三个,所以此时规则不成立,按照分裂的规则继续分裂
在这里插入图片描述
此时,树重新平衡。所以从上面可以看出来,本质上B树的设计还是参考了二叉搜索树。


B树的遍历

B树的有序遍历还是通过中序遍历来完成,不过需要通过队列或者递归遍历完这个节点的所有的key

void _InOrder(PNode pRoot)
{
	if(NULL == pRoot)
		return;
		
	for(size_t i = 0; i < pRoot->_size; ++i)
	{
		_InOrder(pRoot->_pSub[i]);
		cout<<pRoot->_keys[i]<<" ";
	}
	_InOrder(pRoot->_pSub[pRoot->_size]);
}

B树的性能

作为一个M路平衡搜索树,B树的搜索性能达到了 l o g M + 1 N log_{M+1}{N} logM+1N~ l o g M / 2 N log_{M/2}{N} logM/2N之间,查找到对应的节点后,通过节点存储的地址来进行二分查找,就可以确定数据的位置。比起二叉平衡搜索树,速度快了一大截,并且大大的减少了硬盘IO的次数,所以在文件系统以及数据库索引等方面使用的都是这种数据结构。


B+树

B+树是B树的变形,主要性质如下

  • 其定义基本与B树相同
  • 非叶子节点的孩子与key个数相同(简化规则
  • 非叶子节点由叶子节点的最小值构成(充当索引,所以不可能在非叶子节点命中
  • 所有数据都出现在叶子节点,并且所有叶子节点都链接起来,同时是有序的。(方便遍历

如下图
在这里插入图片描述


B+树的插入

这里为了方便,使用三阶B+树举例子,这里还是使用同样的数据。{63, 131, 85, 39, 148, 31, 111}
首先插入63,并把63作为父节点的索引
在这里插入图片描述
接着插入131, 85在这里插入图片描述
当插入39时,发生分裂,分裂规则与之前略有区别。

B+树的分裂规则发生了变化,因为此时父节点存储的是索引,所以此时只会将左半部分数据保留,右半部分数据放入新建的兄弟节点,并且会向上更新父节点的索引。
在这里插入图片描述
接着插入148, 31
在这里插入图片描述
当插入111时,发生分裂
在这里插入图片描述


B+树的遍历

从上面可以看出来,B+树的主要特点其实就是更方便进行遍历,因为其将所有数据存储在叶子节点,并且将所有叶子节点连接起来,就可以像遍历链表一样遍历B+树。而所有非叶子节点就相当于一个索引,这样的结构使得B+树的查找相当于对关键字全集做一次二分查找。

所以通常文件的索引系统都会采用B+树的结构。


B*树

B*树则又是对B+树的变形,其性质如下

  • 其定义基本与B+树相同
  • 将非叶子节点也连接起来
  • 分裂方式再次修改,保证每个节点中key的数量[2/3 * M, M](提高空间利用率,从1/2提升到了2/3
    在这里插入图片描述

B*树的插入

B*树再次修改了插入规则,规则修改为如果当前节点数据已满而兄弟节点未满,则将数据放入兄弟节点,而当两个节点都满了之后再进行分裂,在原节点与兄弟节点之间创建新节点,从两个节点分别取出1/3的数据放入新创建的结点。

还是原来那些数据{63, 131, 85, 39, 148, 31, 111}
![在这里插入图片描述](https://img-blog.csdnimg.cn/20200821001622256.png#pic_center)此时插入111,发生分裂

此时插入111,发生分裂,从两边各取走1/3的数据
在这里插入图片描述

从上面可以看出,B*树的最大改进就是将B+树的空间利用率从1/2提升到了2/3,并且对非叶子节点也进行了连接,查找更加便利。


总结

在这里插入图片描述
在这里插入图片描述

  • 3
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
CSDN四川大学数据结构与算法考点汇总主要内容包括以下几个方面。 首先是数据结构的基本知识点。包括线性表、栈、队列、串、组、链表、和图等常用数据结构的定义、性质以及相关操作。例如,线性表的顺序表示与链式表示、的遍历算法(前序、序、后序)、图的遍历算法(深度优先搜索和广度优先搜索)等。 其次是常见的排序和查找算法。主要包括冒泡排序、选择排序、插入排序、快速排序、归并排序、堆排序等各种排序算法的原理、时间复杂度和空间复杂度。还有二分查找和哈希查找等常见查找算法。 接着是常用的高级数据结构与算法。主要包括二叉、红黑B树、哈希表、图的最短路径算法(Dijkstra算法和Floyd算法)、最小生成(Prim算法和Kruskal算法)等。 最后是一些经典算法问题的解决方法。例如,递归和回溯算法、动态规划算法、贪心算法等。同时还涉及一些常见的算法问题,如字符串匹配问题(KMP算法、Boyer-Moore算法)、最长公共子序列问题、最大子组和问题等。 以上就是CSDN四川大学数据结构与算法考点汇总的简要介绍。这些考点内容涵盖了数据结构与算法的基础知识、常见排序和查找算法高级数据结构与算法以及一些经典算法问题的解决方法。熟练掌握这些知识,对于提高编程能力和解决实际问题都具有重要意义。

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

凌桓丶

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

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

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

打赏作者

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

抵扣说明:

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

余额充值