您的位置:首页 > 其它

B树

2016-07-21 18:56 267 查看
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
#include<iostream>

using namespace std;
const unsigned maxsize = 3;
const unsigned maxelem = maxsize - 1;
const unsigned minsize = maxsize / 2;

//   0     1      2      3     4   5
//a     b     d      f      g     h
/*b树的性质如下
根结点至少有 2 个子女。
除根结点以外的所有brch结点至少有 m / 2 个子女。
所有的leaf结点都位于同一层。
*/
typedef struct btnode
{
unsigned num;
struct btnode *parent;
struct btnode *sub[maxsize + 1];
int   data[maxsize + 1];//数据从1开始存放,为了后面插入和删除的方便,需要多加一个空间
}btnode;

typedef struct result
{
unsigned pos;
bool tag;
btnode *pnode;//用来存放查询树的结果.
}result;

btnode * buynode(int key)
{
btnode *temp = (btnode*)malloc(sizeof(btnode));
temp->data[1] = key;
temp->num = 1;
memset(temp->sub, NULL, sizeof(btnode*)*maxsize);
temp->parent = NULL;
return temp;
}
void freenode(btnode *ptr)
{
free(ptr);
}

result find(btnode *ptr, int key)
{
result res = { 0,false,NULL };
if (ptr == NULL)
{
return res;
}

while (ptr != NULL)
{
unsigned i = ptr->num;
for (; i > 0 && key < ptr->data[i]; --i)
{
}
res.pnode = ptr;
res.pos = i;
if (ptr->data[i] == key)
{
res.tag = true;
return res;
}
else
{
ptr = ptr->sub[i];
}
}
return res;
}

btnode * makeroot(int key, btnode *lc, btnode *rc)
{
btnode *ret = buynode(key);
ret->sub[0] = lc;
ret->sub[1] = rc;
if (lc != NULL)
{
lc->parent = ret;
}
if (rc != NULL)
{
rc->parent = ret;
}
return ret;
}
void insert_item(btnode *ptr, unsigned pos, int key, btnode *rc)
{
//btnode *newnode = ptr;
unsigned i = ++ptr->num;

for (; i - 1 > pos; i--)
{
ptr->data[i] = ptr->data[i - 1];
ptr->sub[i] = ptr->sub[i - 1];
}
ptr->data[i] = key;
ptr->sub[i] = rc;
if (rc != NULL)
rc->parent = ptr;

}
void move_elem(btnode *sour, btnode *des, unsigned pos)
{
unsigned j = 0;
for (pos += 1; pos <= sour->num; j++, pos++)
{
des->data[j] = sour->data[pos];
des->sub[j] = sour->sub[pos];
if (des->sub[j] != NULL)
des->sub[j]->parent = des;
}
}
btnode * splice(btnode *ptr)
{
btnode *pa = ptr->parent;
btnode *newnode = buynode(2);
btnode *newroot = NULL;
unsigned pos = minsize;

move_elem(ptr, newnode, pos);
newnode->num = ptr->num - pos;
ptr->num = minsize;
newnode->num--;

if (pa == NULL)
{
newroot = makeroot(newnode->data[0], ptr, newnode);
return newroot;
}
for (pos = pa->num; pos > 0 && newnode->data[0] < pa->data[pos]; pos--)
{
}

insert_item(pa, pos, newnode->data[0], newnode);

if (pa->num > maxelem)
{
return splice(pa);
}
return NULL;
}
//插入数据的入口处
/*
*如果树是空的那么就申请一个根节点.
*树非空,那么就查找到相应的位置,然后插入,不插入重复的数据.
*插入后分为两种情况,一是该分支的节点不超过最大值,则什么都不做
*如果节点数超过最大值那么就需要进行分裂.
* 由于分裂可能会引起多层分裂所以可能会产生新的根节点.
*分裂时,将一个满节点的一半移动到新的节点.然后选出一个来插入到父节点中.
*如果父节点也满了,那么就继续分裂父节点.
*父亲节点是空的那么就申请一个根节点.
***************
*/
bool insert(btnode *&ptr, int key)
{
if (ptr == NULL)
{
btnode *temp = makeroot(key, NULL, NULL);
return true;
}

result res = find(ptr, key);

if (res.tag == true)
{
return false;
}

btnode * inode = res.pnode;
unsigned pos = res.pos;

insert_item(inode, pos, key, NULL);

if (inode->num > maxelem)
{
btnode *newroot = splice(inode);
if (newroot != NULL)
{
ptr = newroot;
}
}
return true;
}

void show(btnode *ptr)
{
if (ptr == NULL) return;
show(ptr->sub[0]);
for (unsigned i = 1; i <= ptr->num; i++)
{
cout << ptr->data[i] << " ";
show(ptr->sub[i]);
}
//cout << endl;
}
void merge_left(btnode *left, btnode *&ptr, unsigned pos)
{
btnode *par = ptr->parent;
left->num++;

//left->data[left->num] = par->data[pos];
//left->num++;
ptr->data[0] = par->data[pos];

for (unsigned i = left->num, j = 0; j <= ptr->num; ++j, ++i)
{
left->data[i] = ptr->data[j];
left->sub[i] = ptr->sub[j];
if (left->sub[i] != NULL)
left->sub[i]->parent = left;
ptr->sub[j] = NULL;
}
left->num += ptr->num;

freenode(ptr);
for (unsigned i = pos; i < par->num; i++)
{
par->data[i] = par->data[i + 1];
par->sub[i] = par->sub[i + 1];
}
par->num--;
ptr = left;
}
bool dele_item(btnode *ptr, unsigned pos)
{
btnode * tmp = ptr;
for (unsigned i = pos; i < ptr->num; ++i)
{
ptr->data[i] = ptr->data[i + 1];
ptr->sub[i] = ptr->sub[i + 1];
}
ptr->sub[ptr->num] = NULL;
ptr->num--;
return true;
}
btnode *find_prev(btnode *ptr, unsigned pos)
{
if (ptr != NULL)
{
ptr = ptr->sub[pos - 1];
while (ptr != NULL &&ptr->sub[ptr->num] != NULL)
{
ptr = ptr->sub[ptr->num];
}
}
return ptr;
}

btnode *find_next(btnode *ptr, unsigned pos)
{
if (ptr != NULL)
{
ptr = ptr->sub[pos];
while (ptr != NULL && ptr->sub[0] != NULL)
{
ptr = ptr->sub[0];
}
}
return ptr;
}
btnode * adjust(btnode *ptr)
{
btnode * ret = NULL;
btnode * par = ptr->parent;
unsigned pos = par->num;
btnode * lbro = NULL;
btnode * rbro = NULL;

for (; pos > 0 && par->sub[pos] != ptr; --pos)
{
}
rbro = par->sub[pos + 1];
if (pos > 0)
lbro = par->sub[pos - 1];

if (lbro != NULL && lbro->num > minsize)
{
ptr->data[0] = par->data[pos];
ptr->num++;
par->data[pos] = lbro->data[lbro->num];

unsigned i = ptr->num;
for (; i > 0; i--)
{
ptr->data[i] = ptr->data[i - 1];
ptr->sub[i] = ptr->sub[i - 1];
}
ptr->sub[i] = lbro->sub[lbro->num];
if (ptr->sub[i] != NULL)
ptr->sub[i]->parent = ptr;
lbro->sub[lbro->num] = NULL;
lbro->num--;
}
else if (rbro != NULL && rbro->num > minsize)
{
ptr->num++;
ptr->data[ptr->num] = par->data[pos + 1];
ptr->sub[ptr->num] = rbro->sub[0];
if (ptr->sub[ptr->num] != nullptr)
ptr->sub[ptr->num]->parent = ptr;

par->data[pos + 1] = rbro->data[1];

unsigned i = 1;
for (; i <= rbro->num; i++)
{
rbro->data[i - 1] = rbro->data[i];
rbro->sub[i - 1] = rbro->sub[i];
}
//  rbro->sub[i - 1] = rbro->sub[i];
rbro->sub[rbro->num] = NULL;
rbro->num--;
}
else if (lbro != NULL)
{
merge_left(lbro, ptr, pos);
}
else if (rbro != NULL)
{
merge_left(ptr, rbro, pos + 1);
}
if (par->parent != NULL && par->num < minsize)
{
ret = adjust(par);
}
else
{
if (par->parent == NULL && par->num <= 0)
{
free(par);
ptr->parent = NULL;
ret = ptr;
}
}
return ret;
}

/*
*删除节点的入口
*先查找,如果存在某个节点.那么进行删除
*删除分为两种情况,删除分支上的节点,还有删除叶子上的节点.
*如果删除的分支上的节点,那么就用他的子分支中的代替.不断递归知道要删除叶子节点.
*删除叶子节点,如果删除后节点个数满足条件,那么什么都不做,如果小于最低限度,则需要借节点,向左或者右借。
*如果不够借,那么就合并节点,由于是合并那么就可能造成分裂。产生新根。
*/
void delenode(btnode *&ptr, int key)
{
if (ptr == NULL) return;
btnode *par = NULL;
result res = find(ptr, key);
if (res.tag == false)
{
return;
}
btnode *resnode = res.pnode;
unsigned pos = res.pos;

btnode * lbr = find_prev(resnode, pos);//寻找左分支的最后一个
btnode * rbr = find_next(resnode, pos);//寻找右分支的第一个

if (lbr != NULL &&lbr->num > minsize)
{
resnode->data[pos] = lbr->data[lbr->num];
resnode = lbr;
pos = lbr->num;  //将左边的代替分支中的。
}
else if (rbr != NULL && rbr->num > minsize)
{
resnode->data[pos] = rbr->data[1];
resnode = rbr;
pos = 1;
}
else if (lbr != NULL)
{
resnode->data[pos] = lbr->data[lbr->num];
resnode = lbr;
pos = lbr->num;
}
else if (rbr != NULL)
{
resnode->data[pos] = rbr->data[1];
resnode = rbr;
pos = 1;
}
dele_item(resnode, pos);
par = resnode->parent;
if (par != NULL && resnode->num < minsize)
{
btnode * temp = adjust(resnode);
if (temp != NULL)
ptr = temp;
}
else if (par == NULL    && resnode->num == 0)
{
free(resnode);
ptr = NULL;
}
}
int main()
{

btnode * root = buynode(50);
for (int i = 0; i < 1000; i++)
{
int ch;
cin >> ch;
if (ch == -1)
break;
insert(root, ch);
}
show(root);
cout << "delete:" << endl;
for (int i = 0; i < 1000; i++)
{
int ch;
cin >> ch;
delenode(root, ch);
show(root);
}
show(root);
}


很惭愧上次的B树代码有问题,这次是改掉的,我太不严谨了。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: