本文是針對[數據結構基礎系列(8):查找]的實踐。
【項目 - B-樹的基本操作】
實現B-樹的基本操作。基于序列{4, 9, 0, 1, 8, 6, 3, 5, 2, 7}完成測試。
(1)創建對應的3階B-樹b,用括號法輸出b樹。
(2)從b中分別刪除關鍵字為8和1的節點,用括號法輸出刪除節點后的b樹。
[參考解答]
#include <stdio.h>
#include <malloc.h>
#define MAXM 10
typedef int KeyType;
typedef struct node
{
int keynum; KeyType key[MAXM];
struct node *parent;
struct node *ptr[MAXM];
} BTNode;
typedef struct
{BTNode *pt;
int i;
int tag;
} Result;
int m;
int Max;
int Min;
int Search(BTNode *p,KeyType k)
{
int i=
0;
for(i=
0; i<p->keynum && p->key[i+
1]<=k; i++);
return i;
}
Result SearchBTree(BTNode *t,KeyType k)
{BTNode *p=t,*q=NULL;
int found=
0,i=
0;Result r;
while (p!=NULL && found==
0){i=Search(p,k);
if (i>
0 && p->key[i]==k) found=
1;
else{q=p;p=p->ptr[i];}}r.i=i;
if (found==
1) {r.pt=p;r.tag=
1;}
else {r.pt=q;r.tag=
0;}
return r;
}
void Insert(BTNode *&q,
int i,KeyType x,BTNode *ap)
{
int j;
for(j=q->keynum; j>i; j--) {q->key[j+
1]=q->key[j];q->ptr[j+
1]=q->ptr[j];}q->key[i+
1]=x;q->ptr[i+
1]=ap;
if (ap!=NULL) ap->parent=q;q->keynum++;
}
void Split(BTNode *&q,BTNode *&ap)
{
int i,s=(m+
1)/
2;ap=(BTNode *)
malloc(
sizeof(BTNode)); ap->ptr[
0]=q->ptr[s];
for (i=s+
1; i<=m; i++){ap->key[i-s]=q->key[i];ap->ptr[i-s]=q->ptr[i];
if (ap->ptr[i-s]!=NULL)ap->ptr[i-s]->parent=ap;}ap->keynum=q->keynum-s;ap->parent=q->parent;
for (i=
0; i<=q->keynum-s; i++)
if (ap->ptr[i]!=NULL) ap->ptr[i]->parent = ap;q->keynum=s-
1;
}
void NewRoot(BTNode *&t,BTNode *p,KeyType x,BTNode *ap)
{t=(BTNode *)
malloc(
sizeof(BTNode));t->keynum=
1;t->ptr[
0]=p;t->ptr[
1]=ap;t->key[
1]=x;
if (p!=NULL) p->parent=t;
if (ap!=NULL) ap->parent=t;t->parent=NULL;
}
void InsertBTree(BTNode *&t, KeyType k, BTNode *q,
int i)
{BTNode *ap;
int finished,needNewRoot,s;KeyType x;
if (q==NULL) NewRoot(t,NULL,k,NULL);
else{x=k;ap=NULL;finished=needNewRoot=
0;
while (needNewRoot==
0 && finished==
0){Insert(q,i,x,ap);
if (q->keynum<=Max) finished=
1;
else{s=(m+
1)/
2;Split(q,ap);x=q->key[s];
if (q->parent) {q=q->parent;i=Search(q, x);}
else needNewRoot=
1;}}
if (needNewRoot==
1) NewRoot(t,q,x,ap); }
}
void DispBTree(BTNode *t)
{
int i;
if (t!=NULL){
printf(
"[");
for (i=
1; i<t->keynum; i++)
printf(
"%d ",t->key[i]);
printf(
"%d",t->key[i]);
printf(
"]");
if (t->keynum>
0){
if (t->ptr[
0]!=
0)
printf(
"(");
for (i=
0; i<t->keynum; i++) {DispBTree(t->ptr[i]);
if (t->ptr[i+
1]!=NULL)
printf(
",");}DispBTree(t->ptr[t->keynum]);
if (t->ptr[
0]!=
0)
printf(
")"); }}
}
void Remove(BTNode *p,
int i)
{
int j;
for (j=i+
1; j<=p->keynum; j++) {p->key[j-
1]=p->key[j];p->ptr[j-
1]=p->ptr[j];}p->keynum--;
}
void Successor(BTNode *p,
int i)
{BTNode *q;
for (q=p->ptr[i]; q->ptr[
0]!=NULL; q=q->ptr[
0]);p->key[i]=q->key[
1];
}
void MoveRight(BTNode *p,
int i)
{
int c;BTNode *t=p->ptr[i];
for (c=t->keynum; c>
0; c--) {t->key[c+
1]=t->key[c];t->ptr[c+
1]=t->ptr[c];}t->ptr[
1]=t->ptr[
0]; t->keynum++;t->key[
1]=p->key[i];t=p->ptr[i-
1]; p->key[i]=t->key[t->keynum];p->ptr[i]->ptr[
0]=t->ptr[t->keynum];t->keynum--;
}
void MoveLeft(BTNode *p,
int i)
{
int c;BTNode *t;t=p->ptr[i-
1]; t->keynum++;t->key[t->keynum]=p->key[i];t->ptr[t->keynum]=p->ptr[i]->ptr[
0];t=p->ptr[i]; p->key[i]=t->key[
1];p->ptr[
0]=t->ptr[
1];t->keynum--;
for (c=
1; c<=t->keynum; c++) {t->key[c]=t->key[c+
1];t->ptr[c]=t->ptr[c+
1];}
}
void Combine(BTNode *p,
int i)
{
int c;BTNode *q=p->ptr[i]; BTNode *l=p->ptr[i-
1];l->keynum++; l->key[l->keynum]=p->key[i];l->ptr[l->keynum]=q->ptr[
0];
for (c=
1; c<=q->keynum; c++) {l->keynum++;l->key[l->keynum]=q->key[c];l->ptr[l->keynum]=q->ptr[c];}
for (c=i; c<p->keynum; c++) {p->key[c]=p->key[c+
1];p->ptr[c]=p->ptr[c+
1];}p->keynum--;
free(q);
}
void Restore(BTNode *p,
int i)
{
if (i==
0)
if (p->ptr[
1]->keynum>Min)MoveLeft(p,
1);
elseCombine(p,
1);
else if (i==p->keynum)
if (p->ptr[i-
1]->keynum>Min)MoveRight(p,i);
elseCombine(p,i);
else if (p->ptr[i-
1]->keynum>Min) MoveRight(p,i);
else if (p->ptr[i+
1]->keynum>Min)MoveLeft(p,i+
1);
elseCombine(p,i);
}
int SearchNode(KeyType k,BTNode *p,
int &i)
{
if (k<p->key[
1]) {i=
0;
return 0;}
else {i=p->keynum;
while (k<p->key[i] && i>
1)i--;
return(k==p->key[i]);}
}
int RecDelete(KeyType k,BTNode *p)
{
int i;
int found;
if (p==NULL)
return 0;
else{
if ((found=SearchNode(k,p,i))==
1) {
if (p->ptr[i-
1]!=NULL) {Successor(p,i); RecDelete(p->key[i],p->ptr[i]); }
elseRemove(p,i); }
elsefound=RecDelete(k,p->ptr[i]);
if (p->ptr[i]!=NULL)
if (p->ptr[i]->keynum<Min) Restore(p,i);
return found;}
}
void DeleteBTree(KeyType k,BTNode *&root)
{BTNode *p;
if (RecDelete(k,root)==
0)
printf(
" 關鍵字%d不在B-樹中\n",k);
else if (root->keynum==
0){p=root;root=root->ptr[
0];
free(p);}
}
int main()
{BTNode *t=NULL;Result s;
int j,n=
10;KeyType a[]= {
4,
9,
0,
1,
8,
6,
3,
5,
2,
7},k;m=
3; Max=m-
1;Min=(m-
1)/
2;
printf(
"創建一棵%d階B-樹:\n",m);
for (j=
0; j<n; j++) {s=SearchBTree(t,a[j]);
if (s.tag==
0)InsertBTree(t,a[j],s.pt,s.i);
printf(
" 第%d步,插入%d: ",j+
1,a[j]);DispBTree(t);
printf(
"\n");}
printf(
" 結果B-樹: ");DispBTree(t);
printf(
"\n");
printf(
"刪除操作:\n");k=
8;DeleteBTree(k,t);
printf(
" 刪除%d: ",k);
printf(
"B-樹: ");DispBTree(t);
printf(
"\n");k=
1;DeleteBTree(k,t);
printf(
" 刪除%d: ",k);
printf(
"B-樹: ");DispBTree(t);
printf(
"\n");
return 0;
}
總結
以上是生活随笔為你收集整理的数据结构实践——B-树的基本操作的全部內容,希望文章能夠幫你解決所遇到的問題。
如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。