数据结构B树完整实现代码(有借鉴有原创)

1 题目
	采用整型类型为元素类型和结构链表为存储结构,实现抽象类型B树。
	ADT BTree{
		数据对象: D={ ai | ai∈ElemSet, i=1,2,...,n,  n≥0 }
		基本操作:
			void init(t):
操作结果:初始化B树,将B树置为空
searchBTree(BTree t,int k,result &r):
操作结果:在B树中查找关键字k,r.tag==1为找到
          r.tag==0为找不到
search(BTree p,int k):
操作结果:在结点p中找关键字k的位置
newBTreeroot(BTree &t,BTree p,int k,BTree q):
操作结果:新建根节点t
insertBTree(BTree &t,int k):
操作结果:在B树中加入关键字k
insert(BTree p,int k,BTree ap,int i):
操作结果:在p结点中插入关键字k
spilt(BTree p,BTree ap,int s):
操作结果:将结点以位置s为中心拆成两部分
Remove(BTree p,int k):
操作结果:在结点p中删除关键字k
void findNode(BTree p,int k,int &i):
操作结果:在结点p中寻找k的位置
deleteBTree(BTree t,int k):
操作结果:在B树中删除的总函数借口
deleteNode(BTree p,int k):
操作结果:在B树中删除关键字k
substitution(BTree p,int i):
操作结果:向右子树借最小值,将最小值付给当前结点关键值,然后 删除右子树最小值
adjustBTree(BTree p,int i):
			操作结果:结点长度小于Min进行调整为满足最小关键字
leftMove(BTree p,int i):
操作结果:向右结点借值赋值给p结点的i位置,将p结点的i位置的值合并到左结点
rightMove(BTree p,int i):向左结点借值赋值给p结点的i位置,将p结点的i位置的值合并到右结点
combine(BTree p,int i):
操作结果:左右不够借,合并三个元素即左右结点和p结点的i位置元素
DestoryBTree(BTree &t):
操作结果:销毁B树
printBTree(BTree t)
操作结果:用模拟队列输出层序遍历的B树
}ADT BTree
2 存储结构定义
公用头文件DSO.h:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>

#define TRUE 1 
#define FALSE 0
#define OK     1
#define ERROR  0
#define IBFEASIBLE  -1
#define OVERFLOW    -2 
	
#define MAXM  1000

Typedef int keyelem
(1)	结点信息类型
typedef struct rt{          //定义结点信息
    int key[m+1];           //结点关键字数组,key[0]不用
    int keynum;             //结点关键字个数
    struct rt* parent;      //双亲结点指针
    struct rt* ptr[m+1];    //孩子结点指针
}BNT,*BTree;
(2)查找结果类型
	typedef struct op{          //查找结果
      int i;                  //结点的关键字位置或需插入位置
      int tag;                //成功与否标志
      BTree pt;               //找到的结点
}result;
(3)模拟队列无头结点存储结构
		typedef struct qp{          //模拟队列
    	BTree pt;               //指向B树结点(数据域)
    	struct qp* next;        //下一个队列指针(指针域)
}queueBNT,*queueBTree;
3算法设计:
/**B树的抽象实现**/
const int m=4;              //B树的阶树
const int Max=m-1;          //最大的关键字个数
const int Min=(m-1)/2;      //最小的关键字个数

typedef struct rt{          //定义结点信息
    int key[m+1];           //结点关键字数组,key[0]不用
    int keynum;             //结点关键字个数
    struct rt* parent;      //双亲结点指针
    struct rt* ptr[m+1];    //孩子结点指针
}BNT,*BTree;

typedef struct op{          //查找结果
    int i;                  //结点的关键字位置或需插入位置
    int tag;                //成功与否标志
    BTree pt;               //找到的结点
}result;

typedef struct qp{          //模拟队列
    BTree pt;               //指向B树结点(数据域)
    struct qp* next;        //下一个队列指针(指针域)
}queueBNT,*queueBTree;

int search(BTree p,int k) { //在子树p中寻找结点k
    int i=1;
    while(i<=p->keynum&&p->key[i]<k)i++;
    return i;
}

void init(BTree &t){         //初始化B树
    t==NULL;
}

void searchBTree(BTree t,int k,result &r) { //在B树t中查找结点
    int finshed=0,i=0;
    BTree p=t,q=NULL;
    while(p!=NULL&&finshed==0) {
        i=search(p,k);
        if(i<=p->keynum&&p->key[i]==k)finshed=1;
        else {
            q=p;
            p=p->ptr[i-1];
        }
    }
    if(finshed==1) {                         //找到结点
        r.tag=1; r.i=i; r.pt=q;
    }
    else {                                   //找不到结点
        r.tag=0; r.i=i; r.pt=q;
    }
}

void newBTreeroot(BTree &t,BTree p,int k,BTree aq) {
    t=(BTree)malloc(sizeof(BNT));
    t->key[1]=k; t->keynum=1;
    t->ptr[0]=p; t->ptr[1]=aq;
    if(p!=NULL)p->parent=t;
    if(aq!=NULL)aq->parent=t;
    t->parent=NULL;
}

void insert(BTree p,int k,BTree &ap,int i) {	//在p结点中插入关键字k
    int j;
    for(j=p->keynum;j>=i;j--) {
        p->key[j+1]=p->key[j];
        p->ptr[j+1]=p->ptr[j];
    }
    p->key[i]=k; p->ptr[i]=ap;
    if(ap!=NULL)ap->parent=p;
    p->keynum++;
}

void spilt(BTree p,BTree &ap,int s) {//将结点以位置s为中心拆成两部分
    int i,j;
    ap=(BTree)malloc(sizeof(BNT));
    ap->ptr[0]=p->ptr[s];
    for(j=s+1,i=1;j<=p->keynum;i++,j++) {
        ap->key[i]=p->key[j];
        ap->ptr[i]=p->ptr[j];
    }
    ap->keynum=p->keynum-s;
    ap->parent=p->parent;
    for(i=0;i<=ap->keynum;i++) {
        if(ap->ptr[i]!=NULL)ap->ptr[i]->parent=ap;
    }
    p->keynum=s-1;
}

void insertBTree(BTree &t,int k) {//在B树中添加k关键字
    result r;
    searchBTree(t,k,r);
    if(r.tag==1)return ;//关键字已经存在
    BTree p=r.pt; int i=r.i;
    BTree ap; int x,s,finshed,needNewroot;
    x=k; ap=NULL; finshed=needNewroot=0;
    if(p==NULL) newBTreeroot(t,NULL,k,NULL);
    else {
        while(finshed==0&&needNewroot==0) {
            insert(p,x,ap,i);
            if(p->keynum<=Max)finshed=1;
            else {
                s=(m+1)>>1; spilt(p,ap,s);
                x=p->key[s];
                if(p->parent!=NULL) {
                    p=p->parent;
                    i=search(p,x);
                }
                else needNewroot=1;
            }
        }
        if(needNewroot==1) newBTreeroot(t,p,x,ap);
    }
}

void findNode(BTree p,int k,int &i) {	//在结点p中寻找k的位置
    i=p->keynum;
    while(i>0&&p->key[i]>k)i--;
}

void substitution(BTree p,int i) {		//向右子树借最小值
    BTree ap=p->ptr[i];
    while(ap->ptr[0]){
        ap=ap->ptr[0];
    }
    p->key[i]=ap->key[1];
}

void remove(BTree p,int i) {			//在结点p中删除关键字k
    int j;
    p->keynum--;
    for(j=i;j<=p->keynum;j++) {
        p->key[j]=p->key[j+1];
        p->ptr[j]=p->ptr[j+1];
    }
}

void leftMove(BTree p,int i) {			//向右结点借值
    int j;
    BTree q=p->ptr[i-1],ap=p->ptr[i];
    q->keynum++;
    q->key[q->keynum]=p->key[i];
    q->ptr[q->keynum]=ap->ptr[0];
    if(ap->ptr[0]!=NULL)ap->ptr[0]->parent=p->ptr[i-1];

    p->key[i]=ap->key[1];
    ap->ptr[0]=ap->ptr[1];
    ap->keynum--;
    for(j=1;j<=ap->keynum;j++) {
        ap->key[j]=ap->key[j+1];
        ap->ptr[j]=ap->ptr[j+1];
    }
}

void rightMove(BTree p,int i) {			//向左结点借值	
    int j;
    BTree q=p->ptr[i-1],ap=p->ptr[i];
    ap->keynum++;
    for(j=ap->keynum;j>1;j--){
        ap->key[j]=ap->key[j-1];
        ap->ptr[j]=ap->ptr[j-1];
    }
    ap->key[1]=p->key[i]; ap->ptr[1]=ap->ptr[0];
    ap->ptr[0]=q->ptr[q->keynum];
    if(q->ptr[q->keynum]!=NULL)q->ptr[q->keynum]->parent=p->ptr[i];

    p->key[i]=q->key[q->keynum];
    q->keynum--;
}

void combine(BTree p,int i) {			//左右不够借,合并三个元素
    int j,k;
    BTree q=p->ptr[i-1],ap=p->ptr[i];
    j=q->keynum;
    q->key[++j]=p->key[i];q->ptr[j]=ap->ptr[0];
    for(k=1;k<=ap->keynum;k++){
        q->key[++j]=ap->key[k];
        q->ptr[j]=ap->ptr[k];
    }
    for(k=q->keynum+1;k<=j;k++){
        if(q->ptr[k]!=NULL)q->ptr[k]->parent=p->ptr[i-1];
    }
    q->keynum=j;

    p->keynum--;
    for(j=i;j<=p->keynum;j++){
        p->key[j]=p->key[j+1];
        p->ptr[j]=p->ptr[j+1];
    }
    free(ap);
}

void adjustBTree(BTree p,int i) {					// //结点长度小于Min进行调整
    if(i==0){
        if(p->ptr[1]->keynum>Min)leftMove(p,1);
        else combine(p,1);
    }
    else if(i==p->keynum) {
        if(p->ptr[i-1]->keynum>Min)rightMove(p,i);
        else combine(p,i);
    }
    else {
        if(p->ptr[i-1]->keynum>Min)rightMove(p,i);
        else if(p->ptr[i+1]->keynum>Min)leftMove(p,i+1);
        else combine(p,i);
    }
}

int deleteNode(BTree p,int k) {		//在B树中删除关键字k
    if(p==NULL)return 0;
    int i,flag=0;
    findNode(p,k,i);
    if(i>0&&p->key[i]==k) {
        flag=1;
        if(p->ptr[i-1]!=NULL) {
            substitution(p,i);
            deleteNode(p->ptr[i],p->key[i]);
        }
        else {
            remove(p,i);
        }
    }
    else flag=deleteNode(p->ptr[i],k);
    if(flag){
        if(p->ptr[i]!=NULL) {
            if(p->ptr[i]->keynum<Min) {
                adjustBTree(p,i);
            }
        }
    }
    return flag;
}

int deleteBTree(BTree &t,int k) {//删除操作
    int flag;
    BTree p;
    flag=deleteNode(t,k);
    if(flag==0)return 0;//该关键字不在t中
    if(t->keynum==0){
        p=t;t=t->ptr[0];free(p);
		t->parent=NULL;
    }
    return 1;
}

void DestoryBTree(BTree &t){		//销毁B树
    if(t==NULL)return;
    int i;
    BTree p;
    queueBTree pl,pr,ap,q;
    pl=(queueBTree)malloc(sizeof(queueBNT));
    pr=(queueBTree)malloc(sizeof(queueBNT));
    pl->pt=t; pl->next=NULL; pr=pl;
    while(pl){
        p=pl->pt;
        for(i=0;i<=p->keynum;i++){
            if(p->ptr[i]){
                ap=(queueBTree)malloc(sizeof(queueBNT));
                ap->pt=p->ptr[i]; ap->next=NULL;

                pr->next=ap; pr=ap;
            }
        }
        q=pl;
        pl=pl->next;
        free(q->pt);
        free(q);
        q=NULL;
    }
    t=NULL;
}

void printBTree(BTree t){			 //用队列输出层序遍历的B树
    if(t==NULL){
        printf("\n");
        printf("BTree is empty.");
        printf("\n");
    }
    else {
        int i,j;
        BTree p;
        queueBTree root,pl,pr,ap,q,dp;
        pl=(queueBTree)malloc(sizeof(queueBNT));
        root=pl;
        pl->pt=t; pl->next=NULL; pr=pl;

        p=pl->pt;
        printf("[ ");
        for(i=1;i<=t->keynum;i++){
            printf("%d ",p->key[i]);
        }
        printf("]\n");
        dp=pl;
        int flag=1;
        while(pl){
            p=pl->pt;
            if(flag&&p->ptr[0]==NULL&&p!=t){
                while(dp!=NULL&&dp->pt!=p){
                    BTree tmp=dp->pt;
                    for(i=0;i<=tmp->keynum;i++){
                        printf("[ ");
                        for(j=1;j<=tmp->ptr[i]->keynum;j++){
                            printf("%d ",tmp->ptr[i]->key[j]);
                        }
                        printf("] ");
                    }
                    dp=dp->next;
                }
                printf("\n");
                flag=0;
            }
            else if(p==dp->pt->ptr[0]){
                while(dp->pt!=p){
                    BTree tmp=dp->pt;
                    for(i=0;i<=tmp->keynum;i++){
                        printf("[ ");
                        for(j=1;j<=tmp->ptr[i]->keynum;j++){
                            printf("%d ",tmp->ptr[i]->key[j]);
                        }
                        printf("] ");
                    }
                    dp=dp->next;
                }
                printf("\n");
            }
            for(i=0;i<=p->keynum;i++){
                if(p->ptr[i]){
                    ap=(queueBTree)malloc(sizeof(queueBNT));
                    ap->pt=p->ptr[i]; ap->next=NULL;

                    pr->next=ap; pr=ap;
                }
            }
            pl=pl->next;
        }
        while(root!=NULL){
            q=root;
            root=root->next;
            free(q);
        }
    }
}
4 测试
void Test1(){
    	system("color 4F");
    	BTree t=NULL;                                       //设定查找结果
    	int j,n=20;
    	int k;
    	int a[]={1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20};
    	printf("创建一棵%d阶B树:\n",m);
    	for(j=0;j<n;j++){                               //逐一插入元素
       insertBTree(t,a[j]);
       printf("   第%d步,插入元素%d:\n ",j+1,a[j]);
       printBTree(t);
    }

    	printf("\n");
    	printf("删除操作:\n");                          //删除操作
    	k=12;
    	deleteBTree(t,k);
    	printf("  删除%d:\n ",k);
    	printf("  删除后的B树: \n");
    	printBTree(t);
    	printf("\n");

    	k=5;
    	deleteBTree(t,k);
    	printf("  删除%d:\n ",k);
   		printf("  删除后的B树: \n");
    	printBTree(t);
    	printf("\n");

   		printf("  队列释放B树\n");
    	DestoryBTree(t);
    	printBTree(t);
}
	

void Test(){
    	 system("color 4F");
    	 BTree t=NULL;
    	 int n,key,flag;
    	 result r;
   		 while(1) {
        printf("\n");
        printBTree(t);
        printf("\n");
        printf("|********************************************|\n");
        printf("|* 1 B树置空     2 插入关键字  3 查询关键字 *|\n");
        printf("|* 4 删除关键字  5 遍历B树     6 销毁B树    *|\n");
        printf("|*               7 退出                     *|\n");
        printf("|********************************************|\n");

        printf("Enter number to choose operation:_____\b\b\b");
        scanf("%d",&n);
        switch(n){
            case 1:{
                init(t);
                printf("\n");
                printf("InitBTree successfully.\n");
                printf("\n");
                break;
            }
            case 2:{
                printf("Enter number to InsertBTree:_____\b\b\b");
                scanf("%d",&key);
                insertBTree(t,key);
                printf("\n");
                printf("Insert  %d   successfully.\n",key);
                printf("\n");
                break;
            }
            case 3:{
                printf("Enter number to searchBTree:_____\b\b\b");
                scanf("%d",&key);
                searchBTree(t,key,r);
                printf("\n");
                if(r.tag==1)printf("the keyelement  %d  succeed found.\n",key);
                else printf("failed to find the keyelement  %d   \n",key);
                printf("\n");
                break;
            }
            case 4:{
                printf("Enter number to DeleteBTree:_____\b\b\b");
                scanf("%d",&key);
                flag = deleteBTree(t,key);
                printf("\n");
                if(flag==0)printf("the keyelement   %d  isn`t existed.\n",key);
                else printf("Delete the keyelement  %d  successfully.\n",key);
                printf("\n");
                break;
            }
            case 5:{
                printf("\n");
                printBTree(t);
                printf("\n");
                break;
            }
            case 6:{
                DestoryBTree(t);
                printf("\n");
                printf("BTree is destoryed successfully");
                printf("\n");
                break;
            }
            case 7:{
                exit(-1);
                break;
            }
            default:{
                printf("\n");
                printf("invalid operation.\n");
                printf("\n");
            }
        }
    }
}

      

Text1()为初始化值

Text()为自己输值呈现过程

5 思考与小结

  1. 不管对于删除和插入关键字,操作时,变换位置是要将结点的孩子和双亲结点连接正确
  2. 对于遍历,网上的人是用递归暴力遍历,时间复杂度极高,但我经过思考,其实模拟队列就可以解决,只是写的时候注意技巧,同时要清掉用过的指针
  3. free()后要将指针置为NULL,避免野指针

6 收获和体会

    我先是看课本的操作解释,理解每一步后,在上网查下其他人的操作,从中学习,然后自己靠理解打出来,在打的过程中,能够很好的锻炼自己的代码编辑能力,同时自己也能由打的过程更深的理解每一步,最后自己通过理解自己写出模拟队列O(n)复杂度就能层次遍历(为什么要强调O(N)呢?因为我参考的那位是用暴力遍历搞得,这让我感到十分的抵触,哈哈哈,同时网上的代码有些是有bug的,所以最后我就自己重写全部代码啦(测试数据是搬网上,因为我要知道自己的数据与网上的一样吗),目前我还没发现自己的bug),在打的过程我由于把m阶B树的最小限制(m-1)/2写成m/2然后以为代码写错了,最后通过调试发现,这些过程都让我受益匪浅。(添加和删除,查找是书上的代码风格,而删除是网上一位大佬的风格,但我自己靠理解重写了,可能有bug望指点,嘻嘻)

完整代码:

 

#include <bits/stdc++.h>

using namespace std;

/**抽象类型函数
void init(t);                                       //初始化B树
void searchBTree(BTree t,int k,result &r);          //在B树中查找关键字k,r.tag==1为找到
                                                    //r.tag==0为找不到
void search(BTree p,int k);                         //在结点p中找关键字k的位置
void newBTreeroot(BTree &t,BTree p,int k,BTree q);  //新建根节点t
void insertBTree(BTree &t,int k);                   //在B中加入关键字k
void insert(BTree p,int k,BTree ap,int i);          //在p结点中插入关键字k
void spilt(BTree p,BTree ap,int s);                 //将结点以位置s为中心拆成两部分
Remove(BTree p,int k);                              //在结点p中删除关键字k
void findNode(BTree p,int k,int &i);                //在结点p中寻找k的位置
void deleteBTree(BTree t,int k);                    //在B树中删除关键字k
int deleteNode(BTree p,int k);                      //在B树删除操作的总接口
void substitution(BTree p,int i);                   //向右子树借最小值
void adjustBTree(BTree p,int i);                    //结点长度小于Min进行调整
void leftMove(BTree p,int i);                       //向右结点借值
void rightMove(BTree p,int i);                      //向左结点借值
void combine(BTree p,int i);                        //左右不够借,合并三个元素
void DestoryBTree(BTree &t);                        //销毁B树
void printBTree(BTree t);                           //用队列输出层序遍历的B树
**/

/**B树的抽象实现**/
const int m=4;              //B树的阶树
const int Max=m-1;          //最大的关键字个数
const int Min=(m-1)/2;      //最小的关键字个数

typedef struct rt{          //定义结点信息
    int key[m+1];           //结点关键字数组,key[0]不用
    int keynum;             //结点关键字个数
    struct rt* parent;      //双亲结点指针
    struct rt* ptr[m+1];    //孩子结点指针
}BNT,*BTree;

typedef struct op{          //查找结果
    int i;                  //结点的关键字位置或需插入位置
    int tag;                //成功与否标志
    BTree pt;               //找到的结点
}result;

typedef struct qp{          //模拟队列
    BTree pt;               //指向B树结点(数据域)
    struct qp* next;        //下一个队列指针(指针域)
}queueBNT,*queueBTree;

int search(BTree p,int k) { //在子树p中寻找结点k
    int i=1;
    while(i<=p->keynum&&p->key[i]<k)i++;
    return i;
}

void init(BTree &t){         //初始化B树
    t==NULL;
}

void searchBTree(BTree t,int k,result &r) { //在B树t中查找结点
    int finshed=0,i=0;
    BTree p=t,q=NULL;
    while(p!=NULL&&finshed==0) {
        i=search(p,k);
        if(i<=p->keynum&&p->key[i]==k)finshed=1;
        else {
            q=p;
            p=p->ptr[i-1];
        }
    }
    if(finshed==1) {                         //找到结点
        r.tag=1; r.i=i; r.pt=q;
    }
    else {                                   //找不到结点
        r.tag=0; r.i=i; r.pt=q;
    }
}

void newBTreeroot(BTree &t,BTree p,int k,BTree aq) {
    t=(BTree)malloc(sizeof(BNT));
    t->key[1]=k; t->keynum=1;
    t->ptr[0]=p; t->ptr[1]=aq;
    if(p!=NULL)p->parent=t;
    if(aq!=NULL)aq->parent=t;
    t->parent=NULL;
}

void insert(BTree p,int k,BTree &ap,int i) {
    int j;
    for(j=p->keynum;j>=i;j--) {
        p->key[j+1]=p->key[j];
        p->ptr[j+1]=p->ptr[j];
    }
    p->key[i]=k; p->ptr[i]=ap;
    if(ap!=NULL)ap->parent=p;
    p->keynum++;
}

void spilt(BTree p,BTree &ap,int s) {
    int i,j;
    ap=(BTree)malloc(sizeof(BNT));
    ap->ptr[0]=p->ptr[s];
    for(j=s+1,i=1;j<=p->keynum;i++,j++) {
        ap->key[i]=p->key[j];
        ap->ptr[i]=p->ptr[j];
    }
    ap->keynum=p->keynum-s;
    ap->parent=p->parent;
    for(i=0;i<=ap->keynum;i++) {
        if(ap->ptr[i]!=NULL)ap->ptr[i]->parent=ap;
    }
    p->keynum=s-1;
}

void insertBTree(BTree &t,int k) {//在B树中添加k关键字
    result r;
    searchBTree(t,k,r);
    if(r.tag==1)return ;//关键字已经存在
    BTree p=r.pt; int i=r.i;
    BTree ap; int x,s,finshed,needNewroot;
    x=k; ap=NULL; finshed=needNewroot=0;
    if(p==NULL) newBTreeroot(t,NULL,k,NULL);
    else {
        while(finshed==0&&needNewroot==0) {
            insert(p,x,ap,i);
            if(p->keynum<=Max)finshed=1;
            else {
                s=(m+1)>>1; spilt(p,ap,s);
                x=p->key[s];
                if(p->parent!=NULL) {
                    p=p->parent;
                    i=search(p,x);
                }
                else needNewroot=1;
            }
        }
        if(needNewroot==1) newBTreeroot(t,p,x,ap);
    }
}

void findNode(BTree p,int k,int &i) {
    i=p->keynum;
    while(i>0&&p->key[i]>k)i--;
}

void substitution(BTree p,int i) {
    BTree ap=p->ptr[i];
    while(ap->ptr[0]){
        ap=ap->ptr[0];
    }
    p->key[i]=ap->key[1];
}

void remove(BTree p,int i) {
    int j;
    p->keynum--;
    for(j=i;j<=p->keynum;j++) {
        p->key[j]=p->key[j+1];
        p->ptr[j]=p->ptr[j+1];
    }
}

void leftMove(BTree p,int i) {
    int j;
    BTree q=p->ptr[i-1],ap=p->ptr[i];
    q->keynum++;
    q->key[q->keynum]=p->key[i];
    q->ptr[q->keynum]=ap->ptr[0];
    if(ap->ptr[0]!=NULL)ap->ptr[0]->parent=p->ptr[i-1];

    p->key[i]=ap->key[1];
    ap->ptr[0]=ap->ptr[1];
    ap->keynum--;
    for(j=1;j<=ap->keynum;j++) {
        ap->key[j]=ap->key[j+1];
        ap->ptr[j]=ap->ptr[j+1];
    }
}

void rightMove(BTree p,int i) {
    int j;
    BTree q=p->ptr[i-1],ap=p->ptr[i];
    ap->keynum++;
    for(j=ap->keynum;j>1;j--){
        ap->key[j]=ap->key[j-1];
        ap->ptr[j]=ap->ptr[j-1];
    }
    ap->key[1]=p->key[i]; ap->ptr[1]=ap->ptr[0];
    ap->ptr[0]=q->ptr[q->keynum];
    if(q->ptr[q->keynum]!=NULL)q->ptr[q->keynum]->parent=p->ptr[i];

    p->key[i]=q->key[q->keynum];
    q->keynum--;
}

void combine(BTree p,int i) {
    int j,k;
    BTree q=p->ptr[i-1],ap=p->ptr[i];
    j=q->keynum;
    q->key[++j]=p->key[i];q->ptr[j]=ap->ptr[0];
    for(k=1;k<=ap->keynum;k++){
        q->key[++j]=ap->key[k];
        q->ptr[j]=ap->ptr[k];
    }
    for(k=q->keynum+1;k<=j;k++){
        if(q->ptr[k]!=NULL)q->ptr[k]->parent=p->ptr[i-1];
    }
    q->keynum=j;

    p->keynum--;
    for(j=i;j<=p->keynum;j++){
        p->key[j]=p->key[j+1];
        p->ptr[j]=p->ptr[j+1];
    }
    free(ap);
}

void adjustBTree(BTree p,int i) {
    if(i==0){
        if(p->ptr[1]->keynum>Min)leftMove(p,1);
        else combine(p,1);
    }
    else if(i==p->keynum) {
        if(p->ptr[i-1]->keynum>Min)rightMove(p,i);
        else combine(p,i);
    }
    else {
        if(p->ptr[i-1]->keynum>Min)rightMove(p,i);
        else if(p->ptr[i+1]->keynum>Min)leftMove(p,i+1);
        else combine(p,i);
    }
}

int deleteNode(BTree p,int k) {
    if(p==NULL)return 0;
    int i,flag=0;
    findNode(p,k,i);
    if(i>0&&p->key[i]==k) {
        flag=1;
        if(p->ptr[i-1]!=NULL) {
            substitution(p,i);
            deleteNode(p->ptr[i],p->key[i]);
        }
        else {
            remove(p,i);
        }
    }
    else flag=deleteNode(p->ptr[i],k);
    if(flag){
        if(p->ptr[i]!=NULL) {
            if(p->ptr[i]->keynum<Min) {
                adjustBTree(p,i);
            }
        }
    }
    return flag;
}

int deleteBTree(BTree &t,int k) {//删除操作
    int flag;
    BTree p;
    flag=deleteNode(t,k);
    if(flag==0)return 0;//该关键字不在t中
    if(t->keynum==0){
        p=t;t=t->ptr[0];free(p);
	t->parent=NULL;
    }
    return 1;
}

void DestoryBTree(BTree &t){
    if(t==NULL)return;
    int i;
    BTree p;
    queueBTree pl,pr,ap,q;
    pl=(queueBTree)malloc(sizeof(queueBNT));
    pr=(queueBTree)malloc(sizeof(queueBNT));
    pl->pt=t; pl->next=NULL; pr=pl;
    while(pl){
        p=pl->pt;
        for(i=0;i<=p->keynum;i++){
            if(p->ptr[i]){
                ap=(queueBTree)malloc(sizeof(queueBNT));
                ap->pt=p->ptr[i]; ap->next=NULL;

                pr->next=ap; pr=ap;
            }
        }
        q=pl;
        pl=pl->next;
        free(q->pt);
        free(q);
        q=NULL;
    }
    t=NULL;
}

void printBTree(BTree t){
    if(t==NULL){
        printf("\n");
        printf("BTree is empty.");
        printf("\n");
    }
    else {
        int i,j;
        BTree p;
        queueBTree root,pl,pr,ap,q,dp;
        pl=(queueBTree)malloc(sizeof(queueBNT));
        root=pl;
        pl->pt=t; pl->next=NULL; pr=pl;

        p=pl->pt;
        printf("[ ");
        for(i=1;i<=t->keynum;i++){
            printf("%d ",p->key[i]);
        }
        printf("]\n");
        dp=pl;
        int flag=1;
        while(pl){
            p=pl->pt;
            if(flag&&p->ptr[0]==NULL&&p!=t){
                while(dp!=NULL&&dp->pt!=p){
                    BTree tmp=dp->pt;
                    for(i=0;i<=tmp->keynum;i++){
                        printf("[ ");
                        for(j=1;j<=tmp->ptr[i]->keynum;j++){
                            printf("%d ",tmp->ptr[i]->key[j]);
                        }
                        printf("] ");
                    }
                    dp=dp->next;
                }
                printf("\n");
                flag=0;
            }
            else if(p==dp->pt->ptr[0]){
                while(dp->pt!=p){
                    BTree tmp=dp->pt;
                    for(i=0;i<=tmp->keynum;i++){
                        printf("[ ");
                        for(j=1;j<=tmp->ptr[i]->keynum;j++){
                            printf("%d ",tmp->ptr[i]->key[j]);
                        }
                        printf("] ");
                    }
                    dp=dp->next;
                }
                printf("\n");
            }
            for(i=0;i<=p->keynum;i++){
                if(p->ptr[i]){
                    ap=(queueBTree)malloc(sizeof(queueBNT));
                    ap->pt=p->ptr[i]; ap->next=NULL;

                    pr->next=ap; pr=ap;
                }
            }
            pl=pl->next;
        }
        while(root!=NULL){
            q=root;
            root=root->next;
            free(q);
        }
    }
}

void Test1(){
    system("color 4F");
    BTree t=NULL;                                       //设定查找结果
    int j,n=20;
    int k;
    int a[]={1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20};
    printf("创建一棵%d阶B树:\n",m);
    for(j=0;j<n;j++){                               //逐一插入元素
        insertBTree(t,a[j]);
        printf("   第%d步,插入元素%d:\n ",j+1,a[j]);
        printBTree(t);
    }

    printf("\n");
    printf("删除操作:\n");                          //删除操作
    k=12;
    deleteBTree(t,k);
    printf("  删除%d:\n ",k);
    printf("  删除后的B树: \n");
    printBTree(t);
    printf("\n");

    k=5;
    deleteBTree(t,k);
    printf("  删除%d:\n ",k);
    printf("  删除后的B树: \n");
    printBTree(t);
    printf("\n");

    printf("  队列释放B树\n");
    DestoryBTree(t);
    printBTree(t);
}

void Test(){
    system("color 4F");
    BTree t=NULL;
    int n,key,flag;
    result r;
    while(1) {
        printf("\n");
        printBTree(t);
        printf("\n");
        printf("|********************************************|\n");
        printf("|* 1 B树置空     2 插入关键字  3 查询关键字 *|\n");
        printf("|* 4 删除关键字  5 遍历B树     6 销毁B树    *|\n");
        printf("|*               7 退出                     *|\n");
        printf("|********************************************|\n");

        printf("Enter number to choose operation:_____\b\b\b");
        scanf("%d",&n);
        switch(n){
            case 1:{
                init(t);
                printf("\n");
                printf("InitBTree successfully.\n");
                printf("\n");
                break;
            }
            case 2:{
                printf("Enter number to InsertBTree:_____\b\b\b");
                scanf("%d",&key);
                insertBTree(t,key);
                printf("\n");
                printf("Insert  %d   successfully.\n",key);
                printf("\n");
                break;
            }
            case 3:{
                printf("Enter number to searchBTree:_____\b\b\b");
                scanf("%d",&key);
                searchBTree(t,key,r);
                printf("\n");
                if(r.tag==1)printf("the keyelement  %d  succeed found.\n",key);
                else printf("failed to find the keyelement  %d   \n",key);
                printf("\n");
                break;
            }
            case 4:{
                printf("Enter number to DeleteBTree:_____\b\b\b");
                scanf("%d",&key);
                flag = deleteBTree(t,key);
                printf("\n");
                if(flag==0)printf("the keyelement   %d  isn`t existed.\n",key);
                else printf("Delete the keyelement  %d  successfully.\n",key);
                printf("\n");
                break;
            }
            case 5:{
                printf("\n");
                printBTree(t);
                printf("\n");
                break;
            }
            case 6:{
                DestoryBTree(t);
                printf("\n");
                printf("BTree is destoryed successfully");
                printf("\n");
                break;
            }
            case 7:{
                exit(-1);
                break;
            }
            default:{
                printf("\n");
                printf("invalid operation.\n");
                printf("\n");
            }
        }
    }
}

int main(){
    Test1();
    //Test();
    return 0;
}


后续有时间再补下B+树

 

  • 4
    点赞
  • 28
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值