9 B树/B+树
在计算机科学中,B树(B-tree)是一种树状数据结构,它能够存储数据、对其进行排序并允许以O(log n)的时间复杂度运行进行查找、顺序读取、插入和删除的数据结构。B树,概括来说是一个节点可以拥有多于2个子节点的二叉查找树。与自平衡二叉查找树不同,B-树为系统最优化大块数据的读和写操作。B-tree算法减少定位记录时所经历的中间过程,从而加快存取速度。普遍运用在数据库和文件系统。
——维基百科
B 树可以看作是对2-3查找树的一种扩展,即他允许每个节点有M-1个子节点。
定义任意非叶子结点最多只有M个儿子;且M>2;
根结点的儿子数为[2, M];
除根结点以外的非叶子结点的儿子数为[M/2, M];
每个结点存放至少M/2-1(取上整)和至多M-1个关键字;(至少2个关键字)
非叶子结点的关键字:K[1], K[2], …, K[M-1];且K[i] < K[i+1];
非叶子结点的指针:P[1], P[2], …, P[M];其中P[1]指向关键字小于K[1]的 子树,P[M]指向关键字大于K[M-1]的子树,其它P[i]指向关键字属于(K[i-1], K[i])的子树;
所有叶子结点位于同一层;
如:(M=3)
算法思路:
从根结点开始,对结点内的关键字(有序)序列进行二分查找,如果命中则结束,否则进入查询关键字所属范围的儿子结点;重复,直到所对应的儿子指针为空,或已经是叶子结点;
关键字集合分布在整颗树中;
任何一个关键字出现且只出现在一个结点中;
搜索有可能在非叶子结点结束;
其搜索性能等价于在关键字全集内做一次二分查找;
自动层次控制;
代码:
BTNode* BTree_recursive_search(const BTree tree, KeyType key, int* pos) { int i = 0; while (i < tree->keynum && key > tree->key[i]) { ++i; } // 查找关键字 if (i < tree->keynum && tree->key[i] == key) { *pos = i; return tree; } // tree 为叶子节点,找不到 key,查找失败返回 if (tree->isLeaf) { return NULL; } // 节点内查找失败,但 tree->key[i - 1]< key < tree->key[i], // 下一个查找的结点应为 child[i] // 从磁盘读取第 i 个孩子的数据 disk_read(&tree->child[i]); // 递归地继续查找于树 tree->child[i] return BTree_recursive_search(tree->child[i], key, pos); }
B+树:
B+树是B树的变体,也是一种多路搜索树:
其定义基本与B-树同,除了:
非叶子结点的子树指针与关键字个数相同;
非叶子结点的子树指针P[i],指向关键字值属于[K[i], K[i+1])的子树, B树是开区间
为所有叶子结点增加一个链指针;
所有关键字都在叶子结点出现;
如:(M=3)
算法思路:
B+的搜索与B树也基本相同,区别是B+树只有达到叶子结点才命中(B树可以在 非叶子结点命中),其性能也等价于在关键字全集做一次二分查找;https://blog.csdn.net/u013171283/article/details/82951039
所有关键字都出现在叶子结点的链表中(稠密索引),且链表中的关键字恰好是有序的;
不可能在非叶子结点命中;
非叶子结点相当于是叶子结点的索引(稀疏索引),叶子结点相当于是存储(关键字)数据的数据层;
更适合文件索引系统;
LeetCode101题解
参考资料
https://www.sohu.com/a/296278527_478315
https://www.cnblogs.com/exzlc/p/12203744.html
部分配图来源于网络