Guest User

lista.h

a guest
May 21st, 2010
359
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C++ 6.88 KB | None | 0 0
  1. /* Por Martín Miguel y Federico Lebrón */
  2. #ifndef __LISTA_H__
  3. #define __LISTA_H__
  4.  
  5. #include <iostream>
  6. #include <cassert>
  7. using namespace std;
  8.  
  9. //se puede asumir que el tipo T tiene constructor por copia
  10. //no se puede asumir que el tipo T tenga operator=
  11. template<class T>
  12. class Lista {
  13. public:
  14.     /*constructor por defecto, crea una lista vacia*/
  15.     Lista();
  16.  
  17.     /*constructor por copia, una vez copiada, ambas listas deben ser
  18.      *independientes, es decir, cuando se borre una no debe morir la otra.
  19.      *El cursor de la lista otra no debe cambiar de posición, mientras que
  20.      *el cursor de la lista creada *DEBE* apuntar al primer elemento de la
  21.      *lista (o a NULL si la lista es vacia)*/
  22.     Lista(const Lista& otra);
  23.  
  24.     /*Constructor que genera una lista con n copias del elemento e.
  25.      *El cursor debe apuntar al primer elemento.*/
  26.     Lista(int n, const T& e);
  27.  
  28.     /*Destructor. Acordarse de liberar toda la memoria!*/
  29.     ~Lista();
  30.  
  31.     /*Dice cuantos elementos tiene la lista. No modifica el cursor!*/
  32.     int tamanio() const;
  33.  
  34.     /*Dice si la lista es vacia. Esta funcion debe ser muy rapida.*/
  35.     bool esVacia() const;
  36.  
  37.     /*Muestra la lista en formato [e1,e2,...,en] por el stream que recibe
  38.      *como parametro. La lista vacia se muestra como [] y una lista
  39.      *con un solo elemento e como [e].
  40.      *No puede modificar el cursor.*/
  41.     void mostrarLista(ostream&) const;
  42.  
  43.     /**********************
  44.      * Manejo del CURSOR  *
  45.      **********************/
  46.     /*Mueve el cursor para que apunte al primer elemento.  Si la lista
  47.      *es vacia, no hace nada*/
  48.     void retrocederCursorAlInicio() const;
  49.  
  50.     /*mueve el cursor para que apunte al ultimo elemento. Si la lista
  51.      *es vacia, no hace nada.*/
  52.     void avanzarCursorAlFinal() const;
  53.  
  54.     /*avanza el cursor al elemento siguiente.  Si no hay mas elementos
  55.      *adelante o la lista es vacia, entonces no hace nada.*/
  56.     void avanzarCursor() const;
  57.  
  58.     /*retrocede el cursor al elemento anterior.  Si no hay mas elementos
  59.      *atras o la lista es vacia, entonces no hace nada.*/
  60.     void retrocederCursor() const;
  61.  
  62.     /*devuelve el valor en la posicion apuntada por el cursor.
  63.      *PRE: la lista no es vacia.*/
  64.     const T& actual() const;
  65.  
  66.     /*devuelve el valor en la posicion apuntada por el cursor.
  67.      *PRE: la lista no es vacia.*/
  68.     T& actual();
  69.  
  70.     /*agrega un elemento en la posicion siguiente al cursor.
  71.      *El cursor no cambia de posicion.*/
  72.     void insertarAtrasDelCursor(const T& elem);
  73.  
  74.     /*agrega un elemento en la posicion siguiente al cursor.
  75.      *El cursor no cambia de posicion.*/
  76.     void insertarAdelanteDelCursor(const T& elem);
  77.  
  78.     /*elimina el elemento apuntado por el cursor.
  79.      *Si el elemento eliminado es el ultimo, entonces el cursor debe
  80.      *apuntar al ultimo elemento de la lista modificada.  En caso
  81.      *contrario, el cursor debe apuntar al elemento que le sigue al cursor.*/
  82.     void eliminarCursor();
  83.  
  84. private:
  85.     //No se puede modificar esta funcion.
  86.     Lista<T>& operator=(const Lista<T>& lista) {
  87.         assert(false);
  88.     }
  89.  
  90.     //Aca va la implementacion del nodo.
  91.     template<typename T2>struct Nodo {
  92.         Nodo* next;
  93.         Nodo* prev;
  94.         T2 value;
  95.         Nodo(T2 &elem) :value(elem) {
  96.             next = next = NULL;
  97.         }
  98.        
  99.         Nodo(const T2 &elem) :value(elem) {
  100.             prev = next = NULL;
  101.         }
  102.     };
  103.  
  104.     mutable Nodo<T>* cursor;
  105.     Nodo<T>* first;
  106.     Nodo<T>* last;
  107.  
  108.     unsigned int length;
  109.  
  110.     void borrarNodos(Nodo<T>* n);
  111.     void copiarNodos(Nodo<T>* next);
  112. };
  113.  
  114. // O(l.length)
  115. template<class T>
  116. ostream& operator<<(ostream& out, const Lista<T>& l) {
  117.     l.mostrarLista(out);
  118.     return out;
  119. }
  120.  
  121. // O(1)
  122. template<typename T> Lista<T>::Lista() {
  123.     length = 0;
  124.     cursor = first = last = NULL;
  125. }
  126.  
  127. template<typename T> void Lista<T>::copiarNodos(Nodo<T>* next) {
  128.     if(!next) return;
  129.     insertarAtrasDelCursor(next->value);
  130.     cursor = last;
  131.     copiarNodos(next->next);
  132. }
  133.  
  134. // O(otra.length), asumiendo el constructor por copia de T es O(1)
  135. template<typename T> Lista<T>::Lista(const Lista& otra) {
  136.     cursor = first = last = NULL;
  137.     length = 0;
  138.     if(otra.first) copiarNodos(otra.first);
  139.     cursor = first;
  140. }
  141.  
  142. // O(n)
  143. template<typename T>Lista<T>::Lista(int n, const T& e) {
  144.     length = 0;
  145.     cursor = first = last = NULL;
  146.     while(n--) {
  147.         insertarAtrasDelCursor(e);
  148.         if(!length) last = first;
  149.         length++;
  150.     }
  151.     cursor = first;
  152. }
  153.  
  154. // O(length)
  155. template<typename T>Lista<T>::~Lista() {
  156.     if(!first) return;
  157.     borrarNodos(first);
  158.     delete first;
  159. }
  160.  
  161. template<typename T>void Lista<T>::borrarNodos(Nodo<T>* n) {
  162.     if(n->next == NULL) return;
  163.     borrarNodos(n->next);
  164.     delete n->next;
  165. }
  166.  
  167. // O(1), podría ser O(length) si camináramos hasta el final
  168. template<typename T> int Lista<T>::tamanio() const {
  169.     return length;
  170. }
  171.  
  172. // O(1), podría seguir O(1) sin el length cacheado, devolviendo !first
  173. template<typename T> bool Lista<T>::esVacia() const {
  174.     return !length;
  175. }
  176.  
  177. // O(length)
  178. template<typename T> void Lista<T>::mostrarLista(ostream& os) const {
  179.     os << "[";
  180.     Nodo<T>* pie = first;
  181.     while(pie) {
  182.         os << pie->value;
  183.         if(pie = pie->next) os << ",";
  184.     }
  185.     os << "]";
  186. }
  187.  
  188. // O(1)
  189. template<typename T> void Lista<T>::retrocederCursorAlInicio() const {
  190.     if(!esVacia()) cursor = first;
  191. }
  192.  
  193. // O(1)
  194. template<typename T> void Lista<T>::avanzarCursorAlFinal() const {
  195.     if(!esVacia()) cursor = last;
  196. }
  197.  
  198. // O(1)
  199. template<typename T> void Lista<T>::avanzarCursor() const {
  200.     if (!esVacia() && cursor->next) cursor = cursor->next;
  201. }
  202.  
  203. // O(1)
  204. template<typename T> void Lista<T>::retrocederCursor() const {
  205.     if (!esVacia() && cursor->prev) cursor = cursor->prev;
  206. }
  207.  
  208. // O(1)
  209. template<typename T> const T& Lista<T>::actual() const {
  210.     return cursor->value;
  211. }
  212.  
  213. // O(1)
  214. template<typename T> T& Lista<T>::actual() {
  215.     return cursor->value;
  216. }
  217.  
  218. // O(1), asumiendo que el constructor por copia de T es O(1)
  219.  
  220. template<typename T> void Lista<T>::insertarAtrasDelCursor(const T& elem) {
  221.     Nodo<T>* n = new Nodo<T>(elem);
  222.     n->prev = cursor;
  223.     if(esVacia()) first = last = cursor = n;
  224.     else {     
  225.         if(cursor == last) last = n;
  226.         else { 
  227.             n->next = cursor->next;
  228.             cursor->next->prev = n;
  229.         }
  230.         cursor->next = n;
  231.     }  
  232.     length++;
  233. }
  234.  
  235. // O(1), asumiendo que el constructor por copia de T es O(1)
  236.  
  237. template<typename T> void Lista<T>::insertarAdelanteDelCursor(const T& elem) {
  238.     Nodo<T>* n = new Nodo<T>(elem);
  239.     n->next = cursor;
  240.     if(esVacia()) first = last = cursor = n;
  241.     else {     
  242.         if(cursor == first) first = n;
  243.         else { 
  244.             n->prev = cursor->prev;
  245.             cursor->prev->next = n;
  246.         }
  247.         cursor->prev = n;
  248.     }
  249.     length++;
  250. }
  251.  
  252. // O(1)
  253. template<typename T> void Lista<T>::eliminarCursor() {
  254.     assert(cursor && length);
  255.  
  256.     if(cursor == first) {
  257.         if(length == 1) first = last = NULL;
  258.         else {
  259.             first = first->next;
  260.             first->prev = NULL;
  261.         }
  262.     } else if(cursor == last) {
  263.         last = last->prev;
  264.         last->next = NULL;
  265.     } else {
  266.         cursor->next->prev = cursor->prev;
  267.         cursor->prev->next = cursor->next;
  268.     }
  269.    
  270.     Nodo<T>* basura = cursor;
  271.     cursor = cursor->next ? cursor->next : last;
  272.     delete basura;
  273.    
  274.     length--;
  275. }
  276.  
  277. #endif
Advertisement
Add Comment
Please, Sign In to add comment