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

List.hpp

Go to the documentation of this file.
00001 
00027 // *************************************************************
00028 //
00029 //  Class List<C> for implementing lists
00030 //  990505 Manchester
00031 //  990529 Manchester: setHead, setTail and conc added
00032 //  990806 moved from KK to Sat
00033 //  990925 Uppsala: lots of modifications
00034 //  991017     Manchester: moved back to kk
00035 //  26/02/2000 Manchester, inserted into library
00036 //  14/05/2000 Dallas, function length added
00037 //  15/05/2000 Dallas, function member added
00038 //  29/05/2000 Manchester, isNonEmpty added
00039 //  01/06/2000 Manchester, second added
00040 //  04/06/2000 Manchester, remove added
00041 //  04/06/2000 Manchester, nth() added
00042 //  10/12/2000 Manchester, class Iterator added
00043 //  17/12/2000 Manchester, Iterator::reset added
00044 //  02/01/2001 Manchester, addLast added
00045 //  07/01/2001 Manchester, pop changed to return a value
00046 //  29/03/2001 Manchester, two small bugs fixed
00047 //  09/05/2001 Manchester, DelIterator introduced
00048 //  05/05/2001 Manchester, deleteNth ()
00049 //  30/05/2001 Manchester, split
00050 //  30/05/2001 Manchester, append
00051 //  04/06/2001 Manchester, DelIterator::restore
00052 //
00053 // *************************************************************
00054 
00055 
00056 #ifndef __list__
00057 #  define __list__
00058 
00059 
00060 #include "assert.hpp"
00061 #include "Memory.hpp"
00062 
00063 
00064 // *******************Class List*******************************
00065 
00066 template <class C,ClassID ID>
00067 class List
00068 #   if DEBUG_PREPRO
00069     : public Memory <ID>
00070 #   endif
00071 {
00072  public:
00073 
00074   // constructors
00075   inline
00076   List ( C head )
00077     :
00078     _head ( head ),
00079     _tail ( 0 )
00080   {
00081   } // List::List
00082 
00083   inline
00084   List ( C head, List* tail )
00085     :
00086     _head ( head ),
00087     _tail ( tail )
00088   {
00089   } // List::List
00090 
00091   inline
00092   List () {}
00093 
00094   // create empty list
00095   inline
00096   static List* empty ()  
00097   {
00098     return 0;
00099   }
00100 
00101   inline
00102   bool isEmpty () const
00103   {
00104     return this == 0;
00105   } // List::isEmpty
00106 
00107   inline
00108   bool isNonEmpty () const
00109   {
00110     return this != 0;
00111   } // List::isNonEmpty
00112 
00113   inline
00114   List* tail () const
00115   {
00116     ASS ( this != 0 );
00117 
00118     return _tail;
00119   } // List::tail
00120 
00121   inline
00122   C head () const
00123   {
00124     ASS ( this != 0 );
00125 
00126     return _head;
00127   } // List::head
00128 
00129   // second element of the list
00130   inline
00131   C second () const
00132   {
00133     ASS ( this != 0 && _tail != 0 );
00134 
00135     return _tail->_head;
00136   } // List::second
00137 
00138   void head ( C head )
00139   {
00140     ASS ( this != 0 );
00141 
00142     _head = head;
00143   } // List::head
00144 
00145 
00146   inline
00147   void tail ( List* tail )
00148   {
00149     ASS ( this != 0 );
00150 
00151     _tail = tail;
00152   } // list::tail
00153 
00154   // destruction, copying
00155   inline
00156   void destroy ()
00157   {
00158     if ( this->isEmpty ()  )
00159       return;
00160 
00161     List* current = this;
00162 
00163     for (;;) {
00164       List* next = current->tail ();
00165       delete current;
00166       if ( next->isEmpty () )
00167         return;
00168       current = next;
00169     }
00170   } // List::destroy
00171 
00172   List* copy () const
00173   {
00174     if ( isEmpty () )
00175       return empty ();
00176 
00177     List* result = new List;
00178     result->head ( head () );
00179     List* previous = result;
00180     List* rest = tail ();
00181 
00182     while ( ! rest->isEmpty () ) {
00183       List* tmp = new List;
00184       tmp->head ( rest->head () );
00185       previous->tail ( tmp );
00186       previous = tmp;
00187       rest = rest->tail ();
00188     }
00189 
00190     previous->tail ( empty () );
00191 
00192     return result;
00193   }  // List::copy
00194 
00195   List* append (List* snd) 
00196   {
00197     if ( isEmpty () )
00198       return snd;
00199 
00200     List* result = new List;
00201     result->head ( head () );
00202     List* previous = result;
00203     List* rest = tail ();
00204 
00205     while ( ! rest->isEmpty () ) {
00206       List* tmp = new List;
00207       tmp->head ( rest->head () );
00208       previous->tail ( tmp );
00209       previous = tmp;
00210       rest = rest->tail ();
00211     }
00212 
00213     previous->tail ( snd );
00214 
00215     return result;
00216   }  // List::append
00217 
00218   inline
00219   List* cons ( C elem )
00220   {
00221     return new List ( elem, this );
00222   } // List::cons
00223 
00224   inline
00225   static void push ( C elem, List* &lst )
00226   {
00227     lst = lst->cons ( elem );
00228   } // List::push
00229 
00230   inline
00231   static C pop ( List* &lst )
00232   {
00233     ASS ( lst != 0 );
00234 
00235     List* tail = lst->tail ();
00236     C result = lst->head ();
00237     delete lst;
00238     lst = tail;
00239 
00240     return result;
00241   } // List::pop
00242 
00243   // moves the top from from to to
00244   inline 
00245   static void move ( List*& from, List*& to )
00246   {
00247     List* tail = from->tail ();
00248     from->tail ( to );
00249     to = from;
00250     from = tail;
00251   } // List::move
00252 
00253   // list concatenation
00254   static List* concat( List* first, List* second )
00255   {
00256     if ( first == 0 )
00257       return second;
00258 
00259     // an optimization, not really necessary
00260     if ( second == 0 )
00261       return first;
00262 
00263     List* current = first;
00264     for (;;) {
00265       List* next = current->tail ();
00266       if ( ! next ) {
00267         current->tail ( second );
00268         return first;
00269       }
00270       current = next;
00271       next = next->tail ();
00272     }
00273   } // List::concat
00274 
00275   List* reverse ()
00276   {
00277     if ( isEmpty () )
00278       return empty ();
00279 
00280     List* result = empty ();
00281     List* lst = this;
00282 
00283     while ( ! lst->isEmpty () ) {
00284       List* tl = lst->tail ();
00285       lst->tail ( result );
00286       result = lst;
00287       lst = tl;
00288     }
00289 
00290     return result;
00291   } // List::reverse
00292 
00293   // length of the list
00294   int length () const
00295   {
00296     int len = 0;
00297 
00298     for ( const List* lst = this; ! lst->isEmpty () ; lst = lst->tail() )
00299       len ++;
00300 
00301     return len;
00302   } // List::length
00303 
00304   // C is a member of the list
00305   bool member ( C elem )
00306   {
00307     for ( List* lst = this; ! lst->isEmpty () ; lst = lst->tail() ) {
00308       if ( lst->head() == elem )
00309         return true;
00310     }
00311 
00312     return false;
00313   } // List::member
00314 
00315   // removes first occurrence of elem from the list and deletes it
00316   List* remove ( C elem )         
00317   {
00318     if ( isEmpty() )
00319       return this;
00320 
00321     if ( head() == elem ) {
00322       List* result = tail ();
00323       delete this;
00324       return result;
00325     }
00326 
00327     if ( tail()->isEmpty() )
00328       return this;
00329 
00330     List* current = this;
00331     List* next = tail ();
00332 
00333     for (;;) {
00334       if ( next->head() == elem ) { // element found
00335         current->tail ( next->tail() );
00336         delete next;
00337         return this;
00338       }
00339       current = next;
00340       next = next->tail();
00341       if ( next->isEmpty() )
00342         return this;
00343     }
00344   } // List::remove
00345   
00346   // Nth element, counting from 0
00347   C nth ( int N ) const 
00348   {     
00349     // Nth element, counting from 0
00350     ASS ( N >= 0 );
00351 
00352     const List* l = this;
00353 
00354     while ( N != 0 ) {
00355       ASS ( l->isNonEmpty() );
00356 
00357       l = l->tail ();
00358       N-- ;
00359     }
00360 
00361     return l->head();
00362   } // nth
00363 
00364   // delete nth element and return it as the result
00365   static C deleteNth ( List*& lst, int N ) 
00366   {     
00367     // Nth element, counting from 0
00368     ASS ( N >= 0 );
00369 
00370     C result;
00371     List* l = lst;
00372     ASS ( lst->isNonEmpty() );
00373 
00374     if ( N == 0 ) {
00375       result = l->head();
00376       lst = l->tail();
00377       delete l;
00378       return result;
00379     }
00380 
00381     // N != 0
00382     List* next = l->tail();
00383 
00384     while ( --N != 0 ) {
00385       l = next;
00386       next = next->tail ();
00387       ASS ( next->isNonEmpty() );
00388     }
00389     //  now next must be deleted
00390     result = next->head();
00391     l->tail (next->tail());
00392     delete next;
00393 
00394     return result;
00395   } // deleteNth
00396 
00397   // add last element
00398   List* addLast ( C elem )
00399   {
00400     if ( ! this ) 
00401       return new List (elem);
00402 
00403     // nonempty, trying to find the end
00404     List* current;
00405     for ( current = this; current->_tail; current = current->_tail )
00406       ;
00407 
00408     current->tail ( new List (elem) );
00409 
00410     return this;
00411   } // List::addLast
00412 
00413   // split into two sublists, first of the length n
00414   List* split ( int n, List*& rest )
00415   {
00416     if ( ! this ) {
00417       ASS( n == 0 );
00418       rest = empty ();
00419       return empty ();
00420     }
00421 
00422     if ( n == 0 ) {
00423       rest = empty ();
00424       return this;
00425     }
00426 
00427     List* nth = this;
00428     while ( --n > 0 ) {
00429       ASS( nth );
00430       nth = nth->_tail;
00431     }
00432     
00433     ASS( nth );
00434     rest = nth->_tail;
00435     nth->_tail = empty ();
00436     return this;
00437   } // List::split
00438 
00439   class Iterator {
00440    public:
00441     
00442     inline explicit 
00443     Iterator ( List* l ) : _lst (l) {}  // due to WC++ compiler I could not move the definition outside !
00444     inline explicit 
00445     Iterator ( const List* l ) : _lst (const_cast<List*>(l)) {}  
00446     
00447     inline 
00448     C next () 
00449       { 
00450         C result = _lst->head(); 
00451         _lst = _lst->tail();
00452         return result;
00453       }
00454     
00455     inline 
00456     bool more () const { return ! _lst->isEmpty(); }
00457 
00458     inline
00459     void reset ( List* l ) { _lst = l; }
00460 
00461    private:
00462     List* _lst;
00463   };
00464 
00465   class DelIterator {
00466    public:
00467     
00468     inline 
00469     DelIterator ( List*& l ) : 
00470       _lst ( l ),
00471       #if DEBUG_PREPRO
00472         _prev ( 0 ), // required to check the double deletion ASS
00473       #endif
00474       _cur ( 0 )
00475       {}  
00476     
00477     inline 
00478     C next () 
00479       { 
00480         if ( _cur ) { // there was an element previously returned by next()
00481           _prev = _cur;
00482           _cur = _cur->tail();
00483           ASS( _cur );
00484         }
00485         else { // result must be the first element of the list
00486           _cur = _lst;
00487         }
00488         return _cur->head();
00489       }
00490     
00491     inline 
00492     bool more () 
00493       { 
00494         if ( _cur ) { // there was an element previously returned by next()
00495           return _cur->tail() != 0;
00496         }
00497         return ! _lst->isEmpty(); 
00498       }
00499 
00500     inline
00501     void del () 
00502       {
00503         // we can only delete the element returned by next
00504         ASS( _cur ); 
00505         // check that two delete requests in row did not occur
00506         ASS( _cur != _prev ); 
00507 
00508         if ( _cur == _lst ) { // the first element must be deleted
00509           _lst = _lst->tail ();
00510           delete _cur;
00511           _cur = 0;
00512           return;
00513         }
00514 
00515         // not the first element 
00516         _prev->tail (_cur->tail());
00517         delete _cur;
00518         _cur = _prev;
00519       }
00520 
00521     // 04/06/2001
00522     void restore ( C elem ) 
00523       {
00524         if ( _cur ) { // not the first element was deleted
00525           // we use that _cur and _prev point to the same element
00526           _cur = new List (elem,_cur->tail());
00527           _prev->tail (_cur);
00528           return;
00529         }
00530         // the first element was deleted
00531         push (elem, _lst);
00532         // _cur == 0, making the state as if just one more and next were called
00533         _cur = _lst;
00534       }
00535 
00536    private:
00537     List*& _lst;
00538     List* _prev;
00539     List* _cur; // _cur is the element returned by the last next, if 0, then no next was called
00540   };
00541 
00542  protected:  // structure
00543 
00544   C _head;
00545   List* _tail;
00546 };  // class List
00547 
00548 
00549 // ******************* Class List, definitions ****************************
00550 
00551 
00552 #endif
00553 
00554 

Generated on Sat Jun 28 15:08:57 2003 for Vampire by doxygen 1.3.2