LinkedList.h

00001 /*  _________________________________________________________________________
00002  *
00003  *  UTILIB: A utility library for developing portable C++ codes.
00004  *  Copyright (c) 2001, Sandia National Laboratories.
00005  *  This software is distributed under the GNU Lesser General Public License.
00006  *  For more information, see the README file in the top UTILIB directory.
00007  *  _________________________________________________________________________
00008  */
00009 
00010 //
00011 // LinkedList.h
00012 //
00026 #ifndef __LinkedList_h
00027 #define __LinkedList_h
00028 
00029 #ifdef __GNUC__
00030 #pragma interface
00031 #endif
00032 
00033 #ifdef NON_ANSI
00034 #include <iostream.h>
00035 #else
00036 #include <iostream>
00037 using namespace std;
00038 #endif
00039 
00040 #ifndef ANSI_HDRS
00041 #include <stdlib.h>
00042 #include <stddef.h>
00043 #else
00044 #include <cstdlib>
00045 #include <cstddef>
00046 #endif
00047 
00048 #include "errmsg.h"
00049 //#include "utilib_dll.h"
00050 #include "_generic.h"
00051 
00052 template <class T>
00053 class UTILIB_API LinkedList;
00054 
00055 
00056 
00066 template <class T>
00067 class UTILIB_API ListItem {
00068 
00069   friend class LinkedList<T>;
00070 
00071 public:
00072 
00074   ListItem( T& Data_)
00075                 : Data(Data_) {next = prev = 0;}
00076 
00078   T& data() 
00079                 {return Data;}
00081   int operator==(const ListItem<T>& item) 
00082                 {return (Data == item.Data);}
00083 
00085   static void delete_unused();
00086 
00087 protected:
00088 
00090   T Data;
00092   ListItem *next;
00094   ListItem *prev;
00095 
00097   static ListItem* unused;
00098 
00100   void *operator new(size_t);
00102   void operator delete(void*, size_t);
00103 
00104 };
00105 
00106 
00107 
00108 template <class T>
00109 class UTILIB_API LinkedList
00110 {
00111 protected:
00112 
00114   enum {
00115         stackLL = 0,    
00116         queueLL = 1     
00117         };
00118 
00119 public:
00120 
00122   LinkedList()
00123                 { mode=queueLL; counter++; first = last = 0; Len=0; }  
00124 
00130   virtual ~LinkedList();
00131 
00137   ListItem<T>* find( T& data);
00139   ListItem<T>* head() const
00140                 {return first;}
00142   ListItem<T>* tail() const
00143                 {return last;}
00145   ListItem<T>* next(ListItem<T>* item) const
00146                 {return item->next;}
00147 
00149   T& top()
00150                 {
00151                 if (Len <= 0) {
00152                    ErrAbort("LinkedList::top -- Empty list");
00153                    exit(0);
00154                    }
00155                 if (mode == queueLL) return first->data();
00156                 return last->data();
00157                 }
00159   void add( T& data)
00160                 { insert(data); }
00162   void add( T& data, ListItem<T>*& item)
00163                 { item = insert(data); }
00169   ListItem<T>* insert( T& data, ListItem<T>* item = (ListItem<T>*)0);
00170 
00172   void remove( T& data) 
00173                 {
00174                 if (mode==queueLL) 
00175                    extract(first,data); 
00176                 else
00177                    extract(last,data);
00178                 }
00180   void remove( ListItem<T>* item) 
00181                 {extract(item);}
00183   void remove(ListItem<T>* item, T& data) 
00184                 {extract(item,data);}
00185 
00187   int empty() const;
00189   operator int() const
00190                 {return (first == 0 ? FALSE : TRUE);}
00192   int size() const 
00193                 {return Len;}
00195   int len() const 
00196                 {return Len;}
00198   void stack_mode()
00199                 {mode = stackLL;}
00201   void queue_mode()
00202                 {mode = queueLL;}
00203 
00204 protected:
00205 
00207   int mode;
00209   void extract(ListItem<T>* item);
00211   void extract(ListItem<T>* item, T& data)
00212                 {data = item->Data; extract(item);}
00213 
00215   ListItem<T> *first;
00217   ListItem<T> *last;
00219   int Len;
00220 
00222   static int counter;
00223 
00224 };
00225 
00226 
00227 template <class T>
00228 inline UTILIB_API LinkedList<T>& operator>>(LinkedList<T>& list, T& data)
00229 {list.remove(data); return list;}
00230 
00231 template <class T>
00232 inline UTILIB_API LinkedList<T>& operator<<(LinkedList<T>& list, T& data)
00233 {list.add(data); return list;}
00234 
00235 
00236 
00237 //
00238 // ListItem methods
00239 //
00240 
00241 template <class T>
00242 ListItem<T> *ListItem<T>::unused = NULL;
00243 
00244 
00245 template <class T>
00246 void ListItem<T>::delete_unused()
00247 {
00248 ListItem<T> *curr = unused;
00249 ListItem<T> *next;
00250 
00251 while (curr) {
00252   next = curr->next;
00253   char* tmp = (char*) curr;
00254   delete [] tmp;
00255   curr = next;
00256   }
00257 
00258 unused=NULL;
00259 }
00260 
00261 
00262 template <class T>
00263 void* ListItem<T>::operator new(size_t size)
00264 {
00265 if (!unused)
00266    return new char[size];
00267 else {
00268    ListItem<T> *ptr = unused;
00269    unused = unused->next;
00270    return ptr;
00271    }
00272 }
00273 
00274 
00275 template <class T>
00276 void ListItem<T>::operator delete(void *p, size_t)
00277 {
00278 ((ListItem<T>*)p)->next = unused;
00279 unused = (ListItem<T>*)p;
00280 }
00281 
00282 
00283 
00284 //
00285 // LinkedList methods
00286 //
00287 
00288 template <class T>
00289 int LinkedList<T>::counter=0;
00290 
00291 
00292 template <class T>
00293 LinkedList<T>::~LinkedList()
00294 {
00295 while (!empty())
00296   extract(first);
00297 counter--;
00298 
00299 if (!counter)
00300    ListItem<T>::delete_unused();
00301 }
00302 
00303 
00304 template <class T>
00305 int LinkedList<T>::empty() const
00306 {
00307 return (first == NULL ? TRUE : FALSE) ;
00308 }
00309 
00310 
00311 template <class T>
00312 void LinkedList<T>::extract(ListItem<T>* item)
00313 {
00314 if (empty())
00315    ErrAbort("LinkedList<T>::extract : empty list");
00316 
00317 if (item->prev) 
00318    item->prev->next = item->next;
00319 else
00320    first = item->next;
00321 
00322 if (item->next)
00323    item->next->prev = item->prev;
00324 else
00325    last = item->prev;
00326 
00327 delete item;
00328 Len--;
00329 }
00330 
00331 
00332 template <class T>
00333 ListItem<T>* LinkedList<T>::insert( T& data, ListItem<T>* next)
00334 {
00335 ListItem<T>* item = new ListItem<T>(data);
00336 
00337 if (next) {
00338    if (next->prev)
00339       next->prev->next = item;
00340    else
00341       first = item;
00342    item->next = next;
00343    item->prev = next->prev;
00344    next->prev = item;
00345    }
00346 else {                  // appending to end of list 
00347    if (last) {
00348       last->next = item;
00349       item->prev = last;
00350       last = item;
00351       }
00352    else
00353       first = last = item;
00354    }
00355 
00356 Len++;
00357 return item;
00358 }
00359 
00360 
00361 template <class T>
00362 ListItem<T>* LinkedList<T>::find( T& data)
00363 {
00364 ListItem<T>* curr = first;
00365 
00366 while (curr) {
00367   if (data == curr->data()) break;
00368   curr = curr->next;
00369   }
00370 
00371 return curr;
00372 }
00373 #endif