B-树是一种平衡的多路查找树,它在文件系统中很有用。[1]
B-树主要用作文件的索引,因此它的查找涉及外存的存取。[1]
B-树适用于:当文件很大时,索引表(树表)本身也在外存,则查找索引时需多次访问外存,并且,访问外存的次数恰为查找路径上的结点数。为减少访问外存的次数,应尽量缩减索引表的深度。此时宜采用m叉的B-树作索引表。m的选择取决于索引项的多少和缓冲区的大小。[1]
实现语言:c++
1.B-树的查找
2.B-树的插入
#ifndef __BTREE_H
#define __BTREE_H
#include <iostream>
using namespace std;
typedef int KeyType;
#define M 3
typedef struct BTNode{
int keynum;
struct BTNode *parent;
KeyType key[M + 1];
struct BTNode *ptr[M + 1];
}BTNode;
typedef struct Result{
BTNode *pt; //指向查找到的结点。
int i; //1..m,结点中的关键字标号
int tag; //1:查找成功。 0:查找失败
}Result; //B-树查找结果类型
class BTree{
public:
BTree();
~BTree();
Result SearchBTree(KeyType k);
void Insert(BTNode *p, int i, KeyType x, BTNode *ap);
void split(BTNode *q, int s, BTNode **ap);
void NewRoot(BTNode *q, KeyType x, BTNode *ap);
int InsertBTree(KeyType K, BTNode *q, int i);
int ShowBTNode(BTNode *p);
int TraverseBTree(BTNode *p);
BTNode * GetRoot();
private:
BTNode *m_root;
};
#endif // __BTREE_H
#include "Btree.h"
BTree::BTree()
{
m_root = NULL;
}
BTree::~BTree()
{
delete m_root;
}
int Search(BTNode *p, KeyType K)
{
int i = 1;
for(i = 1; i <= p->keynum; ++i)
{
if(p->key[i] <= K)
{
if(i == p->keynum)
{
return i;
}
else if(p->key[i + 1] > K)
{
return i;
}
}else
{
return 0;
}
}
return i;
}
Result BTree::SearchBTree(KeyType K)
{
BTNode *p = m_root;
BTNode *q = NULL;
bool found = false;
int i = 0;
while((p != NULL) && !found)
{
i = Search(p, K);
if((i > 0) && (p->key[i] == K))
{
found = true;
}else
{
q = p; p = p->ptr[i];
}
}
if(found) return {p, i, 1};
else return {q, i, 0};
}
void BTree::Insert(BTNode *p, int i, KeyType x, BTNode *ap)
{
int j = p->keynum;
for(;j >= i + 1; --j)
{
p->key[j + 1] = p->key[j];
p->ptr[j + 1] = p->ptr[j];
}
p->key[i + 1] = x;
p->ptr[i + 1] = ap;
p->keynum++;
}
void BTree::split(BTNode *q, int s, BTNode **ap)
{
int i;
*ap = new BTNode;
(*ap)->parent = q->parent;
(*ap)->keynum = M - s;
(*ap)->ptr[0] = q->ptr[s];
for(i = 1; i <= M - s; ++i)
{
(*ap)->key[i] = q->key[s + i];
(*ap)->ptr[i] = q->ptr[s + i];
if(q->ptr[s + i] != nullptr)
{
q->ptr[s + i]->parent = (*ap);
}
// ap->recptr[i] = q->recptr[s + i];
}
q->keynum = s - 1;
}
void BTree::NewRoot(BTNode *q, KeyType x, BTNode *ap)
{
m_root = new BTNode;
m_root->keynum = 1;
m_root->key[1] = x;
m_root->ptr[1] = ap;
m_root->parent = NULL;
m_root->ptr[0] = q;
if(q != NULL)
{
q->parent = m_root;
}
if(ap != NULL)
{
ap->parent = m_root;
}
}
BTNode * BTree::GetRoot()
{
return m_root;
}
int BTree::ShowBTNode(BTNode *p)
{
int i = 1;
for(; i <= p->keynum; ++i)
{
cout << i << ":" << p->key[i] << "| ";
}
cout << endl;
return 1;
}
int BTree::TraverseBTree(BTNode *p)
{
int i;
if(p != NULL)
{
ShowBTNode(p);
for(i = 0; i <= p->keynum; ++i)
{
TraverseBTree(p->ptr[i]);
}
}
return 1;
}
int BTree::InsertBTree(KeyType K, BTNode *q, int i)
{
KeyType x = K;
BTNode *ap = NULL;
bool finished = false;
while((q != NULL) && !finished)
{
Insert(q, i, x, ap);
if(q->keynum < M)
{
finished = true;
}else
{
int s = M / 2 + 1;
split(q, s, &ap);
x = q->key[s];
if(x == 70)
{
cout << "70" << q->parent->key[1] << endl;
}
q = q->parent;
if(q != NULL)
{
i = Search(q, x);
}
}//else
}//while
if(!finished)
{
NewRoot(m_root, x, ap);
}
return 1;
}
#include "Btree.h"
int main()
{
BTree bt;
Result rs;
rs = bt.SearchBTree(45);
bt.InsertBTree(45, rs.pt, rs.i);
rs = bt.SearchBTree(24);
bt.InsertBTree(24, rs.pt, rs.i);
rs = bt.SearchBTree(53);
bt.InsertBTree(53, rs.pt, rs.i);
rs = bt.SearchBTree(90);
bt.InsertBTree(90, rs.pt, rs.i);
rs = bt.SearchBTree(3);
bt.InsertBTree(3, rs.pt, rs.i);
rs = bt.SearchBTree(12);
bt.InsertBTree(12, rs.pt, rs.i);
rs = bt.SearchBTree(37);
bt.InsertBTree(37, rs.pt, rs.i);
rs = bt.SearchBTree(50);
bt.InsertBTree(50, rs.pt, rs.i);
rs = bt.SearchBTree(61);
bt.InsertBTree(61, rs.pt, rs.i);
rs = bt.SearchBTree(70);
// cout << "kk" << rs.pt->key[1] << " " << rs.i << endl;
bt.InsertBTree(70, rs.pt, rs.i);
rs = bt.SearchBTree(100);
bt.InsertBTree(100, rs.pt, rs.i);
bt.TraverseBTree(bt.GetRoot());
}
参考资料:
[1] 数据结构: C语言版/严蔚敏,吴伟民编著.