一、B_树的基本结构
//定义的B_树的存储结构的节点的结构
typedef struct BTNode{
KeyType keyNum;//用来记录当前的key 的值keyNum
struct BTNode *parent;//定义指向双亲节点的指针
KeyType key[Max+1];//表示key值属于[1...keyNum],这里Key[0]不用
struct BTNode *ptr[Max+1];//表示其有[0...keyNum]个孩子节点指针
}BiTreeNode;
二、B_树的增删改查
源码:
/**
*B-树
*@author 菜鸟
*@version 2014.7.9
*/
#include <iostream>
#include <stdlib.h>
#include <malloc.h>
#include <windows.h>
#define Max 3 //max = m-1 m 为该树结构的阶
#define Min 0 //min = m/2-1
using namespace std;
typedef int KeyType;
int count1 = 0;
int tag1 = 0;
//定义的B_树的存储结构的节点的结构
typedef struct BTNode{
KeyType keyNum;//用来记录当前的key 的值keyNum <= max
struct BTNode *parent;//定义指向双亲节点的指针
KeyType key[Max+1];//表示key值属于[1...keyNum],这里Key[0]不用
struct BTNode *ptr[Max+1];//表示其有[0...keyNum]个孩子节点指针
}BiTreeNode;
//定义查找的指针变量的结构体
typedef struct{
BiTreeNode *pt;//指向B_树节点的指针
int pos;//表示1...m中的下标
int tag;//标志说明有没有找到,若tag= 1说明找到了,否则tag = 0则说明没有找到,继续查找
}SerNode;//查找类型
void BiTreeInsert(BiTreeNode*,SerNode *,KeyType);
void BiTreeOutPut(BiTreeNode*,int);
void operation(BiTreeNode*,SerNode *);
BiTreeNode* BiTreeNewNode();
/**
*查找结构体的初始化o
*@param SerNode *p 表示查找指针的地址
*@return 无
*/
void SerNodeInitiate(SerNode *p){
p->pt = NULL;
p->pos = 1;
p->tag = 0;
cout<<"查找结点初始化成功!"<<endl;
}
/**
*B_树的初始化
*@param BiTreeNode *B 表示根节点的地址
*@return 无
*/
void BiTreeInitiate(BiTreeNode *B){
B->keyNum = 0;
B->parent = NULL;
for(int i = 0; i< Max+1;i++){
B->key[i] = 0;
B->ptr[i] = NULL;
}
cout<<"节点初始化成功!"<<endl;
}
/**
*更新根节点
*/
BiTreeNode* UpDateRoot(BiTreeNode *root,SerNode *s){
cout<<"更新节点完毕!"<<endl;
operation(root,s);
return root;
}
/**
*创建根节点
*/
BiTreeNode* CreateRoot(SerNode *s){
BiTreeNode*p = NULL;
p = BiTreeNewNode();
tag1 = 1;
if(p != NULL ){
cout<<"根节点申请成功!"<<endl;
}
BiTreeInitiate(p);
operation(p,s);
return p;
}
/**
*B-树的遍历
*/
void TraverseB_Tree(BiTreeNode *B){
if(B == NULL){
cout<<"不存在这样的树!"<<endl;
return ;
}
if(B->keyNum == 0){
cout<<"空树!"<<endl;
return;
}
for(int i = 0 ;i <B->keyNum ;i++){
if(B->ptr[i] != NULL&&i%2!=1){//如果有子节点
TraverseB_Tree(B->ptr[i]);
}
BiTreeOutPut(B,i+1);//输出
if(B->ptr[i+1] != NULL){//如果还有子节点继续遍历
TraverseB_Tree(B->ptr[i+1]);
}
}
}
/**
*对一个节点的扫描
*@param SerNode *s 表示传入该结构的空间地址
*@param BiTreeNode *destination表示要扫描的目标
*@param KeyType num表示目标数据
*@return 无
*/
void GetSerNodeInformation(BiTreeNode *destination,SerNode *s,KeyType num){//获取扫描的节点的pos,pt,tag等信息
SerNodeInitiate(s);
s->pt = destination;
BiTreeNode *p = s->pt;
while(s->pos <= p->keyNum){
if(num == p->key[s->pos]){
s->tag = 1;
cout<<"已经查找到了!当前位于该节点的位置s->pos="<<s->pos<<endl;
return;
}else if(num > p->key[s->pos]&&num < p->key[s->pos+1]){
return ;
}else{
s->pos++;
}
if(num > p->key[s->pos]&&num < p->key[s->pos+1]){
return ;
}
if(s->pos > p->keyNum){
cout<<"该节点中没有找到该节点!"<<endl;
//初始化节点,以便于后面的操作
//SerNodeInitiate(s);
return;
}
}
}
/**
*B_树的查找
*@param BiTNode *B 表示根节点地址
*@param KeyType num表示要插入的新元素
*@return 无
*/
BiTreeNode* BiTreeSerch(BiTreeNode *B,SerNode *s,KeyType num){
SerNode *p = NULL;
BiTreeNode *p1 = NULL;
BiTreeNode *p2 = NULL;
SerNodeInitiate(s);
p = s;
p->pt = B;
p1 = B;//指向要查询的节点的位置
//此时获取到了节点的地址
if(B==NULL){
cout<<"空树无法进行查找!"<<endl;
return NULL;
}
while(p->pos<=p1->keyNum){
if(num == p1->key[p->pos]){
p->tag = 1;
cout<<"已经查找到了!-----"<<p1<<" "<<p1->key[p->pos]<<endl;
p2 = p1;
return p2;
}else if(num > p1->key[p->pos]){
if(p->pos < p1->keyNum){
p->pos++;
// continue;
}else if(p1->ptr[p->pos] != NULL){
p->pt = p1->ptr[p->pos];
p1 = p->pt;
}else if(p1->ptr[p->pos] == NULL){
p->tag = 0;
cout<<"没有找到!"<<endl;
return NULL;
}
}else if(num < p1->key[p->pos]){
if(p1->ptr[p->pos-1] != NULL){
p->pt = p1->ptr[p->pos-1];
p1= p->pt;
// BiTreeSerch(p->pt,s,num);
}else if(p1->ptr[p->pos-1] == NULL){
p->tag = 0;
cout<<"没有找到!"<<endl;
return NULL;
}
}
}
}
/**
*B_树新建节点
*@param BiTreeNode *B表示父节点地址
*@param KeyType num表示要插入的元素
*@return BiTreeNode*
*/
BiTreeNode* BiTreeNewNode(){
count1++;
BiTreeNode *NewNode = NULL ;
NewNode = (BiTreeNode*)malloc(sizeof(BiTreeNode));
if(NewNode != NULL){
cout<<"节点空间申请成功!"<<endl;
}else{
cout<<"节点空间申请失败!"<<endl;
}
BiTreeInitiate(NewNode);//对节点初始化
return NewNode;
}
/**
*B_树的分裂
*@param BiTreeNode *s 表示当前需要分裂的节点
*@param BiTreeNode *p 表示当前需分裂的节点的父节点
*@return 无
*/
BiTreeNode* BiTreeSplit(BiTreeNode *B,BiTreeNode *s,SerNode *ser,BiTreeNode *p){//这里需要返回根节点
BiTreeNode *acceptNode[3] = {NULL};//用来接收新建的节点的地址
SerNodeInitiate(ser);
acceptNode[1] = BiTreeNewNode();//分裂时至少要新建两个新的节点然后释放旧的节点
acceptNode[2] = BiTreeNewNode();
BiTreeInitiate(acceptNode[1]);
BiTreeInitiate(acceptNode[2]);
//判断其是否是叶子节点
for(;ser->pos <=s->keyNum;){
cout<<"s->ptr[ser->pos]"<<s->ptr[ser->pos-1]<<endl;
cout<<"---------------------------------------------"<<endl;
if(s->ptr[ser->pos-1]==NULL){
ser->pos++;
}else{
break;
}
}cout<<"ser->pos="<<ser->pos<<endl;
if(ser->pos >= Max&&p!=NULL ){
cout<<"此时为叶子节点,进行叶子节点的分裂!"<<endl;
SerNodeInitiate(ser);
GetSerNodeInformation(p,ser,s->key[(Max)/2+1]);
p->key[ser->pos] = s->key[(Max)/2+1]; //对新创建的根节点进行插入
p->keyNum++;
p->ptr[ser->pos-1] = acceptNode[1];
p->ptr[ser->pos] = acceptNode[2];
//此时我们需要向这两个空的节点中赋值
SerNodeInitiate(ser);
while(ser->pos < Max/2+1){
acceptNode[1]->key[ser->pos] = s->key[ser->pos];
acceptNode[1]->keyNum++;
ser->pos++;
}
acceptNode[1]->parent = p;
int i = 1;
while(i < Max-Max/2){
acceptNode[2]->key[i] = s->key[ser->pos+1];
acceptNode[2]->keyNum++;
i++;
ser->pos++;
}
acceptNode[2]->parent = p;
count1--;
free(s);
cout<<"分裂完成!"<<endl;
return B;//此时返回根节点
//此时获取到了这个元素在父节点中的位置
/* if(p->keyNum >= Max){
s = p;
p= p->parent;
BiTreeSplit(B,s,ser,p);
}else{
BiTreeInsert(p,ser,s->key[Max/2]);//对新创建的根节点进行插入
p->ptr[ser->pos] = acceptNode[1];
p->ptr[ser->pos+1] = acceptNode[2];
//此时我们需要向这两个空的节点中赋值
SerNodeInitiate(ser);
while(s->key[ser->pos]< s->key[(Max)/2]){
acceptNode[1]->key[ser->pos] = s->key[ser->pos];
ser->pos++;
}
int i = 1;
while(s->key[ser->pos]< s->key[Max]){
acceptNode[2]->key[i] = s->key[ser->pos];
i++;
ser->pos++;
}
cout<<"分裂完成!"<<endl;
return B;//此时返回根节点
}*/
}else if(p == NULL){
cout<<"---------此时为根结点的分裂!"<<endl;
SerNodeInitiate(ser);
if(acceptNode[0]!=NULL){
free(acceptNode[0]);
}
acceptNode[0] = BiTreeNewNode();
if(acceptNode[0]!= NULL){
cout<<"新的根节点申请成功!"<<endl;
}
BiTreeInitiate(acceptNode[0]);
// GetSerNodeInformation(acceptNode[0],ser,s->key[(Max)/2]);//获取ser->pos的值
BiTreeInsert(acceptNode[0],ser,s->key[Max/2+1]);//对新创建的根节点进行插入
acceptNode[0]->parent = NULL;
for(int i = 1;i >=0 ;i--){
acceptNode[0]->ptr[i] =acceptNode[i+1];
}
//此时我们需要向这两个空的节点中赋值
SerNodeInitiate(ser);
while(ser->pos < Max/2+1){
acceptNode[1]->key[ser->pos] = s->key[ser->pos];
acceptNode[1]->keyNum++;
ser->pos++;
}
acceptNode[1]->parent = acceptNode[0];
int i = 1;
while(i < Max-Max/2){
acceptNode[2]->key[i] = s->key[ser->pos+1];
acceptNode[2]->keyNum++;
i++;
ser->pos++;
}
acceptNode[2]->parent = acceptNode[0];
count1--;
free(s);
return acceptNode[0];//此时返回根节点
}/*else if(p != NULL&&ser->pos< s->keyNum){//此时非根节点的分裂,意味着其有父亲节点
cout<<"此时为非根结点的分裂!"<<endl;
SerNodeInitiate(ser);
GetSerNodeInformation(p,ser,s->key[(Max)/2]);
//此时获取到了这个元素在父节点中的位置
if(p->keyNum >= Max){
s = p;
p= p->parent;
BiTreeSplit(B,s,ser,p);
}else{
BiTreeInsert(p,ser,s->key[Max/2]);//对新创建的根节点进行插入
p->ptr[ser->pos] = acceptNode[1];
p->ptr[ser->pos+1] = acceptNode[2];
//此时我们需要向这两个空的节点中赋值
SerNodeInitiate(ser);
while(s->key[ser->pos]< s->key[(Max)/2]){
acceptNode[1]->key[ser->pos] = s->key[ser->pos];
acceptNode[1]->ptr[ser->pos-1] = s->ptr[ser->pos-1];
ser->pos++;
}
acceptNode[1]->ptr[ser->pos-1] = s->ptr[ser->pos-1];
int i = 1;
while(s->key[ser->pos]< s->key[Max]){
acceptNode[2]->key[i] = s->key[ser->pos];
acceptNode[2]->ptr[i-1] = s->ptr[ser->pos-1];
i++;
ser->pos++;
}
acceptNode[2]->ptr[i-1] = s->ptr[ser->pos-1];
cout<<"分裂完成!"<<endl;
return B;//此时返回根节点
}
}
*/
}
/**
*B-树的创建
*
*/
/**
*B_树的插入
*@param BiTreeNode*B 表示要根节点
*@param KeyType num表示要插入的新元素
*@param SerNode *Ser表示获取查询节点的地址
*@return 无
*/
void BiTreeInsert(BiTreeNode *B,SerNode * Ser,KeyType num){
SerNode *p = Ser;
BiTreeNode *p1 = NULL;
p->pt = B;
p1 = B;
char c = 0;
//此时根节点为空的情况
if(p1->keyNum == 0){
cout<<"此节点为空节点!"<<endl;
p1->key[p->pos] = num;
p1->keyNum++;
for(int i = 0;i <= p1->keyNum;i++){
p1->ptr[i] = NULL;
}
if(p1->keyNum == 1){
cout<<"插入成功!"<<endl;
return ;
}
}
//此时得到了指向该节点的指针
for(int i= p1->keyNum;i > 0 ;){//查找到要插入的节点获取其地址
if(num >=p1->key[i]&&p1->ptr[i] == NULL||num < p1->key[i]&&p1->ptr[i-1] == NULL){
break;
}
if(num >= p1->key[i]&&p1->ptr[i] != NULL){
/*if(p1->ptr[i]->keyNum == Max&&num >= p1->key[i]&&p1->keyNum <Max){
break;
}
if(i==1&&num <p1->key[i]&&p1->keyNum <Max&&p1->ptr[i-1]->keyNum == Max ){
break;
}*/
if(i+1<=p1->keyNum&&num >= p1->key[i]&&num<=p1->key[i+1]){
p1 = p1->ptr[i];
}else if(num >= p1->key[p1->keyNum]&&p1->ptr[p1->keyNum]!= NULL){
p1 = p1->ptr[i];
}else if(i == 1&&num <p1->key[i]&&p1->ptr[i-1] != NULL){
p1= p1->ptr[i-1];
}else{
i--;
}
}else{
if(i == 1&&num <p1->key[i]&&p1->ptr[i-1] != NULL){
p1= p1->ptr[i-1];
}else{
i--;
}
}
//这时已经获取到了地址,那么我们需要进行插入操作
//插入操作
cout<<"-------------------"<<p1<<p1->key[1]<<" "<<p1->keyNum<<endl;
if(p1->keyNum < Max){
for(int i = p1->keyNum;i >0;){
if(num < p1->key[i]){
if(i ==1){
cout<<"--------"<<p1->keyNum<<endl;
for(int j = p1->keyNum; j >0;j--){
p1->key[j+1] = p1->key[j];
}
p1->key[i] = num;
p1->keyNum = p1->keyNum+1;
cout<<"插入成功!"<<endl;
return ;
}else{
i--;
continue;
}
}else{
for(int j = p1->keyNum;j>i ;j--){
p1->key[j+1] = p1->key[j];
}
cout<<"当前节点的个数和地址:"<<count1<<"个"<<endl;
if(count1<=Min){
p1->key[i+1] = num;
p1->keyNum = p1->keyNum+1;
cout<<"插入成功!"<<endl;
return ;
}else{
while(true){
cout<<"是否需要创建新节点Y/N:";cin>>c;
if(c == 'Y'||c == 'y'){
BiTreeNewNode();
break;
}else if(c == 'N'|| c == 'n'){
p1->key[i+1] = num;
p1->keyNum = p1->keyNum+1;
cout<<"插入成功!"<<endl;
return ;
}else{
cout<<"您的输入有问题,请重新输入!";
// cin>>c;
}
}
}
}
}
}else if(p1->keyNum >= Max){
cout<<"此时进入分裂:"<<endl;
B=BiTreeSplit(B,p1,Ser,p1->parent);
cout<<"分裂完成!"<<endl;
BiTreeInsert(B,Ser,num);
UpDateRoot(B,Ser);
//TraverseB_Tree(B);
return ;
}
/**
*B_树的删除
*/
void BiTreeDelete(BiTreeNode *B,SerNode *s,KeyType num){
BiTreeNode*p = NULL;
p=BiTreeSerch(B,s,num);//接收要删除的节点的地址
cout<<"p->key[1]"<<p->key[1]<<"p="<<p<<endl;
if(p == NULL){
cout<<"没有找到要删除的元素!"<<endl;
return;
}else{
//判断是否为叶子节点
int i = 0;
for(i = 0;i <= p->keyNum;){
if(p->ptr[i]== NULL){
i++;
}else{
break;
}
}
cout<<"p->keyNum="<<p->keyNum<<endl;
cout<<"p->key[1]"<<p->key[1]<<endl;
cout<<"p->ptr[0]="<<p->ptr[0]<<endl;
cout<<"i="<<i<<endl;
int c = 0;
for(int i = 1;i <= p->keyNum;i++){
if(num == p->key[i] ){
c = i;
cout<<"c="<<c<<endl;
break;
}else{
continue;
}
}
if(i >=p->keyNum){
cout<<"进行叶子节点的删除:"<<endl;
if(p->parent == NULL&&p->keyNum == 1){
cout<<"删除完毕,已无数据可删!"<<endl;
tag1= 0;
free(p);
return ;
}
if(p->keyNum >1){
for(int j = p->keyNum;j >0; ){
if(num == p->key[j]){
for(int i = 1;i <=p->keyNum-c;i++){
p->key[i] = p->key[i+1];
}
p->keyNum--;
count1--;
cout<<"删除成功!--"<<endl;
return;
}else{
j--;
}
}
}else{
int a = 0;
for(i = 0;i <= p->parent->keyNum;i++){
if(p == p->parent->ptr[i]){
a = i;
}else{
continue;
}
}
if(num >=p->parent->key[a]){
p->parent->ptr[a] = NULL;
}else{
p->parent->ptr[a-1] = NULL;
}
free(p);
count1--;
cout<<"删除成功!---"<<p->key[a]<<endl;
return ;
}
}else{
cout<<"进行非叶子节点的删除:"<<endl;
int b = 0;//记录要删除的元素的位置
int a = 0;//记录要删除的元素对于的在父节点中的位置
for(int i = 1;i <= p->keyNum;i++){
if(num == p->key[i] ){
b = i;
}else{
continue;
}
}
if(p->parent == NULL){
cout<<"此时进行的是根节点的删除!"<<endl;
}else{
for(int i = 0;i <= p->parent->keyNum;i++){
if(p == p->parent->ptr[i]){
a = i;
break;
}else{
continue;
}
}
}
cout<<"在父节点中的位置a="<<a<<endl;
cout<<"在删除节点中的位置b="<<b<<endl;
if(p->ptr[b-1]!= NULL&&p->ptr[b]!= NULL){
if(p->ptr[b-1]->keyNum >1&&p->ptr[b]->keyNum == 1){
p->key[b] = p->ptr[b-1]->key[p->ptr[b-1]->keyNum];
p = p->ptr[b-1];
BiTreeDelete(p,s,p->key[p->keyNum]);
}else if(p->ptr[b]->keyNum >1&&p->ptr[b-1]->keyNum ==1){
p->key[b] = p->ptr[b]->key[1];
p = p->ptr[b];
BiTreeDelete(p,s,p->key[1]);
}else{
p->key[b] = p->ptr[b-1]->key[p->ptr[b-1]->keyNum];
p = p->ptr[b-1];
BiTreeDelete(p,s,p->key[1]);
}
}else if(p->ptr[b-1]== NULL&&p->ptr[b]!= NULL){
p->key[b] = p->ptr[b]->key[1];
p = p->ptr[b];
BiTreeDelete(p,s,p->key[p->keyNum]);
}else if(p->ptr[b-1]!= NULL&&p->ptr[b]== NULL){
p->key[b] = p->ptr[b-1]->key[p->ptr[b-1]->keyNum];
p = p->ptr[b-1];
BiTreeDelete(p,s,p->key[1]);
}
}
cout<<"删除成功!"<<endl;
return;
}
}
/**
*B_树的输出
*@param BiTreeNode *B 表示要输出的元素所在节点地址
*@param int pos表示该元素所在该节点的位置
*@return 无
*/
void BiTreeOutPut(BiTreeNode *B,int pos){
cout<<"B="<<B<<endl;
cout<<"节点个数:"<<count1<<endl;
cout<<"元素:"<<B->key[pos]<<endl;
}
void menu(){
cout<<" |-----------------------------------------------|"<<endl;
cout<<" |-------------- 菜单 -------------|"<<endl;
cout<<" |--------------1、插入 -------------|"<<endl;
cout<<" |--------------2、查询 -------------|"<<endl;
cout<<" |--------------3、删除 -------------|"<<endl;
cout<<" |--------------4、新建节点 -------------|"<<endl;
cout<<" |--------------5、输出节点元素 -------------|"<<endl;
cout<<" |-----------------------------------------------|"<<endl;
}
void operation(BiTreeNode *root,SerNode *s){
menu();
if(tag1 == 0){
root =NULL;
}
char c = 0;
int input = 0;
int num =0;
cout<<"请选择需要的服务:1-4"<<endl;
cout<<"请输入:";cin>>input;
switch(input){
case 1://cout<<"请输入要插入的元素:";cin>>num;BiTreeInsert(root,s,num);operation(root,s);break;
if(root == NULL){
cout<<"空树!是否创树:Y/N"<<endl;
cin>>c;
if(c == 'Y'||c == 'y'){
CreateRoot(s);
cout<<"请输入要删除的节点元素:";cin>>num;
BiTreeInsert(root,s,num);
operation(root,s);break;
}else if(c == 'N'||c == 'n'){
operation(root,s);
break;
}else{
operation(root,s);
break;
}
}else{
cout<<"请输入要新建的节点元素:";cin>>num;
BiTreeInsert(root,s,num);
operation(root,s);break;
}
case 2:cout<<"请输入要查询的元素:";cin>>num;BiTreeSerch(root,s,num);operation(root,s);break;
case 3:cout<<"请输入要删除的元素:";cin>>num;if(root == NULL){cout<<"空树无法进行删除"<<endl;operation(root,s);}BiTreeDelete(root,s,num);operation(root,s);break;
case 4:cout<<"请输入要新建的节点元素:";cin>>num;BiTreeInsert(root,s,num);operation(root,s);break;//这里没做,可以完善
case 5:cout<<"输出元素:"<<endl;TraverseB_Tree(root);operation(root,s);break;
}
}
int main(){
SerNode *p = NULL;
p = (SerNode*)malloc(sizeof(SerNode));
if(p != NULL){
cout<<"查找结点空间申请成功!"<<endl;
}else{
cout<<"查找结点空间申请失败!"<<endl;
return -1;
}
BiTreeNode *root = NULL;
SerNodeInitiate(p);
root = CreateRoot(p);
system("PAUSE");
return 0;
}