tcbpg

Untitled

Dec 8th, 2011
53
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C++ 5.15 KB | None | 0 0
  1. #ifndef ARRAYORD_H
  2. #define ARRAYORD_H
  3.  
  4. #include <cassert>
  5. #include <iostream>
  6. #include "auxiliares.hpp"
  7.  
  8. using namespace std;
  9.  
  10. /*
  11.     Modulo ArregloOrdenado
  12.     Arreglo con interfaz para insercion ordenada y busqueda en orden O(log n)
  13.  
  14.     Diferencias con el diseño:
  15.         + Se agregó dentro del módulo la funcionalidad para hacer busqueda en orden O(log n),
  16.           que en el diseño era un auxiliar del modulo Sistema.
  17.         + El arreglo es de punteros al tipo, no de referencias al tipo.
  18.           Esto es porque en C++ las referencias son inmutables y se
  19.           deseaba mantener la copia en O(1)
  20.         + La implementacion de insertar ordenado es ligeramente distinta.
  21.           Al momento de dejar el espacio necesario para que entre el nuevo elemento,
  22.           En vez de mantener dos indices e ir de izquierda a derecha, lo que se hace
  23.           es ir de derecha a izquierda intercambiando posicion sucesivas, evitando asi
  24.           necesitar mantener dos indices.
  25. */
  26.  
  27. //NOTA: El tipo T debe tener igualdad, menor o igual y copia
  28. template<typename T>
  29. class ArregloOrdenado{
  30.     public:
  31.         //Constructor
  32.         ArregloOrdenado(Nat m);
  33.         //Constructor por copia
  34.         ArregloOrdenado(const ArregloOrdenado<T> & a);     
  35.         //Destructor
  36.         ~ArregloOrdenado();
  37.         //Devuelve el tamanio del arreglo
  38.         Nat Tamanio() const;
  39.         //Devuelve el tamanio maximo del arreglo, es decir la maxima cantidad de elementos que se puede insertar.
  40.         Nat TamanioMaximo() const;
  41.         /*
  42.         Devuelve el valor correspondiente al lugar en el indice pasado por parametro.
  43.         ALIASING: El valor correspondiente se devuelve por referencia y es modificable.    
  44.         PRE: El indice tiene que ser menor o igual que la cantidad de elementos del arreglo
  45.         */     
  46.         T & operator[](Nat i) const;
  47.         /*
  48.         Inserta un elemento en el arreglo de manera que, ademas de introducirse el nuevo elemento, el arreglo siga ordenado
  49.         ALIASING: El valor correspondiente se asigna por copia.    
  50.         PRE: El tamanio actual del arreglo debe ser menor que el tamaño maximo. Es decir, tiene que haber espacio para el elemento.
  51.         */
  52.         void AgregarOrdenado(const T & e);
  53.         /*
  54.         Busca la posicion en el arreglo del valor pasado como parametro. Usa busqueda binaria por lo tanto la complejidad es O(log n)
  55.         PRE: El elemento debe estar en el arreglo.
  56.         */
  57.         Nat Buscar(const T & e) const;
  58.            
  59.     private:
  60.         //Tamaño y tamaño maximo del arreglo
  61.         Nat _tam, _tamMax;
  62.         //Arreglo de punteros a elementos del arreglo.
  63.         T** _elems;
  64. };
  65.  
  66. template<typename T>
  67. ArregloOrdenado<T>::ArregloOrdenado(Nat n){
  68.     _tam = 0;
  69.     _tamMax = n;
  70.     _elems = new T*[n];
  71. }
  72.  
  73. template<typename T>
  74. ArregloOrdenado<T>::ArregloOrdenado(const ArregloOrdenado<T> & a){
  75.     _tam = a.tamanio();
  76.     _tamMax = a.tamanioMaximo();
  77.    
  78.     //Creo el arreglo
  79.     _elems = new T*[_tam];
  80.  
  81.     //Copio cada uno de los elementos, asignandole punteros
  82.     for(Nat i = 0; i < _tam; i++)
  83.         _elems[i] = new T(a[i]);
  84. }
  85.  
  86. template<typename T>
  87. ArregloOrdenado<T>::~ArregloOrdenado(){
  88.     //Primero borro todos los elementos.
  89.     for(Nat i = 0; i < _tam; i++)
  90.         delete _elems[i];
  91.  
  92.     //Y despues el arreglo tambien.
  93.     delete [] _elems;
  94. }
  95.  
  96. template<typename T>
  97. Nat ArregloOrdenado<T>::Tamanio() const{
  98.     return _tam;
  99. }
  100.  
  101. template<typename T>
  102. Nat ArregloOrdenado<T>::TamanioMaximo() const{
  103.     return _tamMax;
  104. }
  105.  
  106. template<typename T>
  107. T & ArregloOrdenado<T>::operator[](Nat i) const{
  108.     assert(i >= 0 && i < _tam);
  109.     return *_elems[i];
  110. }
  111.  
  112. template<typename T>
  113. void ArregloOrdenado<T>::AgregarOrdenado(const T & e) {
  114.     assert(_tam < _tamMax);
  115.  
  116.     Nat i = 0;
  117.     //Primero busco en que lugar del arreglo tengo que insertarlo.
  118.     //Puesto que la complejidad es O(n) si o si, por simplicidad esta busqueda se hace de manera lineal.
  119.     while(i < _tam && e > *(_elems[i]))
  120.         i++;
  121.  
  122.     //Incremento el tamaño porque tengo un elemento mas
  123.     _tam++;
  124.    
  125.     //Muevo todos los elementos que a partir de i un lugar para adelante.
  126.     //Entonces libero el espacio donde tengo que poner el nuevo valor.
  127.     for(Nat j = _tam-1; j >= i+1; j--){
  128.         //Todas las copias aca son O(1) porque se copian punteros. 
  129.         T * temp = _elems[j];
  130.         _elems[j] = _elems[j-1];
  131.         _elems[j-1] = temp;
  132.     }
  133.  
  134.     //Ahora que el lugar esta liberado, copio el valor a agregar y lo asigno a donde tiene que ir.
  135.     _elems[i] = new T(e);
  136. }
  137.  
  138. template<typename T>
  139. Nat ArregloOrdenado<T>::Buscar(const T & e) const{
  140.     /*
  141.     Hago busqueda binaria sobre el arreglo
  142.     Inicialmente l es el extremo izquierdo y r es el extremo derecho del arreglo.
  143.     Por estar ordenados sabemos que a[l] < e
  144.     */ 
  145.  
  146.     Nat l = 0, r = _tam;
  147.     while(r-l > 1){
  148.         Nat m = (l+r)/2;
  149.  
  150.         if(e > (*_elems[m])){
  151.             //Si el elemento es mas grande que el del medio, tenemos que mirar la mitad derecha.
  152.             l = m;
  153.         }else{
  154.             //Sino, tenemos que mirar la mitad izquierda.
  155.             r = m;
  156.         }
  157.     }
  158.    
  159.     /*
  160.     Al final del ciclo se mantiene invariante que a[l] < e
  161.     Pero porque r-l = 1, a[l] es el ultimo valor tal que a[l] < e
  162.     Por lo tanto, e tiene que ser igual a a[l] o a[r]
  163.     */ 
  164.     return e == (*_elems[l]) ? l : r;
  165. }
  166.  
  167. //PARA PROPOSITOS DE DEBUGGEO.
  168. template<typename T>
  169. std::ostream & operator<<(std::ostream & out, const ArregloOrdenado<T> & a){
  170.     out << "{ ";
  171.     for(Nat i = 0; i < a.tamanio(); i++)
  172.         out << a[i] << " ";
  173.     out << "}";
  174.  
  175.     return out;
  176. }
  177.  
  178. #endif
  179.  
Advertisement
Add Comment
Please, Sign In to add comment