B-树

这个B-树结构将数据存在磁盘上,M是一个自定义的常量,通常定义成200效率会高一些。每个节点内部采用插入排序法,这种排序法适用于节点数较小或者数据已经很有序的情况。 

#ifndef __BOOKTREE_H__
#define __BOOKTREE_H__

#include <time.h>

template <class T>
class TreeNode{
public:
 int  n;
 long a[M+1];
 T    key[M];
};

typedef struct _head{
 long root;
 long number;
}TreeHead;
//
// CBookTree 是M路B-树, 每个结点类型必须包含
//    char * name;
//    long id;
// 这两种结构, 并且依据 name 排序, 依据 name和 id进行查找,
// 依据 name插入结点, 删除结点, 修改结点.
// 其余结构不限.

template <class T>
class CBookTree{
public:
 CBookTree(){ m_root.root = -1; m_root.number = 0; m_IsUsed = 0;};
 ~CBookTree(){while(m_IsUsed)Close();};

public:
 BOOL Open(const char * FileName);
 BOOL Open(CString& pFileName);
 void Close();
 BOOL InsertNode(T& x);
 T * SearchNode(const char *name);
 T * SearchNode(long curs);
 CList<T, T&> * SearchNodeList(long group);
 BOOL ChangeNode(T& x,BOOL dayon);
 BOOL ChangeName(const char * pNewName, const char * pOldName);
 BOOL DeleteNode(const char *name);
 long GetCount();

protected:
 Triple Search(const char *name);
 BOOL SearchNode(long curs,long p);
 void SearchNodeList(long group, long p);
 long SearchDelete();

private:
 CFile m_hFile;
 CList<T, T&> m_List;
 T textTEMP;
 long ptr[20];
 TreeHead m_root;
 int m_pTop;
 int m_IsUsed;
};

template <class T>
BOOL CBookTree<T>::Open(const char * FileName)
{
 if(m_IsUsed++)return TRUE;
 if(!m_hFile.Open(FileName, CFile::modeReadWrite))
 {
  m_root.root=0;
  if(!m_hFile.Open(FileName, CFile::modeCreate|CFile::modeReadWrite))
        {AfxMessageBox("Cann't open the file.\n");return FALSE;}
  else m_hFile.Write(&m_root,sizeof(TreeHead));
  }
 else m_hFile.Read(&m_root,sizeof(TreeHead));
 return TRUE;
}

template <class T>
BOOL CBookTree<T>::Open(CString& FileName)
{
 if(m_IsUsed++)return TRUE;
 if(!m_hFile.Open(FileName, CFile::modeReadWrite))
 {
  m_root.root=0;
  if(!m_hFile.Open(FileName, CFile::modeCreate|CFile::modeReadWrite))
        {AfxMessageBox("Cann't open the file.\n");return FALSE;}
  else m_hFile.Write(&m_root,sizeof(TreeHead));
  }
 else m_hFile.Read(&m_root,sizeof(TreeHead));
 return TRUE;
}

template <class T>
void CBookTree<T>::Close()
{
 if(--m_IsUsed)return;
 m_hFile.Close();
}

template <class T>
Triple CBookTree<T>::Search(const char *name)
{
 long p,q;
 int i=0,j=0;
 TreeNode<T> a;
 Triple t;
 t.p=0L;t.i=0;t.j=0;m_pTop=0;
 ptr[0]=0L;
 for(p=m_root.root,q=0L;p;q=p,p=a.a[i],ptr[++m_pTop]=q)
 {
  m_hFile.Seek(p,CFile::begin);
  m_hFile.Read(&a,sizeof(TreeNode<T>));
  for(i=0;i<a.n;i++)
   if(strcmp(name,a.key[i].name)<=0)break;
  if( i>=a.n )continue;
  if(strcmp(a.key[i].name,name)==0)
  {
   t.p=p;t.i=i;t.j=1;
   return(t);
  }
 }
 t.p=q;t.i=i;t.j=0;
 return(t);
}

template <class T>
long CBookTree<T>::SearchDelete()
{
 long p=sizeof(TreeHead);
 int q;
 while(p != (long)m_hFile.GetLength())
 {
  m_hFile.Seek(p, CFile::begin);
  m_hFile.Read(&q,sizeof(int));
  if(q==0)return(p);
  p+=sizeof(TreeNode<T>);
 }
 m_hFile.Seek(0L, CFile::end);
 p=(long)m_hFile.GetPosition();
 return(p);
}

template <class T>
BOOL CBookTree<T>::InsertNode(T& x)
{
 Triple s;
 T K;
 time_t ltime;
 struct tm *today;
 long _A,p,q,r;
 int i;
 TreeNode<T> a, b;
 s=Search(x.name);
 if(s.j)return FALSE;
 time( &ltime );today = localtime( &ltime );
 x.day=today->tm_mday;x.month=today->tm_mon+1;
 x.year=today->tm_year+1900;
 _A=0L;p=s.p;r=0L;q=0L;
 m_root.number++;
 for(memcpy(&K,&x,sizeof(T));p;memcpy(&K,&a.key[M/2-1],sizeof(T)),_A=q,p=ptr[--m_pTop])
 {
  m_hFile.Seek(p,CFile::begin);
  m_hFile.Read(&a,sizeof(TreeNode<T>));
  i=a.n;
  while(strcmp(K.name,a.key[i-1].name)<0)
  {
   memcpy(&a.key[i],&a.key[i-1],sizeof(T));
   a.a[i+1]=a.a[i];
   if(--i<1)break;
  }
  memcpy(&a.key[i],&K,sizeof(T));
  a.a[i+1]=_A;a.n++;
  if(a.n<=M-1)
  {
   m_hFile.Seek(p, CFile::begin);
   m_hFile.Write(&a,sizeof(TreeNode<T>));
   m_hFile.Seek(0L, CFile::begin);
   m_hFile.Write(&m_root,sizeof(TreeHead));
   m_hFile.Flush();
   return(TRUE);
  }
  q=SearchDelete();
  m_hFile.Seek(q, CFile::begin);
  for(i=0;i<M/2;i++)
  {
   memcpy(&b.key[i],&a.key[i+M/2],sizeof(T));
   b.a[i]=a.a[i+M/2-1];
  }
  b.a[i]=a.a[i+M/2-1];b.n=M-M/2;a.n=M/2-1;
  m_hFile.Seek(p, CFile::begin);
  m_hFile.Write(&a,sizeof(TreeNode<T>));
  m_hFile.Seek(q, CFile::begin);
  m_hFile.Write(&b,sizeof(TreeNode<T>));
 }
 r=SearchDelete();
 m_hFile.Seek(r, CFile::begin);
 b.n=1;b.a[0]=m_root.root;memcpy(&b.key[0],&K,sizeof(T));
 b.a[1]=_A;m_root.root=r;
 m_hFile.Seek(r, CFile::begin);
 m_hFile.Write(&b,sizeof(TreeNode<T>));
 m_hFile.Seek(0L, CFile::begin);
 m_hFile.Write(&m_root,sizeof(TreeHead));
 m_hFile.Flush();
 return(TRUE);
}

template <class T>
BOOL CBookTree<T>::ChangeNode(T& x,BOOL dayon)
{
 Triple  t;
 time_t ltime;
 struct tm *today;
 TreeNode<T> a;
 if(dayon)
 {
      time( &ltime );today = localtime( &ltime );
      x.day=today->tm_mday;x.month=today->tm_mon+1;
      x.year=today->tm_year+1900;
     }
 t=Search(x.name);if(!t.j)return(FALSE);
 m_hFile.Seek(t.p, CFile::begin);
 m_hFile.Read(&a,sizeof(TreeNode<T>));
 memcpy(&a.key[t.i],&x,sizeof(T));
 m_hFile.Seek(t.p, CFile::begin);
 m_hFile.Write(&a,sizeof(TreeNode<T>));
 return TRUE;
}

template <class T>
BOOL CBookTree<T>::ChangeName(const char * pNewName, const char * pOldName)
{
 T s_temp;
 T * p;
 p = SearchNode(pOldName);
 if(p == NULL)return FALSE;
 memcpy(&s_temp, p, sizeof(T));
 DeleteNode(pOldName);
 sprintf(s_temp.name,"%s",pNewName);
 InsertNode(s_temp);
 return TRUE;
}

template <class T>
T * CBookTree<T>::SearchNode(const char *name)
{
 long p;
 int i;
 TreeNode<T> a;
 for(p=m_root.root;p;p=a.a[i])
 {
  m_hFile.Seek(p, CFile::begin);
  m_hFile.Read(&a,sizeof(TreeNode<T>));
  for(i=0;i<a.n;i++)
   if(strcmp(name,a.key[i].name)<=0)break;
  if( i>=a.n )continue;
  if(strcmp(a.key[i].name,name)==0)
  {
   memcpy(&textTEMP,&a.key[i],sizeof(T));
   return &textTEMP;
  }
 }
 return NULL;
}

template <class T>
BOOL CBookTree<T>::DeleteNode(const char *name)
{
 Triple s;
 long z,p,y;
 int i,j;
 TreeNode<T> a, b, c;
 s=Search(name);
 if(!s.j)return(FALSE);
 p=s.p;i=s.i;
 m_hFile.Seek(p, CFile::begin);
 m_hFile.Read(&a,sizeof(TreeNode<T>));
 if(a.a[0])
 {
  for(y=a.a[i+1];;ptr[++m_pTop]=y,y=b.a[0])
  {
   m_hFile.Seek(y, CFile::begin);
   m_hFile.Read(&b,sizeof(TreeNode<T>));
   if(!b.a[0])break;
  }
  memcpy(&a.key[i],&b.key[0],sizeof(T));
  m_hFile.Seek(p, CFile::begin);
  m_hFile.Write(&a,sizeof(TreeNode<T>));
  p=y;i=0;
  m_hFile.Seek(p, CFile::begin);
  m_hFile.Read(&a,sizeof(TreeNode<T>));
 }
 for(j=i;j<a.n;j++)
 {
  memcpy(&a.key[j],&a.key[j+1],sizeof(T));
  a.a[j]=a.a[j+1];
 }
 a.n--;
 while((a.n<(M/2-1))&&p!=m_root.root)
 {
  z=ptr[m_pTop--];
  m_hFile.Seek(z, CFile::begin);
  m_hFile.Read(&c,sizeof(TreeNode<T>));
  for(j=0;j<=c.n;j++)if(c.a[j]==p)break;
  if(j<c.n)
  {
   y=c.a[j+1];
   m_hFile.Seek(y, CFile::begin);
   m_hFile.Read(&b,sizeof(TreeNode<T>));
   if(b.n>=M/2)
   {
    memcpy(&a.key[a.n-1],&c.key[j],sizeof(T));
    a.a[a.n]=b.a[0];a.n++;
    memcpy(&c.key[j],&b.key[0],sizeof(T));
    for(i=0;i<b.n;i++)
    {
     memcpy(&b.key[i],&b.key[i+1],sizeof(T));
     b.a[i]=b.a[i+1];
    }
    b.n--;
    m_hFile.Seek(p, CFile::begin);
    m_hFile.Write(&a,sizeof(TreeNode<T>));
    m_hFile.Seek(y, CFile::begin);
    m_hFile.Write(&b,sizeof(TreeNode<T>));
    m_hFile.Seek(z, CFile::begin);
    m_hFile.Write(&c,sizeof(TreeNode<T>));
    return TRUE;
   }
   memcpy(&a.key[a.n],&c.key[j],sizeof(T));
   a.a[a.n]=b.a[0];
   for(i=1;i<=b.n;i++)
   {
    memcpy(&a.key[a.n+i],&b.key[i-1],sizeof(T));
    a.a[a.n+i]=b.a[i];
   }
   a.n+=b.n+1;b.n=0;
   m_hFile.Seek(p, CFile::begin);
   m_hFile.Write(&a,sizeof(TreeNode<T>));
   m_hFile.Seek(y, CFile::begin);
   m_hFile.Write(&b,sizeof(TreeNode<T>));
   a.n=c.n-1;a.a[j-1]=c.a[j-1];p=z;
   for(i=0;i<j-1;i++)
   {
    memcpy(&a.key[i],&c.key[i],sizeof(T));
    a.a[i]=c.a[i];
   }
   for(i=j;i<c.n;i++)
   {
    memcpy(&a.key[i-1],&c.key[i-1],sizeof(T));
    a.a[i-1]=c.a[i-1];
   }
    }
  else {
   y=c.a[j-1];
   m_hFile.Seek(y, CFile::begin);
   m_hFile.Read(&b,sizeof(TreeNode<T>));
   if(b.n>=M/2)
   {
    for(i=a.n;i>0;i--)
    {
     memcpy(&a.key[i],&a.key[i-1],sizeof(T));
     a.a[i]=a.a[i-1];
    }
    memcpy(&a.key[0],&c.key[j-1],sizeof(T));
    a.a[0]=b.a[b.n];a.n++;
    memcpy(&c.key[j-1],&b.key[b.n-1],sizeof(T));b.n--;
    m_hFile.Seek(p, CFile::begin);
    m_hFile.Write(&a,sizeof(TreeNode<T>));
    m_hFile.Seek(y, CFile::begin);
    m_hFile.Write(&b,sizeof(TreeNode<T>));
    m_hFile.Seek(z, CFile::begin);
    m_hFile.Write(&c,sizeof(TreeNode<T>));
    return TRUE;
   }
   memcpy(&b.key[b.n],&c.key[j-1],sizeof(T));
   b.a[b.n]=a.a[0];
   for(i=1;i<=a.n;i++)
   {
    memcpy(&b.key[b.n+i],&a.key[i-1],sizeof(T));
    b.a[b.n+i]=a.a[i];
   }
   b.n+=a.n+1;a.n=0;
   m_hFile.Seek(p, CFile::begin);
   m_hFile.Write(&a,sizeof(TreeNode<T>));
   m_hFile.Seek(y, CFile::begin);
   m_hFile.Write(&b,sizeof(TreeNode<T>));
   a.n=c.n-1;p=z;
   for(i=0;i<=j;i++)
   {
    memcpy(&a.key[i],&c.key[i],sizeof(T));
    a.a[i]=c.a[i];
   }
  }
 }
 m_hFile.Seek(p, CFile::begin);
 m_hFile.Write(&a,sizeof(TreeNode<T>));
 if(!a.n)
 {
  m_root.root=a.a[0];
  m_hFile.Seek(0L, CFile::begin);
  m_hFile.Write(&m_root,sizeof(TreeHead));
 }
 return TRUE;
}

template <class T>
T * CBookTree<T>::SearchNode(long curs)
{
 if(SearchNode(curs, m_root.root))
  return &textTEMP;
 return NULL;
}

template <class T>
BOOL CBookTree<T>::SearchNode(long curs,long p)
{
 TreeNode<T> a;
 int i;
 if(p==0L)return FALSE;
 m_hFile.Seek(p, CFile::begin);
 m_hFile.Read(&a,sizeof(TreeNode<T>));
 for(i=0;i<a.n;i++)
  if(a.key[i].id == curs)
  {
   memcpy(&textTEMP,&a.key[i],sizeof(T));
   return TRUE;
  }
 for(i=0;i<=a.n;i++)
  if(SearchNode(curs,a.a[i]))
   return TRUE;
 return FALSE;
}

template <class T>
CList<T, T&> * CBookTree<T>::SearchNodeList(long group)
{
 m_List.RemoveAll();
 SearchNodeList(group, m_root.root);
 return &m_List;
}

template <class T>
void CBookTree<T>::SearchNodeList(long group,long p)
{
 TreeNode<T> a;
 int i;
 if(p==0L)return;
 m_hFile.Seek(p, CFile::begin);
 m_hFile.Read(&a,sizeof(TreeNode<T>));
 for(i=0;i<a.n;i++)
  if(a.key[i].h_id == group)
   m_List.AddTail(a.key[i]);
 for(i=0;i<=a.n;i++)
  SearchNodeList(group,a.a[i]);
}

template <class T>
long CBookTree<T>::GetCount()
{
 return m_root.number + 1;
}

#endif

转载于:https://my.oschina.net/RapidBird/blog/3403

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值