一棵m阶B树是一棵m路搜索树,它或者是空树,或者是满足以下性质的树:
1 根节点子女树为[2,m];
2 除根节点和叶节点以外所有分支结点至少有[m/2,m]个子女;
3 所有叶节点位于同一层。
B树的一些特点:
1 根节点关键字个数[1,m-1],非根节点关键字个数[m/2,m-1];
2 关键字集合分布在整棵树中;
3 关键字不容许重复;
4 搜索可能在非叶子结点结束;
5 搜索性能等价于在关键字全集做一次二分查找
#include<iostream>
#include<stdio.h>
#include<assert.h>
using namespace std;
const int M = 5;
const int MaxElemNum = M - 1;
const int MinElemNum = (M / 2);
typedef char KeyType;
typedef struct{} Record;
typedef struct
{
KeyType key;
Record* recptr;
}ElemType;
typedef struct BNode
{
int num;
struct BNode* parent;
ElemType data[M + 1];
struct BNode* sub[M + 1];
}BNode;
typedef struct
{
BNode* root;
int cursize;
}BTree;
typedef struct
{
struct BNode* pnode;
int index;
bool tag;
}Result;
BNode* BuyNode()
{
BNode* ptr = (BNode*)calloc(1, sizeof(BNode));
if (ptr == nullptr) exit(EXIT_FAILURE);
return ptr;
}
void FreeNode(BNode* ptr)
{
free(ptr);
}
void InitTree(BTree* ptree)
{
assert(ptree != nullptr);
ptree->root = nullptr;
ptree->cursize = 0;
}
Result FindKey(BTree* ptree, const KeyType kx)
{
assert(ptree != nullptr);
Result res = { nullptr,-1,false };
BNode* p = ptree->root;
while (p != nullptr)
{
int i = p->num;
p->data[0].key = kx;
while (kx < p->data[i].key) --i;
res.pnode = p;
res.index = i;
if (i > 0 && p->data[i].key == kx)
{
res.tag = true;
break;
}
p = p->sub[i];
}
return res;
}
BNode* MakeRoot(ElemType item, BNode* left, BNode* right)
{
BNode* s = BuyNode();
s->num = 1;
s->parent = nullptr;
s->data[1] = item;
s->sub[0] = left;
if (left != nullptr) left->parent = s;
s->sub[1] = right;
if (right != nullptr) right->parent = s;
return s;
}
void Insert_Item(BNode* ptr, int pos, ElemType item, BNode* right)
{
assert(ptr != nullptr);
for (int i = ptr->num; i > pos; --i)
{
ptr->data[i + 1] = ptr->data[i];
ptr->sub[i + 1] = ptr->sub[i];
}
ptr->data[pos + 1] = item;
ptr->sub[pos + 1] = right;
if (right != nullptr) right->parent = ptr;
ptr->num += 1;
}
ElemType Move_Item(BNode* ptr, BNode* right)
{
assert(ptr != nullptr && right != nullptr);
for (int i = MinElemNum + 1, j = 0; i <= ptr->num; ++i, ++j)
{
right->data[j] = ptr->data[i];
right->sub[j] = ptr->sub[i];
if (right->sub[j] != nullptr)
{
right->sub[j]->parent = right;
}
}
ptr->num = MinElemNum;
right->num = MinElemNum;
right->parent = ptr->parent;
return right->data[0];
}
BNode* Adjust_Tree(BTree* ptree, BNode* ptr)
{
assert(ptree != nullptr && ptr != nullptr);
BNode* right = BuyNode();
ElemType item = Move_Item(ptr, right);
if (ptr->parent == nullptr)
{
return MakeRoot(item, ptr, right);
}
BNode* pa = ptr->parent;
int pos = pa->num;
pa->data[0] = item;
while (item.key < pa->data[pos].key) --pos;
Insert_Item(pa, pos, item, right);
if (pa->num > MaxElemNum)
{
return Adjust_Tree(ptree, pa);
}
else
{
return nullptr;
}
}
bool Insert(BTree* ptree, ElemType item)
{
assert(ptree != nullptr);
if (ptree->root == nullptr)
{
ptree->root = MakeRoot(item, nullptr, nullptr);
ptree->cursize = 1;
return true;
}
Result res = FindKey(ptree, item.key);
if (res.tag) return false;
BNode* ptr = res.pnode;
int pos = res.index;
Insert_Item(ptr, pos, item,nullptr);
if (ptr->num > MaxElemNum)
{
BNode* newroot = Adjust_Tree(ptree, ptr);
if (newroot != nullptr)
{
ptree->root = newroot;
}
}
ptree->cursize += 1;
return true;
}
void InOrder(BNode* ptr)
{
if (ptr == nullptr) return;
InOrder(ptr->sub[0]);
for(int i = 1; i <= ptr-> num;++i)
{
printf("%3c",ptr->data[i].key);
InOrder(ptr->sub[i]);
}
}
void InOrder(BTree* ptree)
{
assert(ptree != nullptr);
InOrder(ptree->root);
printf("\n");
}
int main()
{
KeyType ar[] = { "q9wer6tyui0o1pa7sd4fghj2kl5z80xcvb3nm" };
int len = strlen(ar);
BTree tree;
InitTree(&tree);
for (int i = 0; i < len; ++i)
{
ElemType item = { ar[i],nullptr };
cout << Insert(&tree, item);
}
cout << endl;
InOrder(&tree);
return 0;
}