//B树的相关运算算法#include<stdio.h>
#include<malloc.h>#define MAXM  10//定义B树最大的阶数
typedef int KeyType;//关键码类型typedef struct node//B树结点类型定义
{KeyType keynum;//关键字的个数KeyType key[MAXM];//存放关键字struct node *parent;//双亲结点指针struct node *ptr[MAXM];//孩子结点指针数组
}BTNode;typedef struct //B树查找结果类型
{BTNode *pt;//指向找到的结点int i;//结点中关键字序号int tag;//1:查找成功;0:查找失败
}Result;int m;//m阶B树,全局变量
int Max;//m阶B树中,每个结点的最多关键字个数Max=m-1;
int Min;//m阶B树中,非叶子结点的最少关键字个数Min=(m-1)/2;int Search(BTNode *p,KeyType k)
{//zai p->key[1...keynum]中查找i,使得p->key[i]<=k<p->key[i+1]for(int i=0;i<p->keynum && p->key[i+1]<=k;i++);return i;
}Result SearchBTree(BTNode *t,KeyType k)
{// 在m阶t树上查找关键字k,返回结果(pt,i,tag)。//若成功,则特征值tag=1,指针pt所指结点中第i个关键字等于k//否则特征值tag=0,等于k的关键字应插入在指针pt所指结点中第i和第i+1个关键字之间BTNode *p=t,*q=NULL;//初始化,p指向待查结点,q指向p的双亲int found=0,i=0;Result r;while(p!=NULL && found==0){i=Search(p,k);// 在p->key[1...keynum]中查找i,使得p->key[i]<=k<p->key[i+1]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//查找不成功,返回K的插入位置信息{r.pt=q;r.tag=0;}return r;
}void Insert(BTNode *&q,int i,KeyType x,BTNode *ap)
{//将x和ap分别插入到q->key[i+1] 和q->ptr[i+1]中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)
{//将结点q分裂成两个结点,前一半保留,后一半移入新生结点apint i,s=(m+1)/2;ap=(BTNode *)malloc(sizeof(BTNode));//生成新结点ap->ptr[0]=q->ptr[s];//后一半移入apfor(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;//q的前一半保留,修改keynum
}void NewRoot(BTNode *&t,BTNode *p,KeyType x,BTNode *ap)
{//生成含信息(t,x,ap)的新的根结点 *t和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)
{//在m阶t树t上结点*q的 key[i]和key[i+1]之间插入关键字k。//若引起结点过大,则沿双亲链进行必要的结点分裂调整,使得t仍为m阶t树BTNode *ap;int finished,needNewRoot,s;KeyType x;if(q==NULL)//t为空树(参数q初值为NULL)NewRoot(t,NULL,k,NULL);//生成仅含关键字k的根结点 telse{x=k;ap=NULL;finished=needNewRoot=0;while(needNewRoot==0 &&finished==0){Insert(q,i,x,ap);//将x和ap分别插入到q->key[i+1]和q->ptr[i+1]if(q->keynum<=Max)finished=1;//插入完成else{s=(m+1)/2;Split(q,ap);x=q->key[s];if(q->parent)//在双亲结点*q中查找x的插入位置{q=q->parent;i=Search(q,x);}else needNewRoot=1;}}if(needNewRoot==1)//根结点已经分裂为结点*q和*apNewRoot(t,q,x,ap);//生成新根结点*t,q和ap为子树指针}
}void DispBTree(BTNode *t)//以括号表示法输出B树
{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)
{//从*p结点删除key[i]和它的孩子指针ptr[i]int j;for(j=i+1;j<=p->keynum;j++)//前移删除key[i]和ptr[i]{p->key[j-1]=p->key[j];p->ptr[j-1]=p->ptr[j];}p->keynum--;
}void Successor(BTNode *p,int i)
{//查找被删关键字P->key[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指向左节点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)
{//关键字删除后,调整B树,找到一个关键字将其插入到p->ptr[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)
{//在结点p中找关键字为k 的位置i,成功时返回1,否则返回0if(k<p->key[1])//k小于*p结点的最小关键字时返回0{i=0;return 0;}else//在*p结点中查找{i=p->keynum;while(k<p->key[i] && i>1)i--;return(k==p->key[i]);}
}int RecDelete(KeyType k,BTNode *p)
{//查找并删除关键字kint 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]);//p->key[i]在叶子结点中}elseRemove(p,i);//从*p结点中位置i处删除关键字}elsefound=RecDelete(k,p->ptr[i]);//沿着孩子结点递归查找并删除关键字kif(p->ptr[i]!=NULL)if(p->ptr[i]->keynum<Min)//删除后关键字个数小于MinRestore(p,i);return found;}
}void DeleteBTree(KeyType k,BTNode *&root)
{//从B树root中删除关键字k,若在一个结点中删除指定的关键字,不再有其他关键字,则删除该结点BTNode *p; //用于释放一个空的rootif(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;//3阶B树Max=m-1;Min=(m-1)/2;printf("\n");printf("创建一棵%d阶B-树:\n",m);for(j=0;j<n;j++)//创建一个3阶B树{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("删除操作:\n");k=8;DeleteBTree(k,t);printf("删除%d:",k);DispBTree(t);printf("\n");k=1;DeleteBTree(k,t);printf("删除%d:",k);DispBTree(t);printf("\n\n");return 0;
}

数据结构源码笔记(C语言描述)汇总:

数据结构源码笔记(C语言):英文单词按字典序排序的基数排序

数据结构源码笔记(C语言):直接插入排序

数据结构源码笔记(C语言):直接选择排序

数据结构源码笔记(C语言):置换-选择算法

数据结构源码笔记(C语言):Huffman树字符编码

数据结构源码笔记(C语言):Josephus问题之顺序表

数据结构源码笔记(C语言):Josephus问题之循环链接表

数据结构源码笔记(C语言):多项式合并

数据结构源码笔记(C语言):二叉树之叶子结点旋转销毁

数据结构源码笔记(C语言):哈夫曼树

数据结构源码笔记(C语言):集合的位向量表示

数据结构源码笔记(C语言):链接队列

数据结构源码笔记(C语言):链接栈

数据结构源码笔记(C语言):线性表的单链表示

数据结构源码笔记(C语言):线性表的顺序表示

数据结构源码笔记(C语言):栈的基本操作

数据结构源码笔记(C语言):中缀表达式

数据结构源码笔记(C语言):希尔插入排序

数据结构源码笔记(C语言):索引文件建立和查找

数据结构源码笔记(C语言):冒泡排序

数据结构源码笔记(C语言):快速排序

数据结构源码笔记(C语言):可变长度字符串的快速排序

数据结构源码笔记(C语言):基数排序

数据结构源码笔记(C语言):二路归并排序

数据结构源码笔记(C语言):堆排序

数据结构源码笔记(C语言):二叉树搜索树Kruskal

数据结构源码笔记(C语言):二叉搜索树Prim

数据结构源码笔记(C语言):最短路径弗洛伊德算法

数据结构源码笔记(C语言):深度、广度优先生成树

数据结构源码笔记(C语言):邻接矩阵转化邻接表

数据结构源码笔记(C语言):统计字符串中出现的字符及其次数

数据结构源码笔记(C语言):顺序查找

数据结构源码笔记(C语言):哈希表的相关运算算法

数据结构源码笔记(C语言):分块法查找

数据结构源码笔记(C语言):二分查找

数据结构源码笔记(C语言):二叉树遍历

数据结构源码笔记(C语言):二叉平衡树的相关操作算法

数据结构源码笔记(C语言):二叉排序树的基本操作算法

数据结构源码笔记(C语言):B树的相关运算算法

数据结构源码笔记(C语言):B树的相关运算算法相关推荐

  1. 数据结构源码笔记(C语言):Huffman树字符编码

    #include <stdio.h> #include<string.h> #define N 10 /*待编码字符的个数,即树中叶结点的最大个数*/ #define M 2* ...

  2. 数据结构源码笔记(C语言):哈夫曼树

    #include <stdio.h> #include <stdlib.h> #define MAXINT 2147483647 #define MAXNUM 50 #defi ...

  3. 数据结构源码笔记(C语言描述)汇总

    数据结构源码笔记(C语言):英文单词按字典序排序的基数排序 数据结构源码笔记(C语言):直接插入排序 数据结构源码笔记(C语言):直接选择排序 数据结构源码笔记(C语言):置换-选择算法 数据结构源码 ...

  4. 数据结构源码笔记(C语言):英文单词按字典序排序的基数排序

    //实现英文单词按字典序排序的基数排序算法#include<stdio.h> #include<malloc.h> #include<string.h>#defin ...

  5. 数据结构源码笔记(C语言):索引文件建立和查找

    //实现索引文件建立和查找算法#include<stdio.h> #include<malloc.h> #include<string.h> #include< ...

  6. 数据结构源码笔记(C语言):快速排序

    //实现快速排序算法 #include<stdio.h> #include<malloc.h> #define MAXE 20typedef int KeyType; type ...

  7. 数据结构源码笔记(C语言):冒泡排序

    //冒泡排序算法实现 #include<stdio.h> #include<malloc.h> #define MAXE 20typedef int KeyType; type ...

  8. 数据结构源码笔记(C语言):希尔插入排序

    //实现希尔插入排序算法 #include<stdio.h> #include<malloc.h> #define MAXE 20typedef int KeyType; ty ...

  9. 数据结构源码笔记(C语言):直接插入排序

    //实现直接插入排序算法#include<stdio.h> #include<malloc.h> #define MAXE 20typedef int KeyType; typ ...

最新文章

  1. Comparative assessment of long-read error correction software applied to Nanopore RNA-sequencing dat
  2. 【剑指offer-Java版】32从1到n的整数中1出现的次数
  3. 实验3 linux内存映射,3Linux内存映射,mmap()函数
  4. 为js和css文件自动添加版本号
  5. python项目实践_Python 项目实践三(Web应用程序)第二篇
  6. Bootstrap组件_巨幕,页头,缩略图
  7. 怎么损坏mysql_如何修复MySQL中损坏的表
  8. 判断用户名和密码是否正确java_facebook中如何判断用户名和密码是否正确
  9. JS兼容性问题:window.locatin.href is not a function
  10. scala中class,object,trait的区别
  11. 在oracle里面查询视图,oracle查询所有视图
  12. “打印机安装失败,请检查打印服务”问题解决方案
  13. python 下载 M3U8 视频
  14. 濡沫江湖一直显示获取服务器地址,濡沫江湖霜儿剧情任务怎么完成?霜儿专属剧情任务接取以及完成攻略...
  15. C++中switch用法的意义
  16. imap java 接收_javamail实现邮件接收功能IMap和pop3方式
  17. ev6 ev8 ev4a加密视频破解翻录教程
  18. background-clip和background-origin
  19. 2004年秋浙江省计算机等级考试二级C 编程题(2)
  20. java jdbc 批量更新_java – JDBC PreparedStatement,批量更新和生成的密钥

热门文章

  1. S.O.L.I.D.类设计原则
  2. linux 之 rpm 网站
  3. 10-Flink集群的高可用(搭建篇补充)
  4. 六、配置Oracle数据库的网络环境
  5. Object.defineProperty方法
  6. Python pygame
  7. redis在mac上的安装
  8. 初识linux以及bash的部分使用及技巧
  9. 深入浅出 Java Concurrency (33): 线程池 part 6 线程池的实现及原理 (1)[转]
  10. 编写简单的发布者和订阅者(C++)---ROS学习第9篇