B树
B-tree树,一个m阶B数
目录结构
1.根节点子女数为[2,m],m必须是奇数
2.除根结点和叶节点以外的所有分支节点至少右[[m/2],m]个子女
3.所有节点都位于同一层。(天生就是平衡树)
4.m阶B-tree树的节点结构如下
B树的插入
父节点大于左边的子节点,小于右边的子节点。能放数据的只有1,2,3,4. 0号位置是哨兵位,先存在这里面然后和后面的比较啊
父子都有6个节点,0是存刚插入的数据,确定位置后插入,父节点最多存4个节点,当多余4个节点时候就分裂成三个,两个在左两个在右,中间的在上面,如下图
num这一层有几个数据,parent它的父节点是谁,k[0]是一个哨兵位,k[1]大于sub[0]指针指向的数据值,
B树的删除
m=5
m/2=2
从叶子开始删除,要删除那个节点,就把这个节点和它的直接前驱将这个节点改成直接前驱的值(只有当直接前驱的数据大于(m/2)个的时候才互换),然后删除它的叶子节点,如果直接前驱少于(m/2)个,就找他的直接后继(当直接后继多于(m/2)个的时候),将后继的值赋值给那个节点,删除完之后需要移动数据
如果删除的不够了,就先将这个节点左边的值移动过来,如果左边的值也不够了,再移动右边的值,移动的时候先把移动根节点移下来,再将根节点左边的值移上去,右边同理
如果删除到最后左右两边都只剩两个了,删除掉之后合并,把根节点移到左边,再把右边的数据都移到左边,如下图
无论是借数据还是合并数据,都是先左后右
#define M 5 // M 奇数 //
#define BRCHMAX (M-1) // // SUB M
#define BRCHMIN (M/2); // SUB M/2+1
#define LEAFMAX (M) // MAX ELEM 5
#define LEAFMIN (M/2+1) // MIN ELEM; 3
typedef int KeyType;
typedef struct {}Record;
typedef enum { BRCH = 1, LEAF = 2 } NodeType;
typedef struct BNode
{
int num; // elem size; // LEFT BRCH
BNode* parent;
NodeType utype; // LEAF , BRCH;
KeyType key[M + 1];
union
{
struct // LEAF
{
Record* recptr[M + 1];
BNode* prev, * next;
};
// BRCH;
BNode* sub[M + 1];
};
}BNode;
typedef struct
{
struct BNode* root;
struct BNode* first;
int cursize;
}BTree;
typedef struct
{
struct BNode* pnode; //
int index; //
bool tag; //
}Result;
BNode* Buynode()
{
BNode* s = (BNode*)malloc(sizeof(BNode));
if (nullptr == s) exit(1);
memset(s, 0, sizeof(BNode));
return s;
}
BNode* BuyLeaf()
{
BNode* s = Buynode();
s->parent = nullptr;
s->utype = LEAF;
return s;
}
BNode* BuyBrchnode()
{
BNode* s = Buynode();
s->parent = nullptr;
s->utype = BRCH;
return s;
}
void Init_BTree(BTree& tree)
{
tree.root = nullptr;
tree.first = nullptr;
tree.cursize = 0;
}
BNode* MakeRoot(const KeyType kx, BNode* left, BNode* right)
{
BNode* s = Buynode();
s->utype = BRCH;
s->num = 1;
s->parent = nullptr;
s->key[1] = kx;
s->sub[0] = left;
if (left != nullptr) left->parent = s;
s->sub[1] = right;
if (right != nullptr) right->parent = s;
return s;
}
Result FindLeaf(BNode* ptr, KeyType kx)
{
Result res = { nullptr,-1,false };
BNode* p = ptr;
while (p != nullptr && p->next != nullptr && kx > p->key[p->num - 1])
{
p = p->next;
}
if (p == nullptr) return res;
int pos = p->num - 1;
while (pos >= 0 && kx < p->key[pos])
{
--pos;
}
res.pnode = p;
res.index = pos;
if (pos < 0 && p->prev != nullptr)
{
res.pnode = p->prev;
res.index = p->prev->num - 1;
}
else if (pos >= 0 && kx == p->key[pos])
{
res.tag = true;
}
return res;
}
Result FindRoot(BNode* ptr, KeyType kx)
{
Result res = { nullptr,-1,false };
BNode* p = ptr;
while (p != nullptr && p->utype == BRCH)
{
p->key[0] = kx;
int i = p->num;
while (kx < p->key[i]) --i;
p = p->sub[i];
}
res = FindLeaf(p, kx);
return res;
}
void Insert_Leaf_Item(BNode *ptr,int pos,KeyType kx, Record *rec)
{
for (int i = ptr->num - 1; i > pos; --i)
{
ptr->key[i + 1] = ptr->key[i];
ptr->recptr[i + 1] = ptr->recptr[i];
}
ptr->key[pos + 1] = kx;
ptr->recptr[pos + 1] = rec;
ptr->num += 1;
}
KeyType Move_Leaf_Item(BNode* s, BNode* ptr)
{
for (int i = 0, j = LEAFMIN; j < ptr->num; ++i, ++j)
{
s->key[i] = ptr->key[j];
s->recptr[i] = ptr->recptr[j];
}
s->num = LEAFMIN;
ptr->num = LEAFMIN;
s->parent = ptr->parent;
s->next = ptr->next;
s->prev = ptr;
ptr->next = s;
if (s->next != nullptr)
{
s->next->prev = s;
}
return s->key[0];
}
void Insert_Brch_Item(BNode* ptr, int pos, KeyType kx, BNode* right)
{
for (int i = ptr->num; i > pos; --i)
{
ptr->key[i + 1] = ptr->key[i];
ptr->sub[i + 1] = ptr->sub[i];
}
ptr->key[pos + 1] = kx;
ptr->sub[pos + 1] = right; // right->parent;
ptr->num += 1;
}
KeyType Move_Brch_Item(BNode* s, BNode* ptr)
{
for (int i = 0, j = LEAFMIN + 1; j <= ptr->num; ++i, ++j)
{
s->key[i] = ptr->key[j];
s->sub[i] = ptr->sub[j];
if (s->sub[i] != nullptr) // ptr leaf . brch;
{
s->sub[i]->parent = s;
}
}
s->num = LEAFMIN;
ptr->num = LEAFMIN;
s->parent = ptr->parent;
return s->key[0];
}
BNode* Splice_Brch(BNode* ptr)
{
BNode* s = BuyBrchnode();
KeyType kx = Move_Brch_Item(s, ptr);
if (ptr->parent == nullptr)
{
return MakeRoot(kx, ptr, s);
}
BNode* pa = ptr->parent;
int pos = pa->num;
pa->key[0] = kx; //
while (pos > 0 && kx < pa->key[pos]) { --pos; }
Insert_Brch_Item(pa, pos,kx, s);
if (pa->num > LEAFMAX)
{
return Splice_Brch(pa);
}
else
{
return nullptr;
}
}
BNode* Splice_Leaf(BNode* ptr)
{
BNode* s = BuyLeaf();
KeyType kx = Move_Leaf_Item(s, ptr);
if (ptr->parent == nullptr)
{
return MakeRoot(kx, ptr, s);
}
BNode* pa = ptr->parent;
int pos = pa->num;
pa->key[0] = kx; //
while (pos > 0 && kx < pa->key[pos]) { --pos; }
Insert_Brch_Item(pa, pos, kx, s);
if (pa->num > BRCHMAX)
{
return Splice_Brch(pa);
}
else
{
return nullptr;
}
}
bool Insert(BTree& tree, KeyType kx, Record* rec)
{
if (tree.root == nullptr)
{
BNode* s = BuyLeaf();
s->key[0] = kx;
s->recptr[0] = rec;
s->num = 1;
tree.root = tree.first = s;
return true;
}
Result resr = FindRoot(tree.root, kx);
Result resf = FindLeaf(tree.first, kx);
if (resf.pnode == nullptr)
{
cout << "Btree struct error " << endl;
return false;
}
if (resf.tag)
{
cout << " xxx " << endl;
return false;
}
BNode *ptr = resf.pnode;
int pos = resf.index;
Insert_Leaf_Item(ptr, pos, kx, rec);
if (ptr->num > LEAFMAX)
{
BNode* newroot = Splice_Leaf(ptr);
if (newroot != nullptr)
{
tree.root = newroot;
}
}
return true;
}
int main()
{
int ar[] = { 23,33,12,10,48,50 };
int n = sizeof(ar) / sizeof(ar[0]);
BTree myt;
Init_BTree(myt);
int i = 0;
while (i < n)
{
Insert(myt, ar[i], nullptr);
++i;
}
return 0;
}