天天看点

九大查找算法,值得收藏(四)

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

部分配图来源于网络