00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017 #ifndef _TemplateLibrary_BTree_H_
00018 #define _TemplateLibrary_BTree_H_ 1
00019
00028 #include <lib/sconfig.h>
00029
00030 #include <lib/salloc.h>
00031 #include <lib/tl/defop.h>
00032
00033 #ifndef TLIB_DEBUG_BTREE
00034 # define TLIB_DEBUG_BTREE 0
00035 #endif
00036
00037 #if TLIB_DEBUG_BTREE
00038
00039 # define TLBT_ASSERT(x) Assert(x)
00040
00041 #endif
00042
00078 template<typename T,typename _OP=TLDefaultOperators_CDT<T> >class TLBTree
00079 {
00080 public:
00082 struct Node
00083 {
00084 int nelem;
00085 Node **down;
00086 char _elem[];
00087
00088
00090 inline T &elem(int idx,TLBTree *bt)
00091 { return(*(T*)(_elem+idx*bt->OP.size())); }
00093 inline T *elemP(int idx,TLBTree *bt)
00094 { return((T*)(_elem+idx*bt->OP.size())); }
00095
00104 template<typename K>bool _LBI(const K &e,int *idx,TLBTree *bt)
00105 {
00106
00107 #if 0
00108
00109 int a=0,b=nelem-1;
00110 if(bt->OP.gt(elem(0,bt),e)) { *idx=0; return(0); }
00111 if(bt->OP.lt(elem(b,bt),e)) { *idx=nelem; return(0); }
00112 while(b-a>1)
00113 { int m=(a+b)/2; bt->OP.lt(elem(m,bt),e) ? a=m : b=m; }
00114 if(bt->OP.eq(elem(a,bt),e)) { *idx=a; return(1); }
00115 *idx=b; return(bt->OP.eq(elem(b,bt),e));
00116 #else
00117
00118
00119
00120 int a=0,b=nelem-1;
00121 while(b-a>1)
00122 { int m=(a+b)/2; bt->OP.lt(elem(m,bt),e) ? a=m : b=m; }
00123 if(!a && bt->OP.gt(elem(0,bt),e)) { *idx=0; return(0); }
00124 if(b==nelem-1 && bt->OP.lt(elem(b,bt),e))
00125 { *idx=nelem; return(0); }
00126 if(bt->OP.eq(elem(a,bt),e)) { *idx=a; return(1); }
00127 *idx=b; return(b && bt->OP.eq(elem(b,bt),e));
00128 #endif
00129 }
00130
00140 inline void _INSLeafNS(int idx,const T &e,TLBTree *bt)
00141 {
00142 if(idx==nelem) { bt->OP.ini(elemP(nelem++,bt),e); return; }
00143 int i=nelem-1; bt->OP.ini(elemP(nelem,bt),elem(i,bt));
00144 for(; i>idx; i--) bt->OP.ass(elem(i,bt),elem(i-1,bt));
00145 bt->OP.ass(elem(idx,bt),e); ++nelem;
00146 }
00147
00158 inline void _INS_NS(int idx,const T &e,Node *chld,TLBTree *bt)
00159 {
00160 down[nelem+1]=down[nelem];
00161 if(idx==nelem)
00162 { bt->OP.ini(elemP(nelem++,bt),e); down[idx]=chld; return; }
00163 int i=nelem-1;
00164 bt->OP.ini(elemP(nelem,bt),elem(i,bt)); down[nelem]=down[i];
00165 for(; i>idx; i--)
00166 { bt->OP.ass(elem(i,bt),elem(i-1,bt)); down[i]=down[i-1]; }
00167 bt->OP.ass(elem(idx,bt),e); down[idx]=chld; ++nelem;
00168 }
00169
00171 inline void _DELLeaf(int idx,TLBTree *bt)
00172 {
00173 --nelem;
00174 for(int i=idx; i<nelem; i++)
00175 bt->OP.ass(elem(i,bt),elem(i+1,bt));
00176 bt->OP.clr(elemP(nelem,bt));
00177 }
00178
00181 inline void _DEL_L(int idx,TLBTree *bt)
00182 {
00183 --nelem;
00184 for(int i=idx; ; i++)
00185 {
00186 down[i]=down[i+1]; if(i>=nelem) break;
00187 bt->OP.ass(elem(i,bt),elem(i+1,bt));
00188 }
00189 bt->OP.clr(elemP(nelem,bt)); down[nelem+1]=NULL;
00190 }
00193 inline void _DEL_R(int idx,TLBTree *bt)
00194 {
00195 --nelem;
00196 for(int i=idx; i<nelem; )
00197 {
00198 bt->OP.ass(elem(i,bt),elem(i+1,bt)); ++i;
00199 down[i]=down[i+1];
00200 }
00201 bt->OP.clr(elemP(nelem,bt)); down[nelem+1]=NULL;
00202 }
00203
00204 inline Node() : nelem(0),down(NULL) {}
00205 inline ~Node()
00206 { }
00207 };
00208
00209 private:
00210
00211 int m;
00212 Node *root;
00213 T tmp;
00214
00215 public:
00216
00217
00218 _OP OP;
00219
00220 private:
00221
00222
00223
00224
00230 Node *_AllocLeaf()
00231 {
00232 void *place=OP.alloc( sizeof(Node) + OP.size()*(m+m) );
00233 return(new(place) Node());
00234 }
00236 Node *_AllocNonLeaf()
00237 {
00238 Node *n=_AllocLeaf();
00239 n->down=(Node**)OP.alloc(sizeof(Node*)*(m+m+1));
00240 for(int i=0,e=m+m; i<=e; i++) n->down[i]=NULL;
00241 return(n);
00242 }
00249 inline Node *_FreeNode(Node *n)
00250 { OP.free(n->down); n->Node::~Node(); OP.free(n); return(NULL); }
00251
00253 void _DeleteTree(Node *tn)
00254 {
00255 if(!tn) return;
00256 if(tn->down) for(int i=0; i<=tn->nelem; i++)
00257 _DeleteTree(tn->down[i]);
00258 for(int i=0; i<tn->nelem; i++) OP.clr(&tn->elem(i,this));
00259 _FreeNode(tn);
00260 }
00261
00263 template<typename K>T *_Find(const K &key,Node *tn)
00264 {
00265 for(int idx; ; tn=tn->down[idx])
00266 {
00267 if(tn->_LBI(key,&idx,this)) return(&tn->elem(idx,this));
00268 if(!tn->down) break;
00269 }
00270 return(NULL);
00271 }
00272
00274 Node *_FindSmallestLeaf(Node *n)
00275 { while(n->down) n=n->down[0]; return(n); }
00277 Node *_FindLargestLeaf(Node *n)
00278 { while(n->down) n=n->down[n->nelem]; return(n); }
00280 T *_FindSmallest(Node *n)
00281 { return(&_FindSmallestLeaf(n)->elem(0,this)); }
00282 T *_FindLargest(Node *n)
00283 { n=_FindLargestLeaf(n); return(&n->elem(n->nelem-1,this)); }
00284
00286 template<typename K>T *_FindNeighbours(const K &key,Node *tn,
00287 T **p,T **n)
00288 {
00289 int idx;
00290 if(tn->_LBI(key,&idx,this))
00291 {
00292 if(p) if(tn->down) *p=_FindLargest(tn->down[idx]);
00293 else if(idx>0) *p=&tn->elem(idx-1,this);
00294 if(n) if(tn->down) *n=_FindSmallest(tn->down[idx+1]);
00295 else if(idx+1<tn->nelem) *n=&tn->elem(idx+1,this);
00296 return(&tn->elem(idx,this));
00297 }
00298 T *rv = tn->down ? _FindNeighbours(key,tn->down[idx],p,n) : NULL;
00299 if(p && !*p && idx>0) *p=&tn->elem(idx-1,this);
00300 if(n && !*n && idx<tn->nelem) *n=&tn->elem(idx,this);
00301 return(rv);
00302 }
00303
00311 int _Store(Node *tn,const T &e,Node **split,bool allow_update,
00312 T *oldval)
00313 {
00314 int idx;
00315 if(tn->_LBI(e,&idx,this))
00316 {
00317 if(oldval) OP.ass(*oldval,tn->elem(idx,this));
00318 if(allow_update) OP.ass(tn->elem(idx,this),e);
00319 return(1);
00320 }
00321 if(!tn->down)
00322 {
00323 if(tn->nelem<m+m) { tn->_INSLeafNS(idx,e,this); return(0); }
00324
00325 Node *l=_AllocLeaf();
00326 int d=0,s=0;
00327
00328 while(d<m) OP.ini(&l->elem(d++,this),
00329 s==idx ? (idx=-1,e) : tn->elem(s++,this));
00330
00331 if(s==idx) OP.ini(&tmp,(idx=-1,e));
00332 else { OP.ini(&tmp,tn->elem(s,this));
00333 if(s>=m) OP.clr(&tn->elem(s,this)); ++s; }
00334
00335 for(d=0; d<m; )
00336 if(s==idx) OP.ass(tn->elem(d++,this),(idx=-1,e));
00337 else { OP.ass(tn->elem(d++,this),tn->elem(s,this));
00338 OP.clr(&tn->elem(s++,this)); }
00339 tn->nelem=m; l->nelem=m; *split=l; return(3);
00340 }
00341 Node *isplit;
00342 int rv=_Store(tn->down[idx],e,&isplit,allow_update,oldval);
00343 if(rv!=3) return(rv);
00344 if(tn->nelem<m+m)
00345 { tn->_INS_NS(idx,tmp,isplit,this); OP.clr(&tmp); return(0); }
00346
00347 T itmp(tmp); OP.clr(&tmp);
00348 Node *l=_AllocNonLeaf();
00349 int d=0,s=0;
00350
00351 while(d<m)
00352 if(s==idx) { OP.ini(&l->elem(d,this),(idx=-1,itmp));
00353 (l->down[d++]=isplit); }
00354 else { OP.ini(&l->elem(d,this),tn->elem(s,this));
00355 (l->down[d++]=tn->down[s++]); }
00356
00357 if(s==idx)
00358 {
00359 (l->down[d]=isplit);
00360 OP.ini(&tmp,(idx=-1,itmp));
00361 } else {
00362 OP.ini(&tmp,tn->elem(s,this));
00363 if(s>=m) OP.clr(&tn->elem(s,this));
00364 (l->down[d]=tn->down[s++]);
00365 }
00366
00367 for(d=0; d<m; )
00368 if(s==idx)
00369 { OP.ass(tn->elem(d,this),(idx=-1,itmp));
00370 tn->down[d++]=isplit; }
00371 else
00372 { OP.ass(tn->elem(d,this),tn->elem(s,this));
00373 OP.clr(&tn->elem(s,this));
00374 tn->down[d++]=tn->down[s]; tn->down[s++]=NULL; }
00375 tn->down[d]=tn->down[s]; tn->down[s]=NULL;
00376 tn->nelem=m; l->nelem=m; *split=l; return(3);
00377 }
00378
00386 bool _HandleUnderflow(Node *tn,int idx)
00387 {
00388 Node *l,*r;
00389 if(idx<tn->nelem)
00390 {
00391 l=tn->down[idx]; r=tn->down[idx+1];
00392 if(r->nelem>m)
00393 {
00394 OP.ini(&l->elem(l->nelem++,this),tn->elem(idx,this));
00395 OP.ass(tn->elem(idx,this),r->elem(0,this));
00396 if(l->down)
00397 { (l->down[l->nelem]=r->down[0]);
00398 r->_DEL_L(0,this); }
00399 else r->_DELLeaf(0,this);
00400 return(0);
00401 }
00402 } else {
00403
00404 l=tn->down[idx-1]; r=tn->down[idx];
00405 if(l->nelem>m)
00406 {
00407
00408 if(!r->down) r->_INSLeafNS(0,tn->elem(idx-1,this),this);
00409 else { r->_INS_NS(0,tn->elem(idx-1,this),l->down[l->nelem],
00410 this); }
00411 OP.ass(tn->elem(idx-1,this),l->elem(l->nelem-1,this));
00412 if(l->down) l->_DEL_R(l->nelem-1,this);
00413 else l->_DELLeaf(l->nelem-1,this);
00414 return(0);
00415 } --idx;
00416 }
00417
00418 int d=l->nelem;
00419 OP.ini(&l->elem(d++,this),tn->elem(idx,this));
00420 tn->_DEL_R(idx,this);
00421 for(int i=0; ; i++)
00422 {
00423 if(r->down) (l->down[d]=r->down[i]);
00424 if(i>=r->nelem) break;
00425 OP.ini(&l->elem(d++,this),r->elem(i,this));
00426 OP.clr(&r->elem(i,this));
00427 }
00428 l->nelem=d; _FreeNode(r); return(tn->nelem<m);
00429 }
00430
00432 inline void _HandleRootUnderflow()
00433 {
00434 if(root->nelem) return;
00435 if(!root->down) { root=_FreeNode(root); return; }
00436 Node *oroot=root; root=root->down[0]; _FreeNode(oroot);
00437 }
00438
00447 bool _MoveSmallest(Node *tn,T *ent)
00448 {
00449 if(!tn->down) { OP.ass(*ent,tn->elem(0,this));
00450 tn->_DELLeaf(0,this); return(tn->nelem<m); }
00451 if(_MoveSmallest(tn->down[0],ent))
00452 return(_HandleUnderflow(tn,0));
00453 return(0);
00454 }
00455
00464 template<typename K>int _Remove(Node *tn,const K &key,T *e)
00465 {
00466 int idx;
00467 if(tn->_LBI(key,&idx,this))
00468 {
00469 if(e) OP.ass(*e,tn->elem(idx,this));
00470 if(!tn->down)
00471 { tn->_DELLeaf(idx,this); return(tn->nelem<m ? 2 : 0); }
00472 if(_MoveSmallest(tn->down[idx+1],&tn->elem(idx,this)) &&
00473 _HandleUnderflow(tn,idx+1)) return(2);
00474 return(0);
00475 }
00476 if(!tn->down) return(1);
00477 int rv=_Remove(tn->down[idx],key,e); if(rv!=2) return(rv);
00478 return(_HandleUnderflow(tn,idx) ? 2 : 0);
00479 }
00480
00482 int _RemoveSL(Node *tn,int sl,T *e)
00483 {
00484 if(tn->down)
00485 {
00486 int idx = sl<0 ? 0 : tn->nelem;
00487 int rv=_RemoveSL(tn->down[idx],sl,e); if(rv!=2) return(rv);
00488 return(_HandleUnderflow(tn,idx) ? 2 : 0);
00489 }
00490 int idx = sl<0 ? 0 : (tn->nelem-1);
00491 if(e) OP.ass(*e,tn->elem(idx,this));
00492 tn->_DELLeaf(idx,this); return(tn->nelem<m ? 2 : 0);
00493 }
00494
00496 int _DoRemoveSL(int sl,T *e)
00497 {
00498 if(!root) return(1);
00499 int rv=_RemoveSL(root,sl,e); if(rv!=2) return(rv);
00500 _HandleRootUnderflow(); return(0);
00501 }
00502
00503 #if TLIB_DEBUG_BTREE
00504
00505 int _CheckTree(Node *tn)
00506 {
00507 int nerr=0;
00508
00509 TLBT_ASSERT(tn->nelem<=m+m);
00510 TLBT_ASSERT(tn==root || tn->nelem>=m);
00511
00512 for(int i=1; i<tn->nelem; i++)
00513 TLBT_ASSERT(OP.lt(tn->elem(i-1,this),tn->elem(i,this)));
00514 if(tn->down) for(int i=0,e=m+m; i<=e; i++)
00515 {
00516 Node *d=tn->down[i];
00517 if(i>tn->nelem)
00518 {
00519 TLBT_ASSERT(!d); continue; }
00520 TLBT_ASSERT(d);
00521
00522 if(i>0) TLBT_ASSERT(OP.lt(tn->elem(i-1,this),d->elem(0,this)));
00523 nerr+=_CheckTree(tn->down[i]);
00524 if(i<tn->nelem)
00525 TLBT_ASSERT(OP.lt(d->elem(d->nelem-1,this),tn->elem(i,this)));
00526 }
00527 return(nerr);
00528 }
00529 #endif
00530
00532 size_t _CountElements(Node *tn) const
00533 {
00534 size_t c=tn->nelem;
00535 if(tn->down) for(int i=0; i<=tn->nelem; i++)
00536 c+=_CountElements(tn->down[i]);
00537 return(c);
00538 }
00539
00541 size_t _CountNodes(Node *tn) const
00542 {
00543 size_t c=1;
00544 if(tn->down) for(int i=0; i<=tn->nelem; i++)
00545 c+=_CountNodes(tn->down[i]);
00546 return(c);
00547 }
00548
00550 TLBTree(const TLBTree &);
00551 void operator=(const TLBTree &);
00552 public:
00561 TLBTree(int _m=16,const _OP &op=_OP()) :
00562 m(_m<2 ? 2 : _m),root(NULL),tmp(),OP(op) {}
00564 ~TLBTree() { _DeleteTree(root); root=NULL; }
00565
00567 inline void clear()
00568 { _DeleteTree(root); root=NULL; }
00569
00571 inline bool IsEmpty() const
00572 { return(!root); }
00573
00579 inline size_t CountElements() const
00580 { return(root ? _CountElements(root) : 0); }
00581
00583 inline size_t CountNodes() const
00584 { return(root ? _CountNodes(root) : 0); }
00585
00589 inline size_t GetNodeSize() const
00590 { return(sizeof(Node)+OP.size()*(m+m)); }
00591
00601 template<typename K>inline T *search(const K &key)
00602 { return(root ? _Find(key,root) : NULL); }
00603
00614 template<typename K>T *SearchNeighbours(const K &key,T **prev,T **next)
00615 {
00616 if(prev) *prev=NULL; if(next) *next=NULL;
00617 return(root ? _FindNeighbours(key,root,prev,next) : NULL);
00618 }
00619
00625 inline T *GetSmallest()
00626 { return(root ? _FindSmallest(root) : NULL); }
00627 inline T *GetLargest()
00628 { return(root ? _FindLargest(root) : NULL); }
00629
00648 int store(const T &e,bool allow_update,T *oldval=NULL)
00649 {
00650 if(!root)
00651 {
00652 root=_AllocLeaf();
00653 OP.ini(&root->elem(0,this),e); root->nelem=1; return(0);
00654 }
00655 Node *split; int rv=_Store(root,e,&split,allow_update,oldval);
00656 if(rv!=3) return(rv);
00657
00658 Node *nroot=_AllocNonLeaf();
00659 nroot->down[0]=split;
00660 nroot->down[1]=root;
00661 OP.ini(&nroot->elem(0,this),tmp); OP.clr(&tmp);
00662 nroot->nelem=1; root=nroot; return(0);
00663 }
00664
00677 template<typename K>int remove(const K &key,T *e=NULL)
00678 {
00679 if(!root) return(1);
00680 int rv=_Remove(root,key,e); if(rv!=2) return(rv);
00681 _HandleRootUnderflow(); return(0);
00682 }
00683
00694 inline int RemoveSmallest(T *e=NULL)
00695 { return(_DoRemoveSL(-1,e)); }
00696 inline int RemoveLargest(T *e=NULL)
00697 { return(_DoRemoveSL(+1,e)); }
00698
00699 #if TLIB_DEBUG_BTREE
00702 void DumpTree(FILE *f,Node *tn=NULL,int lvl=0)
00703 {
00704 if(!tn && !lvl) tn=root; if(!tn) return;
00705 for(int i=0; i<tn->nelem; i++)
00706 {
00707 if(tn->down) DumpTree(f,tn->down[i],lvl+1);
00708 for(int j=0; j<lvl; j++) fprintf(f," ");
00709 fprintf(f,"%d\n",tn->elem(i,this));
00710 }
00711 if(tn->down) DumpTree(f,tn->down[tn->nelem],lvl+1);
00712 }
00713
00716 int CheckTree()
00717 {
00718 if(!root) return(0);
00719 int nerr=0;
00720 return(nerr+_CheckTree(root));
00721 }
00722 #endif
00723 };
00724
00725 #if TLIB_DEBUG_BTREE
00726 # undef TLBT_ASSERT
00727 #endif
00728
00729 #endif