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 思考与小结
- 不管对于删除和插入关键字,操作时,变换位置是要将结点的孩子和双亲结点连接正确
- 对于遍历,网上的人是用递归暴力遍历,时间复杂度极高,但我经过思考,其实模拟队列就可以解决,只是写的时候注意技巧,同时要清掉用过的指针
- 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+树