OrderedList.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 // OrderedList.h
00012 //
00024 #ifndef __OrderedList_h
00025 #define __OrderedList_h
00026 
00027 #ifdef __GNUC__
00028 #pragma interface
00029 #endif
00030 
00031 #ifdef NON_ANSI
00032 #include <iostream.h>
00033 #else
00034 #include <iostream>
00035 using namespace std;
00036 #endif
00037 #ifndef ANSI_HDRS
00038 #include <stdlib.h>
00039 #include <stddef.h>
00040 #else
00041 #include <cstdlib>
00042 #include <cstddef>
00043 #endif
00044 
00045 #include "errmsg.h"
00046 #include "utilib_dll.h"
00047 #include "_generic.h"
00048 #include "errmsg.h"
00049 
00050 
00051 template <class T,class V>
00052 class UTILIB_API OrderedList;
00053 
00054 
00064 template <class T, class V>
00065 class UTILIB_API OrderedListItem {
00066 
00067   friend class OrderedList<T,V>;
00068 
00069 public:
00070 
00072   OrderedListItem( T Data_, V Key_) 
00073         : Data(Data_), Key(Key_) {next = prev = 0;}
00074 
00076   T& data()  {return Data;}
00078   V key() {return Key;}
00080   int operator==(const OrderedListItem<T,V>& item) 
00081         {return (Key == item.Key);}
00082 
00083 protected:
00084 
00086   T Data;
00088   V Key;
00089 
00091   OrderedListItem *next;
00093   OrderedListItem *prev;
00094 
00096   static OrderedListItem* unused;
00098   static void delete_unused();
00099 
00101   void *operator new(size_t);
00103   void operator delete(void*, size_t);
00104 };
00105 
00106 
00107 
00108 template <class T,class V>
00109 class UTILIB_API OrderedList
00110 {
00111 public:
00112 
00114   OrderedList() 
00115                 { counter++; first = last = 0; Len=0; }
00117   OrderedList(const OrderedList<T,V>& list)
00118                 { counter++; first = last = 0; Len=0; *this = list;}
00124   virtual ~OrderedList();
00125 
00127   OrderedList<T,V>& operator=(const OrderedList<T,V>& list);
00128 
00134   OrderedListItem<T,V>* find( V& key);
00136   OrderedListItem<T,V>* head() const
00137                 {return first;}
00139   OrderedListItem<T,V>* tail() const
00140                 {return last;}
00142   OrderedListItem<T,V>* next(OrderedListItem<T,V>* item) const
00143                 {return item->next;}         
00144 
00146   T& top()
00147                 {
00148                 if (Len == 0) {
00149                    ErrAbort("OrderedList::top -- Empty list");
00150                    exit(0);
00151                    }
00152                 return first->data();
00153                 }
00155   void add( T& data, V& key)
00156                 {insert(data,key);}
00158   void add( T& data, V& key, OrderedListItem<T,V>*& item ) 
00159                 {item = insert(data,key);}
00161   void remove( T& data, V& key)
00162                 {extract(first,data,key);}
00164   void remove(OrderedListItem<T,V>*& item)
00165                 {extract(item);}
00167   void remove(OrderedListItem<T,V>*& item, T& data, V& key)
00168                 {extract(item,data,key);}
00169 
00171   void update(OrderedListItem<T,V>* item, V& key);
00172 
00174   int empty() const;
00176   operator int() const 
00177                 {return (first == 0 ? FALSE : TRUE);}
00179   int len() const 
00180                 {return Len;}
00181 
00182 protected:
00183 
00185   void extract(OrderedListItem<T,V>* item, T& data, V& key)
00186                 { data = item->Data; key = item->Key; extract(item); }
00188   void extract(OrderedListItem<T,V>* item);
00189 
00191   OrderedListItem<T,V>* insert( T& data, V& key);
00193   void extract_all();
00194 
00196   OrderedListItem<T,V> *first;
00198   OrderedListItem<T,V> *last;
00199 
00201   int Len;
00202 
00204   static int counter;
00205 
00206 };
00207 
00208 
00209 
00210 
00211 //
00212 // OrderedListItem methods
00213 //
00214 
00215 template <class T,class V>
00216 OrderedListItem<T,V> *OrderedListItem<T,V>::unused = NULL;
00217 
00218 
00219 template <class T,class V>
00220 void OrderedListItem<T,V>::delete_unused()
00221 {
00222 OrderedListItem<T,V> *curr = unused;
00223 OrderedListItem<T,V> *next;
00224 
00225 while (curr) {
00226   next = curr->next;
00227   char* tmp = (char*) curr;
00228   delete [] tmp;
00229   curr = next;
00230   }
00231 
00232 unused = NULL;
00233 }
00234 
00235 
00236 template <class T,class V>
00237 void* OrderedListItem<T,V>::operator new(size_t size)
00238 {
00239 if (!unused)
00240    return new char[size];
00241 else {
00242    OrderedListItem<T,V> *ptr = unused;
00243    unused = unused->next;
00244    return ptr;
00245    }
00246 }
00247 
00248 
00249 template <class T,class V>
00250 void OrderedListItem<T,V>::operator delete(void *p, size_t)
00251 {
00252 ((OrderedListItem<T,V>*)p)->next = unused;
00253 unused = (OrderedListItem<T,V>*)p;
00254 }
00255 
00256 
00257 
00258 //
00259 // OrderedList methods
00260 //
00261 
00262 template <class T,class V>
00263 int OrderedList<T,V>::counter=0;
00264 
00265 
00266 template <class T,class V>
00267 OrderedList<T,V>::~OrderedList()
00268 {
00269 extract_all();
00270 counter--;
00271 
00272 if (!counter)
00273    OrderedListItem<T,V>::delete_unused();
00274 }
00275 
00276 
00277 template <class T,class V>
00278 void OrderedList<T,V>::extract_all()
00279 {
00280 while (!empty())
00281   extract(first);
00282 }
00283 
00284 
00285 template <class T, class V>
00286 OrderedList<T,V>& OrderedList<T,V>::operator=(const OrderedList<T,V>& list)
00287 {
00288 extract_all();
00289 OrderedListItem<T,V>* curr = list.head();
00290 
00291 while (curr) {
00292   T tdata = curr->data();
00293   V tkey  = curr->key();
00294   add(tdata,tkey);
00295   curr = list.next(curr);
00296   }
00297 return *this;
00298 }
00299 
00300 
00301 
00302 //
00303 // This is a stupid way of doing this.  I should simply update the key
00304 // value and move the 'item'.
00305 //
00306 template <class T,class V>
00307 void OrderedList<T,V>::update(OrderedListItem<T,V>* item, V& key)
00308 {
00309 insert(item->Data,key);
00310 extract(item);
00311 }
00312 
00313 
00314 template <class T,class V>
00315 int OrderedList<T,V>::empty() const
00316 {
00317 return (first == NULL ? TRUE : FALSE) ;
00318 }      
00319 
00320 
00321 template <class T,class V>
00322 void OrderedList<T,V>::extract(OrderedListItem<T,V>* item)
00323 {
00324 if (empty()) {
00325    cerr << "extract() on empty list" << endl;
00326    exit(-1);
00327    }
00328 
00329 if (item->prev) 
00330    item->prev->next = item->next;
00331 else
00332    first = item->next;
00333 
00334 if (item->next)
00335    item->next->prev = item->prev;
00336 else
00337    last = item->prev;
00338 
00339 delete item;
00340 Len--;
00341 }
00342 
00343 
00344 template <class T,class V>
00345 OrderedListItem<T,V>* OrderedList<T,V>::insert( T& data, V& key)
00346 {
00347 OrderedListItem<T,V>* item = new OrderedListItem<T,V>(data,key);
00348 
00349 OrderedListItem<T,V>* curr = last;
00350 
00351 while (curr && (item->Key < curr->Key))
00352   curr = curr->prev;
00353 
00354 if (curr) {
00355    item->prev = curr;
00356    if (curr->next)
00357       curr->next->prev = item;
00358    else
00359       last = item;
00360    item->next = curr->next;
00361    curr->next = item;
00362    }
00363 
00364 else {                  // insert at beginning of list
00365    item->prev = NULL;
00366    item->next = first;
00367    if (first)
00368       first->prev = item;
00369    first = item;
00370    if (!last) 
00371       last = item;
00372    }
00373 
00374 Len++;
00375 return item;
00376 }
00377 
00378 
00379 template <class T,class V>
00380 OrderedListItem<T,V>* OrderedList<T,V>::find( V& key)
00381 {
00382 OrderedListItem<T,V>* curr = first;
00383 
00384 while (curr) {
00385   if (key == curr->key()) break;
00386   curr = curr->next;
00387   }
00388 
00389 return curr;
00390 }          
00391 #endif