Main Page | Namespace List | Class Hierarchy | Alphabetical List | Class List | File List | Namespace Members | Class Members | File Members | Related Pages

/ray/src/lib/tl/linkedlist.h

Go to the documentation of this file.
00001 /*
00002  * lib/tl/linkedlist.h 
00003  * 
00004  * Complete implementation of a doubly linked list. 
00005  * List elements must be derived from LinkedListBase. 
00006  * 
00007  * Copyright (c) 2001--2004 by Wolfgang Wieser ] wwieser (a) gmx <*> de [ 
00008  * 
00009  * This file may be distributed and/or modified under the terms of the 
00010  * GNU General Public License version 2 as published by the Free Software 
00011  * Foundation. (See COPYING.GPL for details.)
00012  * 
00013  * This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
00014  * WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
00015  * 
00016  */
00017 
00018 #ifndef _TemplateLibrary_LinkedList_H_
00019 #define _TemplateLibrary_LinkedList_H_ 1
00020 
00094 #include <lib/sconfig.h>    /* MUST be first */
00095 
00096 
00102 template<typename T> struct LinkedListBase
00103 {
00104     T *prev,*next;
00105     
00106     enum _LLB_NoInit { LLB_NoInit };
00107     
00109     inline LinkedListBase()  {  prev=next=NULL;  }
00111     inline LinkedListBase(_LLB_NoInit)  { }
00113     inline ~LinkedListBase()  { }
00114 };
00115 
00116 
00117 // Ugly macro used so that we can read things more easily.
00118 #define _LLB LinkedListBase<T>
00119 
00126 template<typename T> class LinkedList
00127 {
00128     private:
00129         T *lfirst,*llast;
00130         
00132         inline LinkedList &operator=(const LinkedList &l)
00133             {  lfirst=l.lfirst;  llast=l.llast;  return(*this);  }
00134         inline LinkedList(const LinkedList &l)
00135             {  lfirst=l.lfirst;  llast=l.llast;  }
00136     public:
00138         inline LinkedList()  {  lfirst=llast=NULL;  }
00141         inline ~LinkedList()  {  }
00142         
00144         inline T *first()  const  {  return(lfirst);  }
00145         inline T *last()   const  {  return(llast);   }
00146         
00148         inline bool IsEmpty()  const  {  return(!lfirst);  }
00149         
00153         inline T *next(T *p)  const  {  return(p->_LLB::next);  }
00154         inline T *prev(T *p)  const  {  return(p->_LLB::prev);  }
00155         inline const T *next(const T *p)  const  {  return(p->_LLB::next);  }
00156         inline const T *prev(const T *p)  const  {  return(p->_LLB::prev);  }
00157         
00161         inline void AssignList(const LinkedList<T> *l)
00162             {  lfirst=l->lfirst;  llast=l->llast;  }
00163         
00165         inline void SwapList(LinkedList<T> *l)
00166             {  T *tmp=lfirst;  lfirst=l->lfirst;  l->lfirst=tmp;
00167                   tmp=llast;   llast= l->llast;   l->llast= tmp;  }
00168         
00170         inline void insert(T *p)
00171         {
00172             if(!p)  return;
00173             p->_LLB::next=lfirst;
00174             p->_LLB::prev=NULL;
00175             //if(lfirst)  lfirst->_LLB::prev=p;
00176             //else  llast=p;
00177             (lfirst ? lfirst->_LLB::prev : llast)=p;
00178             lfirst=p;
00179         }
00180         
00182         inline void append(T *p)
00183         {
00184             if(!p)  return;
00185             p->_LLB::prev=llast;
00186             p->_LLB::next=NULL;
00187             //if(llast)  llast->_LLB::next=p;
00188             //else  lfirst=p;
00189             (llast ? llast->_LLB::next : lfirst)=p;
00190             llast=p;
00191         }
00192         
00196         inline T *replace(T *newp,T *oldp)
00197         {
00198             newp->_LLB::next=oldp->_LLB::next;
00199             newp->_LLB::prev=oldp->_LLB::prev;
00200             if(lfirst==oldp)  lfirst=newp;
00201             if(llast==oldp)   llast=newp;
00202             oldp->_LLB::prev=oldp->_LLB::next=NULL;
00203             return(oldp);
00204         }
00205         
00208         inline void QueueBefore(T *p,T *where)
00209         {
00210             if(!p)  return;
00211             if(where==lfirst)
00212             {  insert(p);  return;  }
00213             p->_LLB::prev=where->_LLB::prev;
00214             where->_LLB::prev->_LLB::next=p;
00215             where->_LLB::prev=p;
00216             p->_LLB::next=where;
00217         }
00218         inline void QueueAfter(T *p,T *where)
00219         {
00220             if(!p)  return;
00221             if(where==llast)
00222             {  append(p);  return;  }
00223             p->_LLB::next=where->_LLB::next;
00224             where->_LLB::next->_LLB::prev=p;
00225             where->_LLB::next=p;
00226             p->_LLB::prev=where;
00227         }
00228         
00231         void queue(T *p,T *where,int loc)
00232         {
00233             if(loc<0)  QueueBefore(p,where);
00234             if(loc>0)  QueueAfter(p,where);
00235         }
00236         
00238         inline T *dequeue(T *p)
00239         {
00240             if(!p)  return(p);
00241             if(p==lfirst)  lfirst=lfirst->_LLB::next;
00242             else  p->_LLB::prev->_LLB::next=p->_LLB::next;
00243             if(p==llast)  llast=llast->_LLB::prev;
00244             else  p->_LLB::next->_LLB::prev=p->_LLB::prev;
00245             p->_LLB::next=p->_LLB::prev=NULL;
00246             return(p);
00247         }
00248         
00250         inline T *PopFirst()
00251         {
00252             if(!lfirst)  return(lfirst);
00253             T *p=lfirst;
00254             lfirst=lfirst->_LLB::next;
00255             if(lfirst)  lfirst->_LLB::prev=NULL;
00256             else  llast=NULL;
00257             p->_LLB::next=NULL;
00258             return(p);
00259         }
00260         inline T *PopLast()
00261         {
00262             if(!llast)  return(llast);
00263             T *p=llast;
00264             llast=llast->_LLB::prev;
00265             if(llast)  llast->_LLB::next=NULL;
00266             else  lfirst=NULL;
00267             p->_LLB::prev=NULL;
00268             return(p);
00269         }
00270         
00272         inline const T *search(const T *p)  const
00273         {
00274             for(T *i=lfirst; i; i=i->_LLB::next)
00275             {  if(i==p)  return(p);  }
00276             return(NULL);
00277         }
00279         inline const T *SearchRev(const T *p)  const
00280         {
00281             for(T *i=llast; i; i=i->_LLB::prev)
00282             {  if(i==p)  return(p);  }
00283             return(NULL);
00284         }
00285         
00287         inline int count()  const
00288         {
00289             int cnt=0;
00290             for(T *i=lfirst; i; i=i->_LLB::next,cnt++);
00291             return(cnt);
00292         }
00293         
00295         inline void clear()
00296             {  while(!IsEmpty()) delete PopFirst();  }
00297         
00310         inline void AppendList(LinkedList<T> &b)
00311         {
00312             if(b.IsEmpty()) return;
00313             
00314             b.lfirst->prev=llast;
00315             //if(llast)  llast->_LLB::next=b.first();
00316             //else  lfirst=b.first();
00317             (llast ? llast->_LLB::next : lfirst)=b.lfirst;
00318             llast=b.llast;
00319             
00320             b.lfirst=NULL;  b.llast=NULL;
00321         }
00322         
00342         inline T *MiddleNode()  const
00343         {
00344             //if(IsEmpty())  return(NULL);   <-- not needed!
00345             T *a=lfirst;
00346             for(T *b=llast; a!=b; b=b->_LLB::prev)  if((a=a->next)==b)  break;
00347             return(a);
00348         }
00349         
00368         template<typename OP>void MergeLists(
00369             LinkedList<T> &a,LinkedList<T> &b,const OP &_OP)
00370         {
00371             for(;;)
00372             {
00373                 T *af=a.lfirst;  if(!af)  {  AppendList(b);  break;  }
00374                 T *bf=b.lfirst;  if(!bf)  {  AppendList(a);  break;  }
00375                 if(_OP.le(*af,*bf))  append(a.PopFirst());
00376                 else                 append(b.PopFirst());
00377             }
00378         }
00379         
00391         template<typename OP>void MergeSort(const OP &_OP)  // recursive
00392         {
00393             if(IsEmpty())  return;
00396             // Divide: Split list. [O(n) due to MiddleNode()]
00397             T *m=MiddleNode();
00398             LinkedList<T> a,b;
00399             a.lfirst=lfirst;  a.llast=m;      m->_LLB::next=NULL;  lfirst=NULL;
00400             b.lfirst=m;       b.llast=llast;  m->_LLB::prev=NULL;  llast=NULL;
00401             // Conquer: Recursion depth O(log(n)). 
00402             a.MergeSort(_OP); b.MergeSort(_OP);
00403             // Merge: O(n). 
00404             MergeLists(a,b,_OP);
00405         }
00406 };
00407 
00408 #undef _LLB
00409 
00410 #endif /* _TemplateLibrary_LinkedList_H_ */

Generated on Sat Feb 19 22:33:46 2005 for Ray by doxygen 1.3.5