Home | Documentation | Download | Platforms | Projects | Mailing Lists | Version History

- Main Page
- Classes
- Files
- Related Pages

# 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 //--------------------------------------------------------------------------

University of Passau - FMI - Theoretical Computer Science

Design © 2002, 2003 Marcus Raitner, University of Passau