关于B树就不废话了,具体书上有
,属于平衡树,每一个节点的含有的键值以及子女指针很多,用于磁盘。基本操作代码如下:(仅供第二次复习的时候再来进行修改,还有不合适的地方,今天晚上头脑不清晰,第二次复习的时候再来看,补全代码以及相应习题)
#include <iostream>
#include <vector>
#define t 3
using namespace std;
class btreenode
{
int num;//键值的个数
vector<btreenode*> vptr;
vector<int> key;
bool leaf;
public:
btreenode(){}//默认构造函数
btreenode(int rnum,bool rleaf,vector<btreenode*> rvptr,vector<int> rkey):num(rnum),leaf(rleaf),vptr(rvptr)
{
int a;
while(cin>>a)
{
key.push_back(a);
}
}
friend btreenode* creat();
friend void search(btreenode* nodex,int k);
friend void split(btreenode* nodex,int i,btreenode* nodey);
friend void nonfull(btreenode* nodex,int k);
friend void insert(btreenode* root,int k);
~btreenode()
{
// delete nodez;//同理
// delete s;//只有确保new了该指针才可以使用delete的否则会造成一个错误。
// delete p;//只有确保调用了的话才可以使用的,这里我们调用
}
};
btreenode* creat()
{
btreenode* p=new btreenode();//构造了一个空的节点,p指向该节点,由于我们的调用的默认的构造函数num为o,其他的为空
p->leaf=true;
return p;//这个指针是我们
}
void search(btreenode* nodex,int k)
{
int i=1;
while(i<nodex->num&&k<(nodex->key)[i])
{
++i;
}
if (i<nodex->num&&(nodex->key)[i]==k)
{
cout<<"we find the num k :"<<k<<" "<<"and the address is: "<<&(nodex->key)[i]<<endl;
}
if(nodex->leaf)
{
cout<<"this is null"<<endl;
}
else
search((nodex->vptr[i]),k);
}
void split(btreenode* nodex,int i,btreenode* nodey)//如果是内节点的键值的个数是2*t-1就对于该节点执行如下的操作,假如要再次的插入
{
btreenode* nodez=new btreenode();
nodez->leaf=nodey->leaf;
nodez->num=t-1;
for(int a=1;a<=t-1;++a)
{
nodez->key[a]=nodey->key[a+t];//这里就凸显了使用容器vector的好处
}
if(!(nodey->leaf))
{
for(int j=1;j<=t;++j)
{
nodez->vptr[i]=nodey->vptr[i+t];
}
}
nodey->num=t-1;
for(int n=nodex->num+1;n>=i+1;--n)
{
nodex->vptr[n+1]=nodex->vptr[n];
}
for(int m=nodex->num;m>i;++m)
{
nodex->key[m+1]=nodex->key[m];
}
nodex->key[i]=nodey->key[t];
nodex->vptr[i+1]=nodez;
nodex->num=nodex->num+1;
}
void nonfull(btreenode* nodex,int k)//执行该操作,当是叶子节点以及非叶子节点进行的操作有如下的几种
{
int i=nodex->num;
if(nodex->leaf)
{
while (i>=1&& k<(nodex->key)[i])
{
nodex->key[i+1]=nodex->key[i];//使用容器的好处彰显了。c可以么?麻烦起来可以
--i;
}
nodex->key[i+1]=k;
nodex->num=nodex->num+1;
}
else//如果是非叶子节点的话,就需要向下进行探索了
{
while (i>=1&& k<nodex->key[i])
{
--i;
}
i=i+1;
if((nodex->vptr[i])->num==2*t-1)
{
split(nodex,i,nodex->vptr[i]);
if(k>nodex->key[i])
++i;
}
nonfull(nodex->vptr[i],k);
}
}
void insert(btreenode* root,int k)//只有在被操作的对象是一个叶子节点的时候才可以,其他的情况下要调用上面的nonfull()函数
{
if(root->num==2*t-1)
{
btreenode* s=new btreenode();
s->num=0;
s->leaf=false;
s->vptr[1]=root;
split(s,1,root);
nonfull(s,k);
}
else
nonfull(root,k);
}
int main()
{
int ra;
int na;
int rk;
//这里有一个疑问就是对于那些new出来的东西,哪里有一个比较不错的处理方案呢?上面的话我们比不可少需要这么一个nodez之类的
//去,在构造树的时候插入的话也不可以马上的在成员函数中delete啊,只有析构函数,但是对于很多的节点的话怎么去delete呢?
//这里对于B树而言,添加键值以及指针有点麻烦。
btreenode* nroot=new btreenode;
//上面的东西在这里的话是不是那么的特殊需要的,因为对于构造函数的话也是可以这么的构造一个对象,但是对于root的话,特殊点。
// btreenode* nodea=creat();
cin>>rk;
insert(nroot,rk);//对于键值根假如有2*t-1的话插入一个键值,进行下面的操作。
/
return 0;
}
,属于平衡树,每一个节点的含有的键值以及子女指针很多,用于磁盘。基本操作代码如下:(仅供第二次复习的时候再来进行修改,还有不合适的地方,今天晚上头脑不清晰,第二次复习的时候再来看,补全代码以及相应习题)