B树的基本例程:删除
来源:互联网 发布:美国网件访客网络 编辑:程序博客网 时间:2024/06/06 02:33
摘要:删除操作与插入基本相似,但是比较复杂(算法部分取自算法导论)。
(0)因为删除操作可以从任意内部节点删除,这导致必须安排它的子女;
(1)除了根节点,一定要保证删除不会使得该节点的元素个数少于t-1个.
(3)因此在递归降至某个节点之前,一定要保证它的父节点有t个子女.
下面分几种情况讨论B树删除的操作:
(1)如果关键字k在节点x中,且x是个叶子节点,则删除x;
(2)如果关键字k在节点x中且x是个内节点,则有如下操作;
a)如果节点x中前于k的子节点y包含至少k个关键字,则找出以y为根的子树前驱k’,递归的删除k’,并在x中用k’取代k.
b)对称的,如果节点x中位于k之后的子节点z包含至少t个关键字,则可以找出k在以z为根的子树中的后继k’,递归的删除k’,并用k’代替k。
c)如果关键字k的前后子节点都只有t-1个关键字,就将y和z合并到y,这使得x失去指向k和z的指针,释放z并将k从y中递归的删除z.
3)如果k不在内节点x中,则确定必包含k的正确子树的根ci[x],如果ci[x]只有t-1个关键字,执行步骤3(a/b),保证我们降至一个有t个关键字的节点.
a)如果ci[x]只有t-1个关键字,但他的一个兄弟包含t个关键字,则x中的某一个关键字降至ci[x],将ci[x]相邻兄弟的某一关键字上升到x。
b)如果ci[x]与相邻兄弟都只有t-1个关键字,就将ci[x]与一个兄弟合并,即将x的一个关键字降至新合并的节点(这里会让父节点减少,因此必须保证每一个节点被到达之前都有t的关键字,否则就需要回溯).
void combine(Position T,Position T2,int x){ //把关键字x,T2中所有的关键字合并入T int max = maxIndex(T); int j = 0; T->data[max + 1] = x;//合并关键字与子节点 for(int i = max + 2;i<=2*DU-2;i++) T->data[i] = T2->data[j++]; j = 0; for(int i = max + 2;i<=2*DU-1;i++) T->child[i] = T2->child[j++];}int FindPrevious(Position T)//前继{ int max = maxIndex(T); while (!T->isLeaf) { T = T->child[max+1]; max = maxIndex(T); } return T->data[max];}int FindNext(Position T)//后继{ while(!T->isLeaf) T = T->child[0]; return T->data[0];}void DeleteBtree(Position *T,int x){ int k,indexmax,j; int temp,max; Position C,Temp;//用来保存正确的子节点 if((*T) == NULL) //没有删除成功 return; int i = 0; max = maxIndex(*T); while(i<= max&&x>(*T)->data[i]) i++; if (i<=2*DU-2&&x == (*T)->data[i]) { if ((*T)->isLeaf == 1) //x在叶子节点上 shiftLeft(*T,i,1);//左移一位 else //x在内节点 { if( pageSize((*T)->child[i]) >=DU ) { k = FindPrevious((*T)->child[i]); (*T)->data[i] = k; DeleteBtree( &(*T)->child[i],k); } else if ( pageSize((*T)->child[i+1]) >=DU ) { indexmax = maxIndex((*T)->child[i+1]); k = FindNext((*T)->child[i+1]); (*T)->data[i] = k; DeleteBtree( &(*T)->child[i+1],k); } else { //合并 combine((*T)->child[i],(*T)->child[i+1],x); free((*T)->child[i+1]); for( j = i;j<=2*DU-3;j++) { (*T)->data[j] = (*T)->data[j+1]; (*T)->child[j+1] = (*T)->child[j+2]; } (*T)->data[j] = 0; (*T)->child[j+1] = NULL;//以上为对T的关键字和子节点进行移动 DeleteBtree(&(*T)->child[i],x);//在合并的新节点递归的删除关键字x } }//x 在内部节点 }//x在当前节点 else if ((*T)->isLeaf == 1) puts("not found"); else { //继续向下找 C = (*T)->child[i]; if(pageSize(C) == DU-1) { max = maxIndex(*T)+1; temp = -1; //执行下列步骤保证降至一个包含t个关键字的节点 if(i == 0&&(pageSize((*T)->child[i+1]) >=DU)) temp = 0;//右兄弟 else if ( i == max&&(pageSize((*T)->child[i-1]) >=DU)) temp = 1;//左兄弟 else { if(pageSize((*T)->child[i+1]) >=DU ) temp = 0; else if (pageSize((*T)->child[i-1]) >=DU) temp = 1; } //将*T中的合适关键字降入C中,将C的左/右兄弟的合适关键字放入T中 if(temp == 0)//右兄弟 { C->data[maxIndex(C)+1] = (*T)->data[0];//将T的最小关键字给C作为C的最大关键字 C->child[maxIndex(C)+2] = (*T)->child[i+1]->child[0];//将右兄弟的最左子节点合并到C shiftLeft(*T,0,1); (*T)->data[maxIndex(*T)] = (*T)->child[i+1]->data[0];//将右兄弟最小关键字给T的最大 shiftLeft((*T)->child[i+1],0,1); } else if (temp == 1)//左兄弟 { max = maxIndex((*T)->child[i-1]); shiftRight(C,0); C->data[0] = (*T)->data[maxIndex(*T)]; C->child[0] = (*T)->child[i-1]->child[max+1]; (*T)->data[maxIndex(*T)] = (*T)->child[i-1]->data[max];//将左兄弟最大关键字给T shiftLeft( (*T)->child[i-1],max,1);//删除左兄弟的最大关键字 } else //合并C与左/右兄弟 { if (i== 0) //合并右兄弟 { combine(C,(*T)->child[i+1],(*T)->data[i]); free((*T)->child[i+1]); for( j = i;j<=2*DU-3;j++) { (*T)->data[j] = (*T)->data[j+1]; (*T)->child[j+1] = (*T)->child[j+2]; } (*T)->data[i] = 0; (*T)->child[j] = NULL;//以上为对T的关键字和子节点进行移动 } else { //合并左兄弟 combine((*T)->child[i-1],C,(*T)->data[i-1]); free(C); C = (*T)->child[i-1]; for( j = i;j<=2*DU-3;j++) { (*T)->data[j] = (*T)->data[j+1]; (*T)->child[j] = (*T)->child[j+1]; } (*T)->data[i-1] = 0; (*T)->child[j] = NULL;//以上为对T的关键字和子节点进行移动 (*T)->child[j+1] = NULL; } } } // C满足至少t个节点,递归删除x DeleteBtree( &C,x); } //检测是否为空,否则删除空根 if(pageSize(*T) == 0) { if ((*T)->parent == NULL) { Temp = *T; (*T) = (*T)->child[0]; (*T)->parent = NULL; free(Temp); } }}
0 0
- B树的基本例程:删除
- B树的基本例程(1)插入
- 伸展树的删除例程
- 二叉查找树的基本例程
- 线索树的基本例程:(2)
- 链表:基本例程的实现
- 二叉树的基本运算及其实现的例程
- 实现基本二叉查找树操作的例程
- 标题:AVL树的基本操作例程(1)
- 3、B-树的删除
- B树的删除操作
- B 树的删除操作
- B树的基本操作
- B-树的基本操作 .
- B-树的基本操作
- B-树的基本操作
- 分离链接散列表的删除例程
- 链表的基本实现例程
- Cannot unwrap to requested type [javax.sql.DataSource]
- java Web项目启动 执行一个方法,执行一个清理工作
- google-play-services_lib添加不成功的解决方案
- iFrame跨域解决办法
- VS中的空格/Tab显示为绿点和箭头的快捷键(Ctrl + r, ctrl + w, )
- B树的基本例程:删除
- 多态中成员函数以及成员变量的特点总结:
- Git SSH Key的配置好却每次需要输入账号密码解决方法
- MyBatis Spring 注解事务配置
- 2MSL TCP三次握手连接与四次握手关闭过程
- 设计模式总结(备忘录)
- Cadence元件库介绍
- Android-高效加载图片经验分享
- SQL 语法的 Pig 实现 (转)