Documentos de Académico
Documentos de Profesional
Documentos de Cultura
Colas de prioridad
7.1. Plantillas de clases y funciones en C++ 7.2. El TAD Cola de Prioridad 7.3. El mont culo binario (heap)
Transformaci on de la clase Vector (de enteros) en una plantilla de clase. class Vector { public: typedef int TBV; explicit Vector(int cap_inicial=0) { capacidad=cap_inicial; elementos=new TBV[cap_inicial]; } ... }; template <class TBV> class Vector { public: explicit Vector(int cap_inicial=0) { capacidad=cap_inicial; elementos=new TBV[cap_inicial]; } ... }; // El resto de la denici on de la plantilla es igual que la de la clase Vector
IS13. Estructuras de datos y de la informaci on 2003/2004 4
Tras la lista de par ametros de plantilla, se da la declaraci on o denici on de la plantilla de clase, exactamente igual que una declaraci on o denici on normal de clase. Dentro de la denici on de la plantilla de clase, su nombre puede utilizarse como especicador de tipo, igual que se hacia hasta ahora con el nombre de una clase. Cada ocurrencia de Vector<TBV>. Vector dentro de su denici on es un abreviatura de
Esta abreviatura s olo puede utilizarse aqu y dentro de la denici on de sus miembros. Cuando se utiliza fuera de su denici on, se debe especicar la lista de par ametros completa: Vector<TBV>.
Cada instanciaci on de una plantilla de clase es una clase independiente Los objetos de la clase Vector<int> no tienen permiso de acceso a los miembros no p ublicos de Vector<char*>. La lista de argumentos de plantilla se separa por comas y se delimita por < y >, asoci andose los tipos y valores espec cos dados en la instanciaci on a los par ametros de plantilla por su posici on. Vector<int> es un nombre de clase, e <int> es su lista de argumentos. Una instancia de una plantilla de clase puede utilizarse en un programa donde pueda utilizarse cualquier clase, y sus objetos se declaran y usan como los de cualquier clase. void Ordena(Vector<long> & vl) { ... } Vector<float> *pvf = new Vector<float>[100];
IS13. Estructuras de datos y de la informaci on 2003/2004 7
Plantillas de funci on Se declaran y denen igual que las plantillas de clase: template m as la lista de par ametros. Despu es se declara o dene la plantilla como una funci on normal, incluyendo el uso de los par ametros de plantilla. La instanciaci on de plantillas de funci on es distinta de las de clase. En principio, no es necesario dar la lista de argumentos de plantilla, porque puede deducirse de los tipos de los argumentos de funci on. Cuando sea necesario puede darse una lista expl cita de argumentos de plantilla.
10
template <class T> int SeparaIntervalo(T* vec, int n, const T & inf, const T & sup) { int ult = -1; T tmp; for (int i=0 ; i < n ; i++) if (inf <= vec[i] && vec[i] <= sup) { ult++; tmp = vec[ult]; vec[ult] = vec[i]; vec[i] = tmp; } return(ult); } ... char vc[500]; double * vd = new double[3000]; ... int u1 = SeparaIntervalo(vc,500,g,m); int u2 = SeparaIntervalo(vd,3000,34.0945,7772.8097021); int u3 = SeparaIntervalo<double>(vd,3000,34.0945,7772.8097021);
11
Cuando se instancie Vector con un determinado tipo, como por ejemplo: struct Punto3D { double x, y, z; }; Vector<short> vec1; Vector<Punto3D> vec2; es responsabilidad del programador asegurarse de que ese tipo est e provisto del operador de salida <<, ya que es necesario en: fsal << v.elementos[i] << ", "; As , no se obtendr a error de compilaci on al escribir: cout << vec1; cout << vec2; Correcto Error: Punto3D no tiene denido <<
Si el tipo no dispone del operador de salida <<, puede instanciarse Vector, y no habr a ninguna pega mientras no se utilice el operador de salida de Vector.
IS13. Estructuras de datos y de la informaci on 2003/2004 14
template <class TBP> class Pila { public: ... private: template <class TBP> struct Nodo { TBP elem; Nodo * sig; Nodo(const TBP& e, Nodo* s) { elem = e; sig = s; } }; typedef Nodo<TBP> * Enlace; Enlace top; int talla; ... ... y debe entenderse como }; si se realizase esta asociaci on
15
Respecto a los m etodos, miembros de clase y tipos anidados de una plantilla de clase, el est andar C++ ofrece dos posibilidades: A nadir su denici on a la denici on de la plantilla de clase en el chero de cabecera. Dar su denici on en un chero de c odigo separado .c++ (igual que se hace con la denici on de los m etodos, miembros de clase y tipos anidados de una clase). Esta segunda posibilidad a un no es factible utilizarla. No est a soportada por muchos compiladores, y por algunos s olo parcialmente. Usaremos la primera forma de denici on de miembros de la plantilla de clase. Aunque ello tiene la desventaja de no encapsular los detalles de la implementaci on, tendremos la ventaja de poder compilar directamente y de la misma forma en cualquier compilador.
IS13. Estructuras de datos y de la informaci on 2003/2004 18
Cuando se dene una plantilla de clase o sus miembros, se debe tener en cuenta qu e identicadores utilizados dependen de alg un par ametro de la plantilla y cu ales no. Los nombres que no dependen de par ametros de la plantilla se resuelven al procesar la denici on de la plantilla. Los que s dependen de alg un par ametro de la plantilla se resuelven al instanciar la plantilla para alg un tipo espec co. En ambos casos, los identicadores utilizados deber an estar declarados o denidos antes de que se necesiten.
19
x, y X , x = y (x < y y < x) (y < x x < y ). CP es el conjunto de multiconjuntos nitos de elementos de X . (En un multiconjunto los elementos pueden repetirse. P.e.: {7, 4, 7, 2, 7, 4}.) Operaciones: Dados CP CP y x X :
Crear() : Devuelve . Destruir(CP ) : Elimina CP . Est aVac a(CP ) : Devuelve cierto si CP = , y falso si CP = . Longitud(CP ) : Devuelve |CP | (cardinalidad del multiconjunto).
IS13. Estructuras de datos y de la informaci on 2003/2004 23
Ejemplos: CP =Crear() {} Insertar(CP ,32) { 32 } Insertar(CP ,13) { 32, 13 } Insertar(CP ,26) { 7, 32, 26 } M nimo(CP )= 13 { 32, 13 } Insertar(CP ,7) { 7, 32, 7, 26 } Insertar(CP ,18) { 7, 18, 32, 26, 18 } M nimo(CP )= 18 { 18, 32, 26 }
25
Longitud(CP )= 5 EliminarM n(CP ) EliminarM n(CP ) { 7, 18, 32, 26, 18 } { 18, 32, 26, 18 } { 18, 32, 26 }
Otras implementaciones ofrecen costes asint oticos amortizados iguales o m as ecientes (unitarios para algunas operaciones): mont culos oblicuos y mont culos de Fibonacci.
IS13. Estructuras de datos y de la informaci on 2003/2004 27
B
2 3
C
4 5 6 11 12 13 14 7 15
D
8 16
9 17 18 19 20
10
E
21 22
A B
0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31
Dado un nodo cualquiera i, 1 i n: Su hijo izquierdo est a en 2i (si tiene; es decir, si 2i n). Su hijo derecho est a en 2i + 1 (si tiene; es decir, si 2i + 1 n). Su padre est a en i/2 (si tiene; es decir, si i > 1).
IS13. Estructuras de datos y de la informaci on 2003/2004 29
7 23 74 93 87 61 55 99
heap
IS13. Estructuras de datos y de la informaci on 2003/2004
7 15 18 36 51 20 93 55 87 61 23 74 99 36 15 51 18 20
no es heap
30
#include "errores.h" // Plantilla heap.h #include <vector> using namespace std; template <class TBH> // TBH debe tener definido el operador < class Heap { public: explicit Heap(int maxelems=1000) { maxheap=maxelems; elems=new TBH[maxheap+1]; talla=0; } ~Heap() { delete [] elems; } Heap(const Heap & der) { elems = 0; operator=(der); } Heap & operator=(const Heap & der); void Vaciar() { talla = 0; } bool EstaVacio() const { return(talla == 0); } bool EstaLleno() const { return(talla == maxheap); } int Longitud() const { return(talla); } const TBH & Minimo() const; void Insertar(const TBH & item); void EliminarMin(); void FormarHeap(const vector<TBH> & items);
31
private: TBH *elems; int talla, maxheap; void Hundir(int hueco); }; template <class TBH> Heap<TBH> & Heap<TBH>::operator=(const Heap & der) { if (this != &der) { delete [] elems; maxheap = der.maxheap; elems = new TBH[maxheap+1]; talla = der.talla; for (int i=1 ; i <= talla ; i++) elems[i] = der.elems[i]; } return(*this); }
32
t Minimo(n) = (1)
9 34 34 48 26 33 75 31 99
9 26 34 48 33 75 31 99
9 12 34 48 26 33 75 31 99
9 17 34 48 26 33 75 31 99
template <class TBH> void Heap<TBH>::Insertar(const TBH & item) { En promedio, el if (talla == maxheap) Error("Insertar"); coste de insertar talla++; es constante. int hueco; for (hueco=talla ; hueco > 1 && item < elems[hueco/2] ; hueco /= 2) elems[hueco] = elems[hueco/2]; elems[hueco] = item; } t Insertar(n) = (1), O(log n)
36
58 9
17 34 34 48
26 33 75
31 99
58 17 34 34 48 26 33 75 31 99
26 17 34 34 48 58 33 75 31 99
26 17 34 34 48 33 58 75 31 99
template <class TBH> void Heap<TBH>::EliminarMin() { if (talla == 0) Error("EliminarMin"); elems[1] = elems[talla]; talla--; Hundir(1); } t EliminarMin(n) = (1), O(log n)
40
El m etodo privado Hundir permite unicar la implementaci on de EliminarMin y FormarHeap. Ambas operaciones del heap se basan en el mismo proceso.
62 63 64 65 66 67 68 69 70 71 72 73 74 75
template <class TBH> void Heap<TBH>::Hundir(int hueco) { TBH tmp = elems[hueco]; int hijo; while (true) { hijo = hueco*2; if (hijo < talla && elems[hijo+1] < elems[hijo]) hijo++; if (hijo > talla || !(elems[hijo] < tmp)) break; elems[hueco] = elems[hijo]; hueco = hijo; } elems[hueco] = tmp; } t Hundir(n) = (1), O(log n)
41
87 71 47 48 34 66 34 33 61 31
87 71 9 48 34 66 34 33 61 31
87 71 9 48 34 66 34 33 61 31
87 71 9 48 34 66 34 33 61 31
87 71 9 48 34 66 34 33 31 61
87 71 9 48 66 34 34 33 31 61
87 9 47 48 66 34 34 33 31 61
87 9 47 48 66 34 34 33 31 61
31 9 47 48 66 34 34 87 33 61
31 47 71 48 66 34 34 87 33 61
31 47 34 48 66 34 87 33 61
58 58 75 99 92
71
template <class TBH> void Heap<TBH>::FormarHeap(const vector<TBH> & items) { if (maxheap < items.size()) Error("FormarHeap"); for (talla=0 ; talla < items.size() ; talla++) elems[talla+1] = items[talla]; for (int i=talla/2 ; i > 0 ; i--) Hundir(i); } t FormarHeap(n) = (n)
48
S=
i=1
hi = 4 + 3 + 2 + 2 + 2 + 1 + 1 + 1 + 1 + 1 = 18 < 20 = n hi = 0, 11 i 20
49
Sin aprovechar la informaci on de las frecuencias, ya se obtiene ganancia al reducir a dos bits el c odigo de dos s mbolos.
IS13. Estructuras de datos y de la informaci on 2003/2004 51
D
c odigo 2
52
c odigo 1
IS13. Estructuras de datos y de la informaci on 2003/2004
C odigo ambiguo: (4, 000), (5, 001), (C, 010), (D, 011), (E, 00), (F, 01). C omo se descodica 010000? C4 = 010-000 o FEE = 01-00-00?
IS13. Estructuras de datos y de la informaci on 2003/2004 53
Este coste coincide con el n umero total de bits calculado anteriormente. Est a claro que podemos denir distintos c odigos binarios de longitud variable, para un conjunto de s mbolos, que tendr an distinto coste. Dado un conjunto de s mbolos A y sus frecuencias en un chero, podemos encontrar un arbol binario de codicaci on optimo para A, es decir, cuyo coste sea m nimo? De esta manera, obtendr amos un c odigo binario optimo que necesitar a el menor n umero total de bits para representar el chero. Este c odigo es optimo para una codicaci on del tipo s mbolo - c odigo de longitud variable (libre de prejos), dados un alfabeto y las frecuencias de sus s mbolos. Otros tipos de codicaci on pueden reducir m as el n umero de bits empleados.
IS13. Estructuras de datos y de la informaci on 2003/2004 54
Algoritmo de Human Trabaja con un bosque, que es una colecci on de arboles. Inicialmente, cada par (s mbolo,frecuencia) forma un arbol de un s olo nodo en el bosque. Iterativamente, hasta que el bosque tenga un s olo arbol: Se seleccionan los dos arboles con menor coste (da lo mismo c omo se resuelvan los empates). Se forma un nuevo arbol binario, creando un nuevo nodo ra z que contendr a: como coste la suma de los costes de los dos arboles seleccionados, y como hijos a dichos arboles (da lo mismo cu al sea el izquierdo y cu al el derecho).
IS13. Estructuras de datos y de la informaci on 2003/2004 55
Inicio:
4
8
5
22
C
25
D
23
E
15
F
7
15
Iteraci on 1:
F
7
4
8
5
22
C
25
D
23
E
15
30
Iteraci on 2:
E
15 15
F
7
4
8
5
22
C
25
D
23
56
Iteraci on 3:
E
15 15 45
F
7
4
8
5
22
D
23
C
25
55
C
25 30
Iteraci on 4:
E
15 15 45
F
7
IS13. Estructuras de datos y de la informaci on 2003/2004
4
8
5
22
D
23
57
100
55
45
Iteraci on 5:
C
25 30
5
22
D
23
E
15 15
F
7
4
8