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树代码有问题,这次是改掉的,我太不严谨了。
相关文章推荐
- LR(1) 有限状态机的压缩
- Description Resource Path Location Type Java compiler level does not match the version of the instal
- Codeforces Round #363 (Div. 2) C. Vacations
- rabbitMQ学习(七)反馈模式
- Intellij idea 出现错误 error:java: 无效的源发行版: 8解决方法
- DOM—动态样式
- tomcat配置文件server.xml详解
- awk截取字串的方法
- ajax执行后,swiper.js的效果消失问题
- rightclick
- 图片验证码
- L1-030. 一帮一-PAT团体程序设计天梯赛GPLT
- L1-031. 到底是不是太胖了-PAT团体程序设计天梯赛GPLT
- centos安装nodejs
- HttpUrlConnection(GET方式)
- Rotate List
- hdu 5742 It's All In The Mind 水题
- DataTable转CSV
- java连接mysql(二)
- UICollectionView的基本概念与使用