tpl_dynDlist.H

00001 
00002 /*
00003   This file is part of Aleph system
00004 
00005   Copyright (c) 2002, 2003, 2004, 2005, 2006
00006   UNIVERSITY LOS ANDES (ULA) Merida - REPÚBLICA BOLIVARIANA DE VENEZUELA  
00007 
00008   - Center of Studies in Microelectronics & Distributed Systems (CEMISID) 
00009   - ULA Computer Science Department
00010   - FUNDACITE Mérida - Ministerio de Ciencia y Tecnología
00011 
00012   PERMISSION TO USE, COPY, MODIFY AND DISTRIBUTE THIS SOFTWARE AND ITS
00013   DOCUMENTATION IS HEREBY GRANTED, PROVIDED THAT BOTH THE COPYRIGHT
00014   NOTICE AND THIS PERMISSION NOTICE APPEAR IN ALL COPIES OF THE
00015   SOFTWARE, DERIVATIVE WORKS OR MODIFIED VERSIONS, AND ANY PORTIONS
00016   THEREOF, AND THAT BOTH NOTICES APPEAR IN SUPPORTING DOCUMENTATION.
00017 
00018   Aleph is distributed in the hope that it will be useful, but WITHOUT
00019   ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
00020   or FITNESS FOR A PARTICULAR PURPOSE.
00021 
00022   UNIVERSIDAD DE LOS ANDES requests users of this software to return to 
00023 
00024   Leandro Leon
00025   CEMISID 
00026   Ed La Hechicera 
00027   3er piso, ala sur
00028   Facultad de Ingenieria 
00029   Universidad de Los Andes 
00030   Merida - REPÚBLICA BOLIVARIANA DE VENEZUELA    or
00031 
00032   lrleon@ula.ve
00033 
00034   any improvements or extensions that they make and grant Universidad 
00035   de Los Andes (ULA) the rights to redistribute these changes. 
00036 
00037   Aleph is (or was) granted by: 
00038   - Consejo de Desarrollo Cientifico, Humanistico, Tecnico de la ULA 
00039     (CDCHT)
00040   - Fundacite Mérida
00041 */
00042 
00043 
00044 # ifndef TPL_DYNDLIST_H
00045 # define TPL_DYNDLIST_H
00046 
00047 # include <tpl_dlist.H>
00048 
00049 using namespace Aleph;
00050 
00051 namespace Aleph {
00052 
00064     template <typename T>
00065 class DynDlist : public Dlist<T>
00066 {
00067 
00068   size_t num_elem;
00069 public:
00070 
00072   const size_t & size() const { return num_elem; }
00074   DynDlist() : num_elem(0) { /* Empty */ }
00084   void insert(const T & _data) 
00085 
00086     throw(std::exception, std::bad_alloc)
00087 
00088   {
00089     typename Dlist<T>::Node* ptr = new typename Dlist<T>::Node (_data);
00090     Dlist<T>::insert(ptr);
00091     ++num_elem;
00092   }
00093 
00103   void append(const T & _data) 
00104 
00105     throw(std::exception, std::bad_alloc)
00106 
00107   {
00108     typename Dlist<T>::Node* ptr = new typename Dlist<T>::Node (_data);
00109     Dlist<T>::append(ptr);
00110     ++num_elem;
00111   }
00127   size_t insert_list(DynDlist & list)
00128   {
00129     Dlink::insert_list(&list);
00130     num_elem += list.num_elem;
00131     list.num_elem = 0;
00132 
00133 
00134     I(list.is_empty());
00135 
00136     return num_elem;
00137   }
00138 
00154   size_t append_list(DynDlist & list)
00155   {
00156     Dlink::append_list(&list);
00157     num_elem += list.num_elem;
00158     list.num_elem = 0;
00159 
00160 
00161     I(list.is_empty());
00162 
00163     return num_elem;
00164   }
00166   T & get_first() 
00167 
00168     throw(std::exception, std::underflow_error)
00169 
00170   {
00171     return Dlist<T>::get_first()->get_data();
00172   }
00173 
00175   T & get_last() 
00176 
00177     throw(std::exception, std::underflow_error)
00178 
00179   {
00180     return Dlist<T>::get_last()->get_data();
00181   }
00188   T remove_first() 
00189 
00190     throw(std::exception, std::underflow_error)
00191 
00192   {
00193     typename Dlist<T>::Node* ptr = Dlist<T>::remove_first();
00194     T retVal = ptr->get_data();
00195     delete ptr;
00196 
00197     --num_elem;
00198 
00199     return retVal;
00200   }
00201 
00208   T remove_last() 
00209 
00210     throw(std::exception, std::underflow_error)
00211 
00212   {
00213     typename Dlist<T>::Node* ptr = Dlist<T>::remove_last();
00214     T retVal = ptr->get_data();
00215     delete ptr;
00216 
00217     --num_elem;
00218 
00219     return retVal;
00220   }
00221   void empty() 
00222   {
00223     while (not this->is_empty())
00224       {
00225         typename Dlist<T>::Node* ptr = Dlist<T>::remove_first();
00226 
00227         delete ptr;
00228       }
00229     
00230     num_elem = 0;
00231   }
00232   ~DynDlist() 
00233   { 
00234     empty();
00235   }
00244   void swap(DynDlist & l)
00245   {
00246     Aleph::swap(num_elem, l.num_elem);
00247     this->Dlink::swap(&l);
00248   }
00261   void split_list(DynDlist & l, DynDlist & r) 
00262 
00263     throw(std::exception, std::domain_error)
00264 
00265   {
00266 
00267     if ((not l.is_empty()) or (not r.is_empty()))
00268       throw std::domain_error("lists are not empty");
00269 
00270     Dlink::split_list(l, r);
00271 
00272     l.num_elem = r.num_elem = num_elem/2;
00273 
00274     if (num_elem % 2 == 1) // ¿es num_elem impar?
00275       l.num_elem++;
00276 
00277     num_elem = 0;
00278   }
00283   class Iterator : public Dlist<T>::Iterator
00284   {
00285     DynDlist * list_ptr;
00286     int pos;
00287 
00288   public:
00289 
00290 
00292     const int & get_pos() const { return pos; }
00298     const int & next()
00299     {
00300       Dlist<T>::Iterator::next();
00301       pos++;
00302 
00303       return pos;
00304     }
00305 
00311     const int & prev()
00312     {
00313       Dlist<T>::Iterator::prev();
00314       pos--;
00315 
00316       return pos;
00317     }
00318 
00323     const int & reset_first()
00324     {
00325       Dlist<T>::Iterator::reset_first();
00326       pos = 0;
00327 
00328       return pos;
00329     }
00330 
00336     const int & reset_last()
00337     {
00338       Dlist<T>::Iterator::reset_last();
00339       pos = list_ptr->num_elem - 1;
00340 
00341       return pos;
00342     }
00344     Iterator(DynDlist<T> & _list) 
00345       : Dlist<T>::Iterator(_list), list_ptr(&_list), pos(0)
00346     { /* Empty */ }
00347 
00349     Iterator(const DynDlist<T> & _list) 
00350       : Dlist<T>::Iterator(const_cast<DynDlist<T>&>(_list)), 
00351         list_ptr(&const_cast<DynDlist<T>&>(_list)), pos(0)
00352     { /* Empty */ }
00353 
00354 
00356     Iterator(const Iterator & it) 
00357       : Dlist<T>::Iterator(it), list_ptr(it.list_ptr), pos(it.pos)
00358     { /* Empty */ }
00359 
00360     Iterator() : list_ptr(NULL){ /* empty */ }
00361 
00363     Iterator & operator = (const Iterator & it) 
00364     { 
00365       Dlist<T>::Iterator::operator = (it);
00366       list_ptr = it.list_ptr;
00367       pos      = it.pos;
00368 
00369       return *this;
00370     }
00372     T & get_current() { return Dlist<T>::Iterator::get_current()->get_data(); }
00383     void insert(const T & _data) 
00384 
00385       throw(std::exception, std::overflow_error, std::bad_alloc)
00386 
00387     {
00388 
00389       if (not this->has_current())
00390         throw std::overflow_error ("DynDlist Iterator has not current");
00391 
00392       typename Dlist<T>::Node* node = new typename Dlist<T>::Node (_data);
00393       Dlist<T>::Iterator::get_current()->insert(node);
00394       ++list_ptr->num_elem;
00395     }
00396 
00407     void append(const T & _data) 
00408 
00409       throw(std::exception, std::overflow_error, std::bad_alloc)
00410 
00411     {
00412 
00413       if (not this->has_current())
00414         throw std::overflow_error ("DynDlist Iterator has not current");
00415 
00416       typename Dlist<T>::Node* node = new typename Dlist<T>::Node (_data);
00417       Dlist<T>::Iterator::get_current()->append(node);
00418       ++list_ptr->num_elem;
00419     }
00436     void insert_list(const DynDlist & list) 
00437 
00438       throw(std::exception, std::overflow_error)
00439 
00440     {
00441 
00442       if (not this->has_current())
00443         throw std::overflow_error ("DynDlist Iterator has not current");
00444 
00445       Dlist<T>::Iterator::get_current()->insert_list(&list);
00446       list_ptr->num_elem += list.num_elem;
00447       list.num_elem = 0;
00448 
00449       I(list.is_empty());
00450 
00451     }
00452 
00469     void append_list(const DynDlist & list) 
00470 
00471       throw(std::exception, std::overflow_error)
00472 
00473     {
00474 
00475       if (not this->has_current())
00476         throw std::overflow_error ("DynDlist Iterator has not current");
00477 
00478       Dlist<T>::Iterator::get_current()->append_list(&list);
00479       list_ptr->num_elem += list.num_elem;
00480       list.num_elem = 0;
00481 
00482       I(list.is_empty());
00483 
00484     }
00494     T del() 
00495 
00496       throw(std::exception, std::overflow_error)
00497 
00498     {
00499 
00500       if (not this->has_current())
00501         throw std::overflow_error ("DynDlist Iterator has not current");
00502 
00503       typename Dlist<T>::Node* ptr = Dlist<T>::Iterator::get_current(); 
00504 
00505       T ret_val = ptr->get_data(); 
00506 
00507       Dlist<T>::Iterator::next();
00508 
00509       ptr->del();
00510       delete ptr;
00511 
00512       --list_ptr->num_elem;
00513 
00514       return ret_val;
00515     }
00526     T remove_prev()
00527 
00528       throw(std::exception, std::overflow_error)
00529 
00530     {
00531 
00532       if (not this->has_current())
00533         throw std::overflow_error ("DynDlist Iterator has not current");
00534 
00535       Dnode<T> * curr_ptr = Dlist<T>::Iterator::get_current(); 
00536 
00537       Dnode<T> * ptr = curr_ptr->remove_prev();
00538 
00539       T ret_val = ptr->get_data(); 
00540 
00541       delete ptr;
00542 
00543       --list_ptr->num_elem;
00544 
00545       return ret_val;
00546     }
00547 
00558     T remove_next() 
00559 
00560       throw(std::exception, std::overflow_error)
00561 
00562     {
00563 
00564       if (not this->has_current())
00565         throw std::overflow_error ("DynDlist Iterator has not current");
00566 
00567       Dnode<T> * curr_ptr = Dlist<T>::Iterator::get_current(); 
00568 
00569       Dnode<T> * ptr = curr_ptr->remove_next();
00570 
00571       T ret_val = ptr->get_data(); 
00572 
00573       delete ptr;
00574 
00575       --list_ptr->num_elem;
00576 
00577       return ret_val;
00578     }
00600     size_t cut_list(DynDlist & list)
00601     {
00602 
00603       if (not this->has_current())
00604         throw std::overflow_error ("DynDlist Iterator has not current");
00605 
00606       list_ptr->Dlist<T>::cut_list(Dlist<T>::Iterator::get_current(), 
00607                                    &list); // cortar lista
00608 
00609       list.num_elem = list_ptr->num_elem - pos; // actualizar cardinalidad de list
00610       list_ptr->num_elem -= pos; // actualizar cardinalidad de ptr_list.
00611 
00612       return list.num_elem;
00613     }
00614   };
00623   DynDlist<T> & operator = (const DynDlist & list)
00624   {
00625 
00626     if (this == &list)
00627       return *this;
00628 
00629     while (not this->is_empty()) // vaciar this
00630       this->remove_first();
00631 
00632     
00633     I(this->is_empty());
00634 
00635     typename DynDlist<T>::Iterator itor(const_cast<DynDlist&>(list)); 
00636 
00637     while (itor.has_current())
00638     {
00639       this->append(itor.get_current()); 
00640 
00641       itor.next();
00642     }
00643 
00644     return *this;
00645   }
00647   DynDlist(const DynDlist & list) : Dlist<T>(list)
00648   {
00649     this->reset();
00650     
00651     I(this->is_empty());
00652 
00653     typename DynDlist<T>::Iterator itor(const_cast<DynDlist&>(list)); 
00654 
00655     while (itor.has_current())
00656     {
00657       this->append(itor.get_current()); 
00658 
00659       itor.next();
00660     }
00661   }
00662 };
00663 
00664 } // end namespace Aleph
00665 
00666 # endif /* TPL_DYNDLIST_H */
00667 

Leandro R. León