symlist.h

00001 //==========================================================================
00002 //
00003 //   symlist.h
00004 //
00005 //==========================================================================
00006 // $Id: symlist.h,v 1.17 2002/12/20 08:26:08 chris Exp $
00007 
00008 #ifndef SYMLIST_H
00009 #define SYMLIST_H
00010 
00011 #include <GTL/GTL.h> 
00012 
00013 #include <cassert>
00014 
00015 __GTL_BEGIN_NAMESPACE
00016 
00020 template <class T>
00021 struct symnode 
00022 {
00026     symnode()
00027     {
00028     }
00029 
00033     symnode(const T& n) : data(n)
00034     {
00035     }
00036 
00040     symnode* adj[2];
00041 
00045     T data;
00046 };
00047 
00051 template <class T, class Ref>
00052 struct symlist_iterator 
00053 {
00057     typedef symlist_iterator<T, Ref> self;
00058 
00062     typedef symnode<T>* linktype;
00063 
00067     symlist_iterator() : act (0)
00068     {
00069     }
00070 
00074     symlist_iterator(const self& it) : act(it.act), dir(it.dir)
00075     {
00076     }
00077 
00081     symlist_iterator(linktype _act, int _dir) : act(_act), dir(_dir)
00082     {
00083     }
00084     
00088     symlist_iterator(linktype _act, linktype _prev) :
00089         act(_act),
00090         dir (where_not (_act, _prev))
00091     {
00092     }
00093 
00097     self& operator=(const self& it)
00098     {
00099         act = it.act;
00100         dir = it.dir;
00101         return *this;
00102     }
00103 
00107     bool operator==(const self& it) const
00108     {
00109         return act == it.act;
00110     }
00111     
00115     bool operator!=(const self& it) const
00116     {
00117         return act != it.act;
00118     }
00119     
00123     Ref operator*() 
00124     {
00125         return act->data;
00126     }
00127 
00131     self& operator++();
00132 
00136     self& operator--();
00137     
00141     static int where(linktype _act, linktype _prev) 
00142     {
00143         return _prev == _act->adj[0] ? 0 : 1;
00144     }
00145 
00149     static int where_not(linktype _act, linktype _prev)
00150     {
00151         return _prev == _act->adj[1] ? 0 : 1;
00152     }
00153 
00157     void reverse()
00158     {
00159         dir = 1 - dir;
00160     }
00161         
00165     linktype& next()
00166     {
00167         return act->adj[dir];
00168     }
00169 
00173     linktype& prev()
00174     {
00175         return act->adj[1 - dir];
00176     }
00177 
00181     linktype act;
00182 
00186     int dir;
00187 };
00188 
00207 template <class T>
00208 class symlist 
00209 {
00210 public:
00214     typedef symlist_iterator<T, T&> iterator;
00215 
00219     typedef symlist_iterator<T, const T&> const_iterator;
00220 
00224     symlist()
00225     {
00226         link = new symnode<T>;
00227         link->adj[0] = link->adj[1] = link;
00228     }
00229 
00235     symlist(const symlist<T>& li);
00236 
00246     symlist<T>& operator=(const symlist<T>& li);
00247 
00251     ~symlist();
00252 
00260     bool empty() const
00261     {
00262         return link->adj[0] == link && link->adj[1] == link;
00263     }
00264 
00272     T& front()
00273     {
00274         return link->adj[0]->data;
00275     }
00276 
00284     T& back()
00285     {
00286         return link->adj[1]->data;
00287     }
00288 
00294     iterator begin()
00295     {
00296         return ++end();
00297     }
00298 
00304     iterator end()
00305     {
00306         return iterator(link, 0);
00307     }
00308 
00314     const_iterator begin() const
00315     {
00316         return ++end();
00317     }
00318 
00324     const_iterator end () const
00325     {
00326         return const_iterator (link, 0);
00327     }
00328 
00334     iterator rbegin()
00335     {
00336         return ++rend();
00337     }
00338 
00344     iterator rend()
00345     {
00346         return iterator (link, 1);
00347     }
00348 
00354     const_iterator rbegin() const
00355     {
00356         return ++rend();
00357     }
00358 
00364     const_iterator rend() const
00365     {
00366         return const_iterator(link, 1);
00367     }
00368 
00377     iterator insert (iterator pos, const T& data);
00378 
00390     void splice (iterator pos, iterator it);
00391 
00404     void splice (iterator pos, iterator it, iterator end);
00405 
00413     iterator erase (iterator pos);
00414 
00423     iterator erase (iterator it, iterator end);
00424 
00428     void attach_sublist (iterator, iterator);
00429 
00433     void detach_sublist ();
00434 
00440     void reverse ();
00441 private:
00445     symnode<T>* link;
00446 
00452     iterator _prev;
00453 
00459     iterator _next;
00460 };
00461 
00462 
00463 // Implementation Begin
00464 
00465 template <class T, class Ref>
00466 symlist_iterator<T, Ref>& symlist_iterator<T, Ref>::operator++()
00467 {
00468     symnode<T>* prev = act; 
00469     act = act->adj[dir];
00470     dir = where_not(act, prev);
00471     return *this;
00472 }
00473 
00474 
00475 template <class T, class Ref>
00476 symlist_iterator<T, Ref>& symlist_iterator<T, Ref>::operator--()
00477 {
00478     symnode<T>* prev = act;
00479     act = act->adj[1 - dir];
00480     dir = where(act, prev); 
00481     return *this;
00482 }
00483 
00484 
00485 template <class T>
00486 symlist<T>::symlist (const symlist<T>& l)
00487 {
00488     link = new symnode<T>;
00489     link->adj[0] = link->adj[1] = link;    
00490     
00491     const_iterator it = l.begin();
00492     const_iterator e = l.end();
00493 
00494     while (it != e)
00495     {
00496         insert(end(), *it);
00497         ++it;
00498     }
00499 }
00500 
00501 
00502 template <class T>
00503 symlist<T>::~symlist()
00504 {
00505     if (_next == iterator())
00506     {
00507         erase (begin(), end());
00508     }
00509     else
00510     {
00511         detach_sublist();
00512     }
00513     
00514     delete link;
00515 }
00516 
00517 
00518 template <class T>
00519 symlist<T>& symlist<T>::operator=(const symlist<T>& l) 
00520 {
00521     erase(begin(), end());
00522 
00523     const_iterator it = l.begin();
00524     const_iterator e = l.end();
00525 
00526     while (it != e)
00527     {
00528         insert(end(), *it);
00529         ++it;
00530     }
00531     
00532     return *this;
00533 }
00534 
00535 
00536 template <class T>
00537 symlist_iterator<T, T&> symlist<T>::insert(
00538     symlist_iterator<T,T&> pos,
00539     const T& ins)
00540 {
00541     iterator prev = pos;
00542     --prev;
00543     symnode<T>* n = new symnode<T>(ins);
00544     n->adj[0] = pos.act;
00545     n->adj[1] = prev.act;
00546 
00547     if (pos == prev)
00548     {
00549         pos = prev;
00550     }
00551 
00552     pos.prev() = n;
00553     prev.next() = n;
00554 
00555     return iterator(n, 0);
00556 }
00557 
00558 
00559 template <class T>
00560 void symlist<T>::splice(symlist_iterator<T, T&> pos,
00561                         symlist_iterator<T, T&> beg,
00562                         symlist_iterator<T, T&> end) 
00563 {
00564     if (beg != end)
00565     {
00566         iterator prev = beg;
00567         --prev;
00568         iterator last = end;
00569         --last;
00570 
00571         //
00572         // The following seems to be rather senseless, but it is required
00573         // since two iterator are equal, iff the point to the same element.
00574         // This implies that they might have different directions. Suppose
00575         // that prev == end is true and they have different directions,
00576         // than prev.next() and end.prev() return the same element !! Thus
00577         // the assignment prev = end corrects this, since the direction
00578         // gets copied, too.
00579         //
00580         if (prev == end)
00581         {
00582             prev = end;
00583         }
00584             
00585         prev.next() = end.act;
00586         end.prev() = prev.act;
00587 
00588         prev = pos;
00589         --prev;
00590 
00591         if (pos == prev)
00592         {
00593             pos = prev;
00594         }
00595 
00596         if (last == beg)
00597         {
00598             last = beg;
00599         }
00600         
00601         prev.next() = beg.act;
00602         beg.prev() = prev.act;
00603         pos.prev() = last.act;
00604         last.next() = pos.act;
00605     }
00606 }
00607 
00608 
00609 template <class T>
00610 void symlist<T>::splice(symlist_iterator<T,T&> pos, 
00611                         symlist_iterator<T,T&> beg)
00612 {
00613     iterator tmp = beg;
00614     ++tmp;
00615     splice(pos, beg, tmp);
00616 }
00617 
00618 
00619 template <class T>
00620 symlist_iterator<T,T&> symlist<T>::erase(symlist_iterator<T,T&> pos) 
00621 {
00622     assert (pos.act != link);
00623     iterator prev = pos;
00624     --prev;
00625     iterator next = pos;
00626     ++next;
00627     
00628     if (next == prev)
00629     {
00630         next = prev;
00631     }
00632 
00633     next.prev() = prev.act;
00634     prev.next() = next.act;
00635 
00636     delete (pos.act);
00637 
00638     return next;
00639 }
00640 
00641 template <class T>
00642 symlist_iterator<T,T&> symlist<T>::erase(symlist_iterator<T,T&> beg, 
00643                                          symlist_iterator<T,T&> end)
00644 {
00645     iterator prev = beg;
00646     --prev;
00647     iterator it = beg;
00648     symnode<T>* act;
00649 
00650     while (it != end)
00651     {
00652         assert (it.act != link);
00653         act = it.act;
00654         ++it;
00655         delete (act);
00656     }
00657 
00658     if (prev == end)
00659     {
00660         prev = end;
00661     }   
00662     
00663     end.prev() = prev.act;
00664     prev.next() = end.act;
00665    
00666     return end;
00667 }    
00668 
00669 
00670 template <class T>
00671 void symlist<T>::attach_sublist(symlist_iterator<T,T&> it, 
00672                                 symlist_iterator<T,T&> end) 
00673 { 
00674     assert (empty());
00675     iterator last = end;
00676     --last;
00677     _prev = it;
00678     --_prev;
00679     _next = end;
00680 
00681     if (it == last)
00682     {
00683         it = last;
00684     }
00685 
00686     link->adj[0] = it.act;
00687     it.prev() = link;
00688     link->adj[1] = last.act;
00689     last.next() = link;
00690 }   
00691 
00692     
00693 template <class T>
00694 void symlist<T>::detach_sublist() 
00695 {
00696     if (_next != iterator())
00697     {
00698         iterator it(begin());
00699         iterator e(end());
00700         
00701         --e;
00702         
00703         if (e == it)
00704         {
00705             e = it;
00706         }
00707 
00708         _prev.next() = it.act;
00709         it.prev() = _prev.act;
00710         _next.prev() = e.act;
00711         e.next() = _next.act;
00712         link->adj[0] = link->adj[1] = link;
00713 
00714         _next = iterator();
00715         _prev = iterator();
00716     }
00717 }
00718 
00719 
00720 template <class T>
00721 inline void symlist<T>::reverse()
00722 {
00723     symnode<T>* tmp = link->adj[0];
00724     link->adj[0] = link->adj[1];
00725     link->adj[1] = tmp;
00726 }
00727 
00728 // Implementation End
00729 
00730 __GTL_END_NAMESPACE
00731 
00732 #endif // SYMLIST_H
00733 
00734 //--------------------------------------------------------------------------
00735 //   end of file
00736 //--------------------------------------------------------------------------