学习随记四十三——B树(递归实现四——我的错误整体代码)

我的错误B树递归实现


第一篇总的介绍.
第二篇插入的介绍.
第三篇删除的介绍.
花了很久的时间,最后还是没有达到我希望的功能,有点遗憾,但是在这个过程中我也学会了一些东西,首先要明白程序设计需求,再考虑设计模式,明确函数功能划分、接口设计,画出我实现的流程图,将我的实现算法能清晰表达出来再动手写伪代码,再手写具体代码自己纸上运行演算,最后再上机调试。由于我时间不是很多了,所以还有一些问题我就没有解决,留待非递归实现解决。之前各个部分的思路,具体实现都在我的同系列文章中了,就不在这里赘述。

具体代码:

#include<iostream>
typedef int KeyType;
const int T=3;
typedef struct Btreenode{
	KeyType key[2*T-1]={0};								//关键字数组 
	bool leaf=true;												//默认叶子结点为真
	int n=0;															//结点个数 
	struct Btreenode* son[2*T]={nullptr};	//子结点数组 
	struct Btreenode* father=nullptr;			//父指针 
}Btreenode;
typedef Btreenode* B_tree;
using namespace std;
B_tree Insert(B_tree,KeyType);						//插入函数 
B_tree Delete_Key(B_tree,KeyType);				//删除关键字 
B_tree Search(B_tree,KeyType);						//搜索关键字返回结点地址 
int KeyReplace(B_tree,KeyType);			    	//在子结点中找一个关键字代替待删除的关键字 
int Find_position(B_tree,KeyType);				//查找关键字所在位置 
B_tree Split(B_tree);											//分裂结点函数,返回新生成的结点地址 
void Sortkey(B_tree,KeyType);							//将一个新关键字插入结点并排序
void Sortson(B_tree,B_tree);							//将一个新儿子插入父结点的儿子数组并排序				 
void Cat(B_tree,B_tree);									//将一个结点的某个位置开始剪切给另外一个结点
void Cat(B_tree,B_tree,KeyType);					//合并结点时用的剪切函数 
void AdjustNode(B_tree,int);							//将某个位置后面的数据前进一个位置 
int  MergeNode(B_tree,int);								//将后一个结点剪切至第一个结点 
int  TransferKey(B_tree,int);							/*将一个相邻的兄弟结点的关键字转移到父结点,
                                        	再将父结点的一个关键字转移到该结点*/ 
int main(void){
	B_tree temp=nullptr,root=new Btreenode;
	KeyType x;
	int i=0;
	while(cin>>x){
		Insert(root,x);
		if(root->father) root=root->father;
	}
	cin.clear();
	cin.ignore();
	cout<<endl;
	cout<<"Please input the key you want to delete."<<endl;
	cin>>x;
	Delete_Key(root,x);
	cout<<"Please input the key you want to search."<<endl;
	cin>>x;
	temp=Search(root,x);
	for(;i<temp->n;i++) if(temp)cout<<temp->key[i]<<endl;
	return 0;
}
B_tree Insert(B_tree root,KeyType newkey){
	int flag=0; 
	B_tree newson=nullptr;																			//分裂结点后会产生新儿子 
	int position=Find_position(root,newkey);
	if(root->n==2*T-1){																					//满结点 
		KeyType temp=root->key[T-1];
		newson=Split(root);		  																	//newson是继承了满结点的后半部分的新儿子结点 
		if(newkey<temp) flag=1;
		else flag=2;
	}else{
		if(root->leaf==false) flag=3;															//内部结点 
		else Sortkey(root,newkey);																//叶子结点 
	}
	if(flag==1) return Insert(root,newkey);											//在分裂后的当前结点中插入 
	else if(flag==2) return Insert(newson,newkey);						  //在分裂后产生的新儿子中进行插入 
	else if(flag==3) return Insert(root->son[position],newkey); //当前结点为内部结点,递归查找合适的叶结点进行插入 
	else return root;																						//已经将关键字插入到叶结点中了 
}
B_tree Search(B_tree root,KeyType x){
	int position=Find_position(root,x);
	if(root->key[position]==x) return root;
	else{
		if(root->son[position])return Search(root->son[position],x);
		else return nullptr;
	}
}
B_tree Split(B_tree p){
	B_tree newson=new Btreenode;
	KeyType new_father_key=p->key[T-1];
	Cat(p,newson);
	if(p->father){										//p有父结点
		Sortkey(p->father,new_father_key);
		Sortson(p->father,newson); 
	}else{														//没有父结点,说明待分裂结点为根结点 
		B_tree newfather=new Btreenode;
		p->father=newfather;
		newson->father=newfather;
		newfather->son[0]=p;
		newfather->key[0]=new_father_key;
		newfather->n++;
		newfather->son[1]=newson;				//因为newson继承了原来结点的右半边比原来结点大 
		newfather->leaf=false;
	}
	return newson;
}
void Sortkey(B_tree p,KeyType newkey){
	KeyType temp[2*T-1]={0};
	int i=0,j=0,flag=1;										//flag=1代表新关键字未插入
	for(;i<p->n;i++,j++){
		if(flag&&p->key[i]>newkey){
			temp[j]=newkey;
			temp[++j]=p->key[i];
			flag=0;
		}else if(p->key[i]==newkey){
			cout<<"The key you have input."<<endl;
			return;
		}else temp[j]=p->key[i];
	} 
	if(flag) temp[j]=newkey;
	for(i=0;i<=j;i++) p->key[i]=temp[i];
	p->n++;
}
void	Sortson(B_tree father,B_tree newson){
	B_tree temp[2*T]={nullptr};
	int i=0,j=0,flag=1;										//flag=1代表新儿子未插入父结点的儿子数组
	for(;i<father->n;i++,j++){
		if(flag&&father->son[i]->key[0]>newson->key[0]){
			temp[j]=newson;
			temp[++j]=father->son[i];
			flag=0; 
		}else temp[j]=father->son[i];
	} 
	if(flag) temp[j]=newson;
	for(i=0;i<2*T&&temp[i];i++) father->son[i]=temp[i];
}
void Cat(B_tree first,B_tree second){						//begin是第一个结点传关键字给第二个结点的起始位置 
	int i=T,j=0;
	first->key[T-1]=0;								//在分裂结点时因为这个关键字已经被传给了父结点
	for(;i<2*T-1;i++,j++){
		second->key[j]=first->key[i];
		first->key[i]=0;
		second->son[j]=first->son[i];
		first->son[i]=nullptr;
	} 
	second->son[j]=first->son[i];			//因为儿子结点比关键字多一 
	first->son[i]=nullptr;
	second->n=first->n=T-1;
	second->leaf=first->leaf;
	second->father=first->father;
}
void Cat(B_tree first,B_tree second,KeyType x){
	int i=first->n,j=0;
	first->key[i++]=x;
	for(;i<2*T-1;i++,j++){
		first->key[i]=second->key[j];
		first->son[i]=second->son[j];
		first->n++;
	}
	first->son[i]=second->son[j];				//儿子比关键字多一
	delete(second); 
}
void AdjustNode(B_tree p,int position){
	for(;position<p->n-1;position++){
		p->key[position]=p->key[position+1];
		p->son[position+1]=p->son[position+2];
	}
	p->key[position]=0;
	p->son[position+1]=nullptr;
	p->n--;
}
int MergeNode(B_tree father,int position){
	B_tree left_brother=nullptr,right_brother=nullptr;
	int flag=0;
	if(position>0) left_brother=father->son[position-1];
	if(position<father->n) right_brother=father->son[position+1]; 
	if(left_brother){								//有左兄弟与左兄弟合并
		Cat(left_brother,father->son[position],father->key[position]);
		AdjustNode(father,position);
		flag=3;
	}else if(right_brother){
		Cat(right_brother,father->son[position],father->key[position]);
		AdjustNode(father,position);
		flag=4;
	}
	return flag;
}
int TransferKey(B_tree father,int position){
	B_tree left_brother=nullptr,right_brother=nullptr;
	int flag=0;
	if(position>0) left_brother=father->son[position-1];
	if(position<father->n) right_brother=father->son[position+1];
	if(left_brother&&left_brother->n>T-1){				//左兄弟有至少T个关键字 
		Sortkey(father->son[position],father->key[position-1]);
		Sortson(father->son[position],left_brother->son[left_brother->n]);
		father->key[position-1]=left_brother->key[left_brother->n-1];
		left_brother->key[left_brother->n-1]=0;
		left_brother->son[left_brother->n]=nullptr;
		flag=6;
	}else if(right_brother&&right_brother->n>T-1){//右兄弟有至少T个关键字 
		Sortkey(father->son[position],father->key[position+1]);
		Sortson(father->son[position],right_brother->son[0]);
		father->key[position+1]=right_brother->key[0];
		AdjustNode(right_brother,0);
		flag=7;
	}
	return flag;
}
int KeyReplace(B_tree p,int position){
	B_tree last_son=p->son[position],next_son=p->son[position+1];
	int flag=0;					//如果结束时返回的flag=0则说明未替换 
	if(last_son&&last_son->n>T-1){	//如果前一个儿子至少有T个关键字
		p->key[position]=last_son->key[last_son->n-1];
		flag=1;						//说明用其前一个儿子的关键字进行替换 
	}else if(next_son&&next_son->n>T-1){
		p->key[position]=next_son->key[0];
		flag=2;						//说明用其后一个儿子进行替换 
	}
	return flag;
}
int Find_position(B_tree p,KeyType x){
	int i=0,position=0,flag=1;					//flag=1说明还未定位到关键字位置
	for(;i<p->n;i++){
		if(flag&&(x<p->key[i]||x==p->key[i])){
			position=i;
			flag=0;													//说明已经定位到其位置 
		} 
	} 
	if(flag) position=i;								//说明其比这个结点中的关键字大 
	return position;
}
B_tree Delete_Key(B_tree root,KeyType x){ 
	int position=Find_position(root,x),flag=0;			//flag是标志变量用来 
	B_tree left_brother=nullptr,right_brother=nullptr;
	if(position>0) left_brother=root->son[position-1];
	if(position<root->n) right_brother=root->son[position+1];
	if(root->key[position]==x){											//待删除关键字在当前结点中
		if(root->leaf) AdjustNode(root,position);			//当前结点为叶结点 
		else{																					//当前结点为内部结点
			flag=KeyReplace(root,position);							//若待删除关键字的相邻结点有至少T个关键字就进行关键字替换 
			if(flag==0) flag=MergeNode(root,position);	//合并结点 
			}
	}else{																					//待删除关键字不在当前结点 
		if(root->son[position]->n>T-1) flag=5;				//待降落的结点有至少T个关键字
		else{																					//待降落的结点只有T-1个关键字 
			flag=TransferKey(root,position);						//待降落结点的兄弟结点有至少T个关键字就进行关键字转移 
			if(flag==0){																//说明其兄弟结点都只有T-1个关键字,进行关键字合并 
				flag=MergeNode(root,position);
			}
		}
	}
	if(root->n==0){														//当前结点为根结点合并后无关键字,则合并结点成为新根结点 
		B_tree temp=root;
		root=root->son[0];
		delete(temp);
	}
	if(flag==0) return root;
/*①*/else if(flag==1) return Delete_Key(root->son[position],root->son[position]->key[root->son[position]->n-1]);
/*②*/else if(flag==2) return Delete_Key(root->son[position+1],root->son[position+1]->key[0]);
/*③*/else if(flag==3) return Delete_Key(root->son[position-1],x);
/*④*/else if(flag==4) return Delete_Key(root->son[position+1],x);
/*⑤*/else return Delete_Key(root->son[position],x);
}

  • 2
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值