Home | Documentation | Download | Platforms | Projects | Mailing Lists | Version History
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