查找(四)-------基于B树的查找和所谓的B树

时间:2021-05-13 15:15:35

关于B树,不想写太多了,因为花在基于树的查找上的时间已经特么有点多了,就简单写写算了,如果以后有需要,或者有时间,可以再深入写写

首先说一下,为什么要有B树,以及B树是什么,很多数据结构和算法的书上来就上B树的定义,然后讲基于B树的几个操作,什么插入啊,建立啊,分裂啊,最后写个查找算法了事

我想,请问一下,编书的人这样搞是什么意思,这样还不如直接画算法的示意图,接下来是源码就够了,这样学下来,各种查找,搜索算法之间都是孤立开来的,无法领会到他们为什么这样做,他们是怎样想出来的,算了,不扯了,心里烦编书的人

为什么会有B树呢?我们还是先回到二叉排序树和平衡二叉排序树上,有了他们,我们才能理解为什么会有B树

在平衡二叉排序树里,算法的时间复杂度为O(log2(n)),明显,这里的算法时间复杂度是取决于树的深度的,想一想,一个节点只能存储有限的数据,一个结点最多只能有两颗子树,这样一来,数据一多,树的深度就很大,因此,算法的时间复杂度很容易就变得很大,这种问题有什么解决办法呢?肯定是减少树的深度啊!,怎么减少树的深度呢?可以多增加几个子树啊!子树之间也是有序的,这样一来,树的深度不久降下来了吗,这样的话,这种多子树的平衡术的时间复杂度就为logm(n),其中的m为子树的个数,m越大,算法时间复杂度就很小了!

按照这样的思路,我们新提出来一种树,那就是B树了,B树通常被描述为m阶B树,m阶B树的定义如下:

1.每个结点最多只能有m颗子树()

2.根节点至少有2颗子树(根节点子树数目>=2&&<=m)

3.除了根节点之外的非叶结点至少有|_m/2_|颗子树(>=|_m/2_|&&<=m)

4.所有的叶子结点都在同一层()

好了,有了以上的定义,下面可以给出B树的数据结构了

#include<iostream>
#define M 100
typedef char KeyType;
//m阶B树表示:这个树每个节点最多能有m颗子树,根节点最少有2颗子树,非根的非叶子结点最少有ceil(m/2)颗子树
typedef struct _B_Node
{
struct _B_Node* childTree[M+1];//M+1个子树
int keyNum;//关键字个数,keyNum+1为子树个数
struct _B_Node* parent;
KeyType key[M+1];//m个关键字,第0个不用
}B_Node,*BTreeRoot;

  

接下来是基于B树的查找

//返回查找成功或者失败,成功时:node为该关键字所在结点的地址,number为该关键字在他节点中的位置,
//失败时:返回false,node为应该插入的结点,number为这个节点中应该插入的位置,
bool find_By_Btree(BTreeRoot root,int* number,B_Node* &node,KeyType k)
{
B_Node *p=root;
int i=1;
while (p)
{
for (i = 1; i <=p->keyNum; i++)
{ if (p->key[i]==k)
{
*number=i;
node=p;
return true;
}
else if (p->key[i]<k)
{
continue;
}
else
{
break;
}
}
node=p;
p=p->childTree[i-1];
}
if (p==nullptr)
{
*number=i;
node=p->parent;
return false;
} }

  

算法分析:通过对B树的树形的分析,不难发现,B树的时间复杂度为O(logm(n)),也可以写为log(n)