类stl的btree模板

类别:编程语言 点击:0 评论:0 推荐:

    最近写了一个类似stl的btree,拿出来与大家共享一下。这个btree的用法与stl中的map非常相似。我在vc7.1和redhat(gcc 3.2)中编译成功。btree未经过严格测试,欢迎大家一起来测试完善他。

     如果发现有什么问题,或者有什么建议,可以跟我联系。联系方式:[email protected]

1.btree源码
#ifndef _LARRIN_WORKSHOP_BTREE_H
#define _LARRIN_WORKSHOP_BTREE_H

#include <memory.h>

#define BEGIN_NAMESPACE namespace LarrinDSL {
#define END_NAMESPACE }

#ifndef NULL
#ifdef __cplusplus
#define NULL    0
#else
#define NULL    ((void *)0)
#endif
#endif

BEGIN_NAMESPACE

template<class Type>
struct btree_less
{
 bool operator()(const Type& _Left, const Type& _Right) const
 {
  return _Left < _Right ;
 }
};

template <class _first_,class _second_>
struct btree_pair
{
 /*typename*/ _first_ first ;
 /*typename*/ _second_ second ;

 btree_pair(){}

 btree_pair(/*typename*/ _first_ v1,/*typename*/ _second_ v2)
 {
  first = v1 ;
  second = v2;
 }

 ~btree_pair(){}
};

template <class Key, class Type, unsigned int order , class Traits = btree_less<Key> >
class btree
{
 
public:

 typedef Key key_type ;
 typedef Type data_type;
 typedef Traits key_compare;
 typedef unsigned long size_type;

 typedef btree_pair<key_type,data_type> value_type ;

private:

 typedef btree<Key,Type,order,Traits> _btree_;
 static const unsigned int mid_pos = (int)(order / 2);
 static const unsigned int max_val_size = order - 1 ;
 static const unsigned int min_vals = ((order + 1) / 2) - 1 ;

 struct tree_iterator;

 class BTNode
 {
  friend class _btree_;
  friend class _btree_::tree_iterator ;
  
  int   keynum  ;   
  BTNode  *parent ;
  int   sub_id  ; //i am my parent's sub_id'th sun
  value_type *vals[order]  ; //value node
  BTNode  *subTree[order+1] ;

 public:

  BTNode()
  {
   memset(this,0,sizeof(BTNode));  
  }

  ~BTNode()
  {
  }

  BTNode *left_sibling()
  {
   if(this->parent && this->sub_id > 0)
   {
    return this->parent->subTree[sub_id - 1];
   }

   return NULL ;
  }

  BTNode *right_sibling()
  {
   if(this->parent && this->sub_id < this->parent->keynum)
   {
    return this->parent->subTree[sub_id + 1];
   }

   return NULL ;
  }

  void set_parent(BTNode *p,const int sub_id)
  {
   this->parent = p ;
   this->sub_id = sub_id ;
   this->parent->subTree[sub_id] = this ;
  }

  Key & _key_(const int idx){return vals[idx]->first ;}

  bool find_in_node(const Key &key,int &pos)
  {
   if(keynum == 0)
   {
    pos = 0 ;
    return false ;
   }

   pos = -1 ;

   //binary search ...
   int top,bottom,mid ;
   top = 0 ;
   bottom = keynum == 0 ? 0 : keynum -1;

   typename _btree_::key_compare less;
   for(;;)
   {
    mid = (top + bottom) / 2 ;
    if(less(key , _key_(mid))) //key < _key_(mid)
    {
     if(top >= bottom -1)
     {
      pos = mid ;
      return false ;
     }

     bottom = mid - 1 ;
    }
    else if(less(_key_(mid),key)) //key > _key_(mid)
    {
     if(top == bottom)
     {
      pos = mid + 1;
      return false ;
     }

     top = mid + 1 ;
    }
    else //find it
    {
     pos = mid ;
     return true ;
    }
   }
  }

  void move_up(int new_key_pos,BTNode *&node,int &where)
  {
   BTNode *new_node = new BTNode ;
   int k = 0 ;
   for(int i = mid_pos + 1 ; i <= max_val_size ; i++,k++)
   {
    new_node->vals[k] = this->vals[i] ;
    if(this->subTree[i])
     this->subTree[i]->set_parent(new_node,k);
    this->keynum--;
    new_node->keynum++;
   }

   if(this->subTree[max_val_size+1])
    this->subTree[max_val_size+1]->set_parent(new_node,k);
   
   if(new_key_pos != -1)
   {
    if(new_key_pos < mid_pos) // new key will keep it's position
    {
     new_key_pos = -1 ; //keep it's position
    }
    else if(new_key_pos > mid_pos) //new key will be move up
    {
     node = new_node ;
     where = where - mid_pos - 1;
     new_key_pos = -1 ; //keep new key's position
    }
    //else{} //new key will be moveup
   }
   
   if(this->parent) // have parent's
   {
    if(new_key_pos != -1) // new key is moved into parent
    {
     node = this->parent ;
     where = this->sub_id;
    }

    for(int i = this->parent->keynum ; i > this->sub_id ; i--)
    {
     this->parent->vals[i] = this->parent->vals[i-1];
     this->parent->subTree[i]->set_parent(this->parent,i+1);
    }

    this->parent->vals[this->sub_id] = this->vals[mid_pos] ;
    --this->keynum;

    new_node->set_parent(this->parent,this->sub_id+1);

    if(++this->parent->keynum > max_val_size)
    {
     this->parent->move_up(new_key_pos,node,where);
    }
   }
   else // i am the current root
   {
    BTNode *new_root = new BTNode ;
    new_root->vals[0] = this->vals[mid_pos];
    --this->keynum;
    ++new_root->keynum ;

    if(new_key_pos != -1)
    {
     node = new_root ;
     where = 0 ;
    }

    this->set_parent(new_root,0);

    new_node->set_parent(new_root,1);
   }
  }

  bool insert(const key_type &key,const data_type &data,BTNode *&node,int &where)
  {
   int pos ;
   if(find_in_node(key,pos)) //key exsist in this node already
   {
    return false ;
   }

   if(this->subTree[pos] != NULL)
   {
    return this->subTree[pos]->insert(key,data,node,where);
   }
   else
   {
    for(int i = this->keynum ; i > pos; i--)
    {
     this->vals[i] = this->vals[i-1] ;
    }

    {//where the new key is inserted
     node = this ;
     where = pos ;
    }
   
    vals[pos] = new value_type ;
      
    vals[pos]->first = key ;
    vals[pos]->second = data ;

    if(++this->keynum > max_val_size) //slipt this node,new key will be moved up
    {
     move_up(pos,node,where);
    }

    return true ;
   }
  }
  
  bool find(const Key &key,BTNode *&node,int &pos)
  {
   if(find_in_node(key,pos))
   {
    node = this ;
    return true ;
   }
   else
   {
    if(this->subTree[pos])
    {
     return this->subTree[pos]->find(key,node,pos);
    }
    else
    {
     return false ;
    }
   }
  }

  BTNode * erase(BTNode *node,int idx)
  {
   //step1 : delete the key
   delete node->vals[idx];

   //step2 : find my successor( or former)
   BTNode *leaf ;
   {
    int rIdx ;
    if(NULL == node->subTree[idx+1]) //node is a leaf
    {
     leaf = node ;
     rIdx = idx ;
    }
    else
    {
     rIdx = 0 ;
     leaf = node->subTree[idx+1] ;
     while(NULL != leaf->subTree[0])
     {
      leaf = leaf->subTree[0] ;
     }

     node->vals[idx] = leaf->vals[0] ; //copy successor to ... 
    }

    //move
    for(int i = rIdx ; i < leaf->keynum - 1; i++)
    {
     leaf->vals[i] = leaf->vals[i+1];
    }

    leaf->keynum-- ;
   }

   //now the key is removed,we need makes sure of balance of this tree

   //case 1
   if(leaf->keynum >= min_vals)           
    return NULL;

   return merge(leaf);
  }

  BTNode * merge(BTNode *node)
  {
   //case 2
   if(!node->parent) //this is root too
    return NULL;   
   
   //case 3
   {
    BTNode *sibling = node->left_sibling();
    if(sibling && sibling->keynum > min_vals)
    {
     for(int i = node->keynum ; i > 0 ; i--)
     {
      node->vals[i] = node->vals[i-1];
      if(node->subTree[i])
       node->subTree[i]->set_parent(node,i+1); 
     }
     node->vals[0] = node->parent->vals[node->sub_id-1];
     if(sibling->subTree[sibling->keynum])
      sibling->subTree[sibling->keynum]->set_parent(node,0);
     node->keynum++;

     node->parent->vals[node->sub_id-1] = sibling->vals[sibling->keynum-1];
     sibling->keynum-- ;
     return NULL;
    }

    sibling = node->right_sibling();
    if(sibling && sibling->keynum > min_vals)
    {
     node->vals[node->keynum] = node->parent->vals[node->sub_id];
     if(sibling->subTree[0])
      sibling->subTree[0]->set_parent(node,node->keynum + 1) ;
     node->keynum++ ;

     node->parent->vals[node->sub_id] = sibling->vals[0];

     for(int i = 0 ; i < sibling->keynum - 1 ;i++)
     {
      sibling->vals[i] = sibling->vals[i+1] ; //move ...
      if(sibling->subTree[i+1])
       sibling->subTree[i+1]->set_parent(sibling,i)  ;
     }
     if(sibling->subTree[sibling->keynum])
      sibling->subTree[sibling->keynum]->set_parent(sibling,sibling->keynum - 1) ;

     sibling->keynum--;
     return NULL;
    }
   }

   //case 4 : do merge now
   {
    BTNode *left ,*right ;
    left = node->left_sibling();
    if(left)
    {
     right = node ;
    }
    else
    {
     left = node ;
     right = node->right_sibling() ;
    }

    //now merge left/right/parent
    
    //step1:
    {
     left->vals[left->keynum] = left->parent->vals[left->sub_id];
     if(right->subTree[0])
      right->subTree[0]->set_parent(left,left->keynum+1);
     left->keynum++;
    }

    //step2:remove parent's valus
    {
     for(int i = left->sub_id ; i < left->parent->keynum - 1 ; i++)
     {
      left->parent->vals[i] = left->parent->vals[i+1];
      if(left->parent->subTree[i+2])
       left->parent->subTree[i+2]->set_parent(left->parent,i+1) ;
     }

     left->parent->keynum--;
    }

    //step3: merge left and right - move right into left
    {
     for(int i = 0 ; i < right->keynum ; i++)
     {
      left->vals[left->keynum] = right->vals[i];
      left->keynum++;
      if(right->subTree[i+1])
       right->subTree[i+1]->set_parent(left,left->keynum) ;
     }

     delete right ;
    }

    if(left->parent->keynum < min_vals)
    {
     if(left->parent->keynum == 0 && !left->parent->parent) //this is root,left become new root
     {
      delete left->parent ;
      left->parent = NULL ;
      return left ;
     }
     else
     {
      return merge(left->parent);
     }
    }
   }
  }

  void destroy()
  {
   for(int i = 0 ; i < this->keynum ; i++)
   {
    delete vals[i];
   }

   if(this->subTree[0] == NULL) //this is a leaf
   {
    delete this ;
    return ;
   }
   else
   {
    for(int i = 0 ; i < this->keynum+1 ; i++)
    {
     this->subTree[i]->destroy();
    }
   }

   delete this ;
  }
 };

 BTNode *m_Root ;  //btree
 size_type m_size ;  

public:

 struct tree_iterator
 {
  BTNode * curNode ;
  int curKey ;

  tree_iterator():curNode(NULL),curKey(0){}
  tree_iterator(BTNode *node,int key):curNode(node),curKey(key){}

  value_type & operator->() const
  {
   return *(curNode->vals[curKey]);  
  }

  value_type & operator *() const
  {
   return *(curNode->vals[curKey]);
  }

  bool operator == (const tree_iterator &it) const
  {
   return (this->curNode == it.curNode && this->curKey == it.curKey) ;
  }

  bool operator != (const tree_iterator &it) const
  {
   return (this->curNode != it.curNode || this->curKey != it.curKey) ;
  }

  tree_iterator & operator ++()
  {
   if(curNode->subTree[curKey+1] == NULL)
   {
    if(++curKey < curNode->keynum)
    {
    }
    else
    {
     //check if this is end()
     BTNode *node = curNode->parent ;
     if(node == NULL)
     {
      return *this ; //end
     }
     int tmp = curNode->sub_id;
     while(node && tmp >= node->keynum)
     {
      tmp = node->sub_id ;
      node = node->parent ;
     }

     if(node == NULL)
     {
      return *this ; //end
     }
   
     curKey = tmp ;
     curNode = node ;
    }
   }
   else
   {
    curNode = curNode->subTree[curKey+1] ;
    while(curNode->subTree[0])
    {
     curNode = curNode->subTree[0];
    }

    curKey = 0 ;
   }

   return *this ;
  }
 };

 struct const_tree_iterator
 {
  const BTNode *curNode ;
  int curKey ;

  const_tree_iterator():curNode(NULL),curKey(0){}
  const_tree_iterator(const BTNode *node,int key):curNode(node),curKey(key){}
 };

public:

 typedef tree_iterator iterator ;
 typedef const_tree_iterator const_iterator ;

 btree():m_Root(NULL),m_size(0)
 {
 }

 ~btree()
 {
  clear();
 }

 iterator begin( )
 {
  if(!m_Root) return iterator(NULL,-1);

  BTNode *node = m_Root ;  
  while(node->subTree[0])
  {
   node = node->subTree[0] ;
  }

  return  tree_iterator(node,0);
 }

 const_iterator begin( ) const
 {
  if(!m_Root) return iterator(NULL,-1);

  const BTNode *node = m_Root ;  
  while(node->subTree[0])
  {
   node = node->subTree[0] ;
  }

  return  const_tree_iterator(node,0);
 }

 iterator end()
 {
  if(!m_Root) return iterator(NULL,-1);

  BTNode * node = m_Root ;
  while(node->subTree[node->keynum-1])
  {
   node = node->subTree[node->keynum];
  }

  return tree_iterator(node,node->keynum);
 }

 btree_pair<iterator,bool> insert(const Key &key,const Type & data)
 {
  typedef btree_pair<iterator,bool> ret_type ;

  BTNode *node ;
  int pos ;

  if(NULL == m_Root)
  {
   m_Root = new BTNode();
  }

  if(m_Root->insert(key,data,node,pos))
  {
   while(m_Root->parent)
   {
    m_Root = m_Root->parent ;
   }

   m_size++ ;
   return ret_type(iterator(node,pos),true) ;
  }

  return ret_type(this->end(),false) ;
 }

 Type & operator[](const Key &key)
 {
  if(!this->m_Root)
  {
   this->m_Root = new BTNode ;
  }

  iterator it = this->find(key);
  if(it != this->end())
  {
   return (*it).second ;
  }
  else
  {
   btree_pair<iterator,bool> res = this->insert(key,data_type());
   return (*res.first).second ;
  }
 }

 iterator find(const Key& key)
 {
  if(!m_Root) return iterator(NULL,-1);
  BTNode *node ;
  int pos ;

  if(m_Root->find(key,node,pos))
  {
   return iterator(node,pos);
  }
  else
  {
   return end();
  }
 }

 size_type erase(const Key &key)
 {
  iterator it = this->find(key);
  erase(it) ;
  return m_size ;
 }

 void erase(iterator where)
 {
  if(where != this->end())
  {
   BTNode *root = m_Root->erase(where.curNode,where.curKey);
   if(root) m_Root = root ; //wei have new root ;
   m_size--;
  }
 }

 size_type size()
 {
  return m_size ;
 }

 void clear()
 {
  if(m_Root)
  {
   m_Root->destroy();
  }
  
  m_Root = NULL ;
  m_size = 0 ;
 }

 bool empty()
 {
  return m_size == 0 ;
 }
};

END_NAMESPACE

#endif //

2.测试程序
#include "btree.h"
#include <stdio.h>

using namespace LarrinDSL ;
int main()
{
 typedef btree<char,char,5> testTree ;
 testTree a;

 char keys[] = "agfbkdhmjesirxclntup" ;
 
 for(char *p = keys ; *p ; p++)
 {
  //btree_pair<testTree::iterator,bool> k = a.insert(*p,*p);
  a[*p] = *p ;
 }

 a.erase('h');
 a.erase('r');
 a.erase('p');
 a.erase('d');

 return 0 ;
}

 

本文地址:http://com.8s8s.com/it/it28867.htm