B-樹

B-樹

B-樹的查找
B-樹的插入ios

//算法7.8 B-樹的查找
//算法7.9 B-樹的插入


#include<iostream>
using namespace std;
#define FALSE 0
#define TRUE 1
#define OK 1
#define m 3                     //B-樹的階,暫設爲3
typedef struct BTNode{
    int keynum;                 //結點中關鍵字的個數,即結點的大小
    BTNode *parent;             //指向雙親結點
    int key[m+1];               //關鍵字矢量,0號單元未用
    BTNode *ptr[m+1];           //子樹指針矢量
}BTNode,*BTree;

//- - - - - B-樹的查找結果類型定義- - - - -
struct Result{
  BTNode *pt;                               //指向找到的結點
  int i;                                    //1..m,在結點中的關鍵字序號
  int tag;                                  //1:查找成功,0:查找失敗
};                             


int Search(BTree T,int key)
{
    BTree p=T;  
    int endnum;
    if(p)                       //樹不爲空時
    {
        endnum=p->keynum;       //得到首節點包含的記錄個數
    }
    else
    {
        return 0;               //返回沒找到
    }
    int i=0;
    if(endnum==0)
    {
        return i;               //樹存在,但僅有一個爲空根節點
    }
    else if(key>=p->key[endnum])//節點不爲空,但當前值比最大的key還大
    {
        i=endnum;
        return i;
    }
    else if(key<=p->key[1])     //節點不爲空,但當前值比最小的key還小
    {
        return i;}
    else
    {
        for(i=1;i<endnum;i++)   //有合適的位置,即處於當前結點的最大和最小值之間,或找到了
        {
            if(p->key[i]<=key && key<p->key[i+1])
                return i;
        }
    }
}

void Insert(BTree &q,int i,int x,BTree &ap)
{//將x插入q結點的i+1位置中
    int j;
    for(j=m-1;j>i;j--)          
    {
        //將插入位置以後的key所有後移一位
        q->key[j+1]=q->key[j];
    }
    for(j=m;j>i;j--)
    {
        //相應地也移動其後ptr的位置
        q->ptr[j]=q->ptr[j-1];
    }
    q->key[i+1]=x;//插入x到該位置
    q->ptr[i+1]=ap;
    q->keynum++;
}

void split(BTree &q,int s,BTree &ap)
{   //將q->key[s+1,..,m], q->ptr[s+1,..,m]移入新結點*ap做爲右結點
    //原結點做爲新的左側結點
    //中間值被保存在ap[0]->key中,等待找到跳轉回InsertBTree()尋找到到合適的插入位置插入
    int i;
    ap=new BTNode;
    for(i=s+1;i<=m;i++)
    {   //將q->key[s+1,..,m]保存到ap->key[0,..,m-s+1]中
        //將q->ptr[s+1,..,m]保存到ap->ptr[0,..,m-s+1]中
        ap->key[i-s-1]=q->key[i];   
        ap->ptr[i-s-1]=q->ptr[i];
    }
    if(ap->ptr[0])
    {
        //當ap有子樹的時候
        for(i=0;i<=1;i++)
        {
            //將ap的子樹的父親改成ap本身
            ap->ptr[i]->parent=ap;
        }
    }
    ap->keynum=(m-s)-1;
    ap->parent=q->parent;//將ap的父親改成q的父親

    q->keynum=q->keynum-(m-s);//修改q的記錄個數
}

void NewRoot(BTree &T,BTree q,int x,BTree &ap)//生成含信息(T, x, ap)的新的根結點*T,原T和ap爲子樹指針
{
    BTree newT=new BTNode;//新建一個結點做爲新的根
    
    newT->key[1]=x;//寫入新根的key[1]
    newT->ptr[0]=T;//將原來的樹根做爲新根的左子樹
    newT->ptr[1]=ap;//ap做爲新根的右子樹
    newT->keynum=1;
    newT->parent=NULL;//新根的父親爲空

    ap->parent=newT;//ap的父親爲新根
    T->parent=newT;//T的父親爲新根

    T=newT;//樹改爲新根引導的
}

//算法7.9 B-樹的插入
int InsertBTree(BTree &T,int K,BTree q,int i){
  int x=K;
  BTree ap=NULL;
  int finished=FALSE;//x表示新插入的關鍵字,ap爲一個空指針
  while(q&&!finished){
    Insert(q,i,x,ap);           //將x和ap分別插入到q->key[i+1]和q->ptr[i+1]
    if (q->keynum<m)
        finished=TRUE;      //插入完成
    else{                       //分裂結點*q
     int s= m/2;
     split(q,s,ap);
    x=ap->key[0];//  x=q->key[s];
      //將q->key[s+1..m], q->ptr[s..m]和q->recptr[s+1..m] 移入新結點*ap
      q=q->parent;
      if(q)
      {
          i=Search(q,x);
      }     //在雙親結點*q中查找x的插入位置
    }                       //else
  }                         //while
  if(!finished)             //T是空樹(參數q初值爲NULL)或者根結點已分裂爲結點*q和*ap
      NewRoot(T,q,x,ap);        //生成含信息(T, x, ap)的新的根結點*T,原T和ap爲子樹指針
  return  OK;
}                           //InsertBTree                       //InsertBTree

//算法7.8 B-樹的查找
Result SearchBTree(BTree &T, int key){
    /*在m階B-樹T上查找關鍵字key,返回結果(pt,i,tag)。若查找成功,則特徵值tag=1,指針pt所指結點中第i個關鍵字等於key;不然特徵值tag=0,等於key的關鍵字應插入在指針pt所指結點中第i和第i+1個關鍵字之間*/
    BTree p=T;
    BTree q=NULL;
    int found=FALSE;
    int i=0;            //初始化,p指向待查結點,q指向p的雙親
while(p&&!found){
    i=Search(p,key);                
    //在p->key[1..keynum]中查找i,使得:p->key[i]<=key<p->key[i+1]
    if(i>0&&p->key[i]==key)
        found=TRUE;     //找到待查關鍵字
    else
    {
        q=p;
        p=p->ptr[i];
    }
  }
    Result result;
if(found)
{
    result.pt=p;
    result.i=i;
    result.tag=1;
    return result;
}                   //查找成功
else
{
    result.pt=q;
    result.i=i;
    result.tag=0;
    return result;
}                       //查找不成功,返回K的插入位置信息
}//SearchBTree

void InitialBTree(BTree &T)
{
    //初始化一個空的根
    T->keynum=0;        
    T->parent=NULL; 
    for(int i=0;i<m+1;i++)
    {
        T->ptr[i]=NULL;
    }
}



void main()
{
    BTree T=new BTNode;
    InitialBTree(T);
    //先用SearchBTree()找到要插入的位置,獲得一個Result結構體
    //再用InsertBTree()插入數據
    Result result;
    int a[11]={45,24,53,90,3,12,50,61,70,100};
    for(int i=0;i<10;i++)
    {
        result=SearchBTree(T,a[i]);
        if(result.tag==0)
        {
            InsertBTree(T,a[i],result.pt,result.i);
        }
    }
    cout<<"OK";
}
相關文章
相關標籤/搜索