My BTree by C++

不太优良的B树。。。调了4天,终于大功告成了。。。

//========================================
//BTreeNode.h
//B树节点类的实现声明
//========================================

#ifndef HEADER_BTREENODE
#define HEADER_BTREENODE

//----------------------------------------
#include<iostream>
//----------------------------------------

const int m = 5; //BTree的阶数,暂定为5
typedef int KeyType;

class BTreeNode
{
public:

 int keyNum;
 KeyType key[m];
 BTreeNode * child[m+1];
 BTreeNode * parent;

 void sort()
 {
  //加入新元素后调整元素及孩子指针的顺序,以满足升序排列要求
  if(!isLeaf())
   for(int i = keyNum - 1; i > 0 ; i--)
   {
    if(key[i] >= key[i-1] && child[i+1]->key[0] >= child[i]->key[0])
     break;
    else
    {
     if(key[i] < key[i-1])
     {
      KeyType t;
      t = key[i];
      key[i] = key[i-1];
      key[i-1] = t;
     }

     if(child[i+1]->key[0] < child[i]->key[0])
     {
      BTreeNode * pt;
      pt = child[i+1];
      child[i+1] = child[i];
      child[i] = pt;
     }
    }
   }
  
  else
  {
   for(int i = 1; i < m+1; i++)
    child[i] = NULL;

   for(int i = keyNum - 1; i > 0 ; i--)
   {
    
    if(key[i] >= key[i-1])
     break;
    else
    {
     if(key[i] < key[i-1])
     {
      KeyType t;
      t = key[i];
      key[i] = key[i-1];
      key[i-1] = t;
     }
    }
   }
  }
 }


 BTreeNode()
 {
  keyNum = 0;

  for(int i = 0; i < m+1; i++)
  {
   child[i] = NULL;
  }

  parent = NULL;
 }

 BTreeNode( KeyType & e,BTreeNode * first = NULL,BTreeNode * second = NULL,BTreeNode * p = NULL)
 {
  for(int i = 0; i < m+1; i++)
   child[i] = NULL;

  keyNum = 1;
  key[0] = e;
  child[0] = first;
  child[1] = second;
  parent = p;

 }

 ~BTreeNode() {}

 bool insertVal(KeyType & k,BTreeNode * nd = NULL)
 {
  //该结点数据存储已满,无法再插入数据
  
  key[keyNum] = k;
  child[keyNum+1] = nd;
  keyNum++;
  sort();
   
  if(keyNum >= m)
   return false;
  else
   return true;   

 }
 
 bool remove(int n)
 {
 
  for(int i = n; i < keyNum - 1; i++)
  {
   key[i] = key[i+1];
   child[i+1] = child[i+2];
  }
  keyNum--;

  return true;
 }

 bool removeLeafKey(KeyType & k)
 {
  //对叶子节点中的key进行删除

  if(!isLeaf())
   return false;

  int i = 0;

  while(i < keyNum && k != key[i])
   i++;
  
  if(i == keyNum)
   return false;
  else
  {
   for(int j = i; j < keyNum - 1; j++)
   {
    key[j] = key[j+1];
    child[i+1] = child[i+2];
   }   

   keyNum--;
   return true;
  }

 }


 bool isLeaf()
 {
  if(child[0] == NULL)
   return true;
  else
   return false;
 }

};
#endif //HEADER_BTREENODE

//========================================
//BTree.h
//B树类的声明
//========================================

#ifndef HEADER_BTREE
#define HEADER_BTREE

//---------------------------------------
#include "BTreeNode.h"
//---------------------------------------
class BTree
{
public:
 BTreeNode * root;
 int level;  //记录B树的层数

 BTree() {root = NULL; level = 0;}
 ~BTree() {clear();}

 BTreeNode * findhelp(BTreeNode * subroot,KeyType & k,int & pos) ;
 void clearhelp(BTreeNode * subroot);
 void printhelp(BTreeNode * subroot,int level) ;
 
 //重新调整以subroot为根节点的子树的所有节点的parent值
 void resetParent(BTreeNode * subroot); 

 BTreeNode * isBroCan(BTreeNode * node);

 void clear()
 {
  clearhelp(root);
  root = NULL;
  level = 0;
 }

 bool insert(KeyType & k);

 bool remove( KeyType & k);

 BTreeNode * find( KeyType & k,int & pos)
 {
  return findhelp(root,k,pos);
 }

};

#endif //HEADER_BTREE

 

 

//========================================
//BTree.cpp
//B树类的实现
//========================================

#include "BTree.h"
//-----------------------------------------
void BTree::clearhelp(BTreeNode * subroot)
{
 if( subroot == NULL )
  return;

 if( subroot -> isLeaf() )
 {
  delete subroot;
  return;
 } 

 for(int i = subroot->keyNum; i >= 0; i--)
 {
  clearhelp(subroot -> child[i]);
  subroot->child[i] = NULL;
 }
 
 delete subroot;
 
}
//-----------------------------------------
void BTree::resetParent(BTreeNode * subroot)
{
 if(subroot == NULL || subroot->isLeaf())
  return;
 
 for(int i = 0; i <= subroot->keyNum; i++)
 {
  subroot->child[i]->parent = subroot;
  resetParent(subroot->child[i]);
 }
 
}                                 
//-----------------------------------------
BTreeNode * BTree::isBroCan(BTreeNode * node)
{
 if(node == root || node == NULL)
  return NULL;

 BTreeNode * p = node->parent;

 //t用于定位该节点是父节点的第t个孩子
 int t = 0;
 while(t < node->parent->keyNum)
 {
  if(node->parent->key[t] < node->key[0])
   t++;
  else
   break;
 } 

 if(t == 0)
 {
  if(node->parent->child[t+1]->keyNum > m/2)
   return node->parent->child[t+1];
  else
   return NULL;
 }

 else if(t == node->parent->keyNum)
 {
  if(node->parent->child[t-1]->keyNum > m/2)
   return node->parent->child[t-1];
  else
   return NULL;
 }

 else
 {
  if(node->parent->child[t+1]->keyNum > m/2)
   return node->parent->child[t+1];
  else if(node->parent->child[t-1]->keyNum > m/2)
   return node->parent->child[t-1];
  else
   return NULL;

 }

 return NULL;
}

//-----------------------------------------
BTreeNode * BTree::findhelp(BTreeNode * subroot, KeyType & k,int & pos)
{
 if(subroot == NULL)
  return NULL;

 for(int i = 0; i < subroot->keyNum; i++)
 {
  if( k < subroot->key[i] )
   return findhelp( subroot->child[i], k ,pos);

  else if( k == subroot->key[i] )
  {
   pos = i;
   return subroot;
  }
 }

 return findhelp( subroot->child[subroot->keyNum] ,k,pos);

}
//-----------------------------------------
bool BTree::insert(KeyType & k)
{
 //当该树为空
 if(root == NULL)
 {
  root = new BTreeNode (k);
  level++;
  return true;
 }

 //不为空则找到一个叶结点node并将k插入
 BTreeNode * node = root;

 while(!node->isLeaf())
 {
  if(k > node->key[node->keyNum - 1])
   node = node->child[node->keyNum];

  else
   for(int i = 0; i < node->keyNum; i++)
    if( k < node->key[i] )
    {
     node = node->child[i];
     break;
    }

    else if( k == node->key[i] )
     return false;
  
 }
 
 while(true)
 {
  static BTreeNode * node1 = NULL;
  static BTreeNode * node2 = NULL;

  if(node->insertVal(k,node2)) 
  {
   //若节点node未上溢

   resetParent(root); //重新调整node以下的各节点的parents值
   return true;
  }
 
  else
  {
   //若发生上溢
   node1 = node;
   node2 = new BTreeNode; //(node->key[3],node->key[4],node->child[],NULL,node->parent);
   
   int j,i;
   for(j = 0 , i = m/2+1; i < m; i++,j++)
   {
    node2->key[j] = node->key[i];
    node2->child[j] = node->child[i];  
   }
   node2->child[j] = node->child[i];
   
   node2->parent = node1->parent;

   k = node->key[m/2];
   node1->keyNum = m/2;
   node2->keyNum = m/2;


   if(node == root)
   {
    root = new BTreeNode (k,node1,node2,NULL);
    root->child[0]->parent = root;
    root->child[1]->parent = root;

    level++;
    resetParent(root);
    return true;
   }

   else
    node = node->parent;
  
  }

 }
 
 return true;
}
//-----------------------------------------
bool BTree::remove( KeyType & k)
{
 int pos;
 BTreeNode * node = findhelp(root,k,pos);
 
 if(node == NULL)
  return false;

 else
 {

  if(!node->isLeaf())
  {
   //找到k的直接前驱s所在的叶子结点,用s覆盖node中的k
   //node赋值为含s叶子结点
   //从node中删除s
   BTreeNode * t = node->child[pos];
   while(!t->isLeaf())
    t = t->child[ t->keyNum ];

   node->key[pos] = t->key[ t->keyNum - 1 ];
   t->remove(t->keyNum - 1);
   node = t;
   
  }
  
  else
   node->removeLeafKey(k);

  while(true)
  {
   if(node->keyNum >= m/2)
    return true;
   
   //如果node的一个兄弟结点中有足够的key
   else if(BTreeNode * bro = isBroCan(node))
   {
     int t = 0;
    while(t <= node->parent->keyNum)
    {
     if(node->parent->key[t] < node->key[0])
      t++;
     else
      break;
    } 

    //在node及bro中重新分配key
    if(node->key[0] > bro->key[0])
    {
     node->insertVal(node->parent->key[t-1]);
     node->parent->key[t-1] = bro->key[bro->keyNum - 1];
     bro->remove(bro->keyNum - 1);
    }

    else
    {
     node->insertVal(node->parent->key[t]);
     node->parent->key[t] = bro->key[0];
     bro->remove(0);
    
    }

    return true;    
   }

   //如果node的父结点为根
   else if(node->parent == root)
   {

    //如果父节点只有一个key
    if(node->parent->keyNum == 1)
    {
     //将root、node及兄弟结点合并成新的根
     root->child[0]->insertVal(root->key[0],root->child[1]);
     for(int i = 0; i < root->child[1]->keyNum; i++)
     {
      root->child[0]->child[ root->child[0]->keyNum ] = root->child[1]->child[i];
      root->child[0]->insertVal(root->child[1]->key[i],root->child[1]->child[i+1]);
     }
     
     BTreeNode * t = root;
     root = root->child[0];
     root->parent = NULL;
     resetParent(root);
     level--;
     delete t->child[1];
     delete t;
     
     return true;
    }


    else
    {
     //合并node及兄弟结点

     if(node->key[0] < root->key[0])
     {
      node->insertVal(root->key[0]);
      for(int i = 0; i < root->child[1]->keyNum; i++)
      {
       node->child[ node->keyNum ] = root->child[1]->child[i];
       node->insertVal(root->child[1]->key[i]);
      }
      node->child[ node->keyNum ] = root->child[1]->child[ root->child[1]->keyNum ];
      root->remove(0);
     }

     else
     { 
      int t = 0;
      while(t <= node->parent->keyNum)
      {
       if(node->parent->key[t] < node->key[0])
        t++;
       else
        break;
      } 

      root->child[t]->insertVal(root->key[t]);

      for(int i = 0; i < node->keyNum; i++)
      {
       root->child[t]->child[ root->child[t]->keyNum ] = node->child[i];
       root->child[t]->insertVal(node->key[i]);
      }
      root->child[t]->child[ root->child[t]->keyNum ] = node->child[ node->keyNum ];

      delete node;
      root->remove(t);

     }

     return true;
    }
   
   
   } //else if(node->parent == root)
  
  
   else
   {
    //合并node及兄弟结点

    if(node->key[0] < node->parent->key[0])
    {
     node->insertVal(node->parent->key[0]);
     for(int i = 0; i < node->parent->child[1]->keyNum; i++)
     {
      node->child[ node->keyNum ] = node->parent->child[1]->child[i];
      node->insertVal(node->parent->child[1]->key[i]);
     }
     node->child[ node->keyNum ] = node->parent->child[1]->child[ node->parent->child[1]->keyNum ];
     node->parent->remove(0);
    }

    else
    {
     int t = 0;
     while(t <= node->parent->keyNum)
     {
      if(node->parent->key[t] < node->key[0])
       t++;
      else
       break;
     } 

     node->parent->child[t]->insertVal(node->parent->key[t]);

     for(int i = 0; i < node->keyNum; i++)
     {
      node->parent->child[t]->child[ node->parent->child[t]->keyNum ] = node->child[i];
      node->parent->child[t]->insertVal(node->key[i]);
     }
     node->parent->child[t]->child[ node->parent->child[t]->keyNum ] = node->child[ node->keyNum ];

     delete node;
     node->parent->remove(t);

    }


    node = node->parent;
   }
  
  } //while(true)
 
 }

}

B树是一种平衡多路搜索树,在数据库索引中被广泛应用。在C语言中实现B树索引可以通过以下步骤: 第一步,定义B树的数据结构。B树节点由关键字和指向子节点的指针组成。具体而言,可以使用结构体来表示B树节点,并在结构体中定义关键字和指针的数据类型。 第二步,实现插入操作。在B树中插入一个新的关键字,需要遵循一定的规则。首先,从根节点开始查找并找到合适的叶子节点。如果该叶子节点的关键字个数小于节点容量,则直接插入新的关键字。如果关键字个数达到容量,需要进行分裂操作,将关键字一分为二,并调整父节点指针。如果父节点关键字个数也达到容量,递归进行分裂操作,直到根节点。插入完成后,要确保整个B树仍然保持平衡性。 第三步,实现删除操作。在B树中删除一个关键字,同样需要遵循一定的规则。首先,从根节点开始查找并找到含有该关键字的叶子节点。如果叶子节点的关键字个数大于最小容量,则直接删除该关键字。如果小于最小容量,则需要进行合并或借用操作。接下来,从该关键字所在的叶子节点开始调整整个B树的平衡性。 第四步,实现查找操作。在B树中查找一个关键字,首先从根节点开始依次比较关键字大小,根据指针判断下一步移动的位置,直到找到该关键字或遍历完整个B树。 以上是用C语言实现B树索引的基本步骤。在实际应用中,还可以优化其性能,比如通过缓存策略减少磁盘I/O操作,或者使用前缀压缩技术减少存储空间。同时,为了保证数据的一致性和持久性,还需要实现日志记录、事务管理和并发控制等功能。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值