Professional Documents
Culture Documents
Cuadernillo
El alumno aplicar las clases de la biblioteca estndar STL del lenguaje C++ y ser capaz de manejar las estructuras de datos dinmicas, para la elaboracin de programas utilizando la programacin orientada a objetos. L.I. Octavio Molina Aguilar 13/07/2011
INTRODUCCIN.............................................................................................................................. 3 TEMA 1 .......................................................................................................................................... 4 ANTECEDENTES. ............................................................................................................................. 4 1.1 Introduccin a la orientacin a objetos. ................................................................................ 4 1.2 Tipos de datos abstractos. .................................................................................................... 6 1.3 Definicin de estructuras de datos. ....................................................................................... 7 1.4 Colecciones genricas de datos............................................................................................. 8 1.5 Acceso directo y secuencial a los datos. .......................................................................... 9
1.6 Iteradores. .......................................................................................................................... 10 1.7 Plantillas (templates). ......................................................................................................... 11 1.8 La biblioteca STL. ................................................................................................................ 13 Preguntas de autoevaluacin. .................................................................................................. 15 TEMA 2 ........................................................................................................................................ 16 ARREGLOS. ................................................................................................................................... 16 2.1 Arreglos lineales dinmicos................................................................................................. 16 2.2 Representacin de arreglos lineales en memoria ................................................................ 18 2.3 Operaciones con arreglos. .................................................................................................. 19 2.4 Arreglos dinmicos. ............................................................................................................ 20 2.5 Punteros y arreglos de punteros. ........................................................................................ 21 2.6 La clase VECTOR. ................................................................................................................ 23 Preguntas de autoevaluacin. .................................................................................................. 25 TEMA 3 ........................................................................................................................................ 26 LISTAS. ......................................................................................................................................... 26 3.1 Definicin de lista. .............................................................................................................. 26 3.2 Asignacin de memoria a la lista. ........................................................................................ 27 3.3 La clase lista de STL. ............................................................................................................ 28 3.4 Iteradores para la clase lista................................................................................................ 29 3.5 Construccin de listas. ........................................................................................................ 32 3.6 Algoritmos genricos sobre colecciones de STL. .................................................................. 33 Preguntas de autoevaluacin. .................................................................................................. 34 TEMA 4 ........................................................................................................................................ 35 PILAS. ........................................................................................................................................... 35
4.1 Definicin de pilas. ............................................................................................................. 35 4.2 Implementacin de pilas. .................................................................................................... 36 4.3 La clase STACK de STL ......................................................................................................... 37 4.4 Iteradores para la clase Stack. ............................................................................................. 39 4.5 Construccin de Pilas. ......................................................................................................... 40 Preguntas de autoevaluacin. .................................................................................................. 42 TEMA 5 ........................................................................................................................................ 43 COLAS. ......................................................................................................................................... 43 5.1 Definicin de colas. ............................................................................................................. 43 5.2 Construccin de colas. ........................................................................................................ 44 5.3 La clase queue de STL. ........................................................................................................ 45 5.4 Iteradores para la clase Queue. .......................................................................................... 46 Preguntas de autoevaluacin. .................................................................................................. 48 TEMA 6 ........................................................................................................................................ 49 ARBOLES. ..................................................................................................................................... 49 6.1 Definicin de rbol. ............................................................................................................ 49 6.2 rboles binarios. ................................................................................................................. 51 6.3 Representacin de rboles binarios en memoria. ............................................................... 52 6.4 Recorrido de rboles........................................................................................................... 53 6.5 Arboles binarios de bsqueda. ............................................................................................ 55 6.6 Bsqueda e insercin de rboles binarios de bsqueda. ..................................................... 56 6.7 rboles degenerados. ......................................................................................................... 57 6.8 Aplicaciones de rboles. ..................................................................................................... 58 Preguntas de autoevaluacin. .................................................................................................. 59 CONCLUSIONES ............................................................................................................................ 60 BIBLIOGRAFA .............................................................................................................................. 61
INTRODUCCIN.
El ANSI define un conjunto de reglas. Cualquier compilador de C o de C++ debe cumplir esas reglas, si no, no puede considerarse un compilador de C o C++. Estas reglas definen las caractersticas de un compilador en cuanto a palabras reservadas del lenguaje, comportamiento de los elementos que lo componen, funciones externas que se incluyen, etc. Un programa escrito en ANSI C o en ANSI C++, podr compilarse con cualquier compilador que cumpla la norma ANSI. Se puede considerar como una homologacin o etiqueta de calidad de un compilador. Todos los compiladores incluyen, adems del ANSI, ciertas caractersticas no ANSI, por ejemplo libreras para grficos. Pero mientras no usemos ninguna de esas caractersticas, sabremos que nuestros programas son transportables, es decir, que podrn ejecutarse en cualquier ordenador y con cualquier sistema operativo. Junto con los compiladores de C y C++, se incluyen ciertos ficheros llamados libreras. Las libreras contienen el cdigo objeto de muchos programas que permiten hacer cosas comunes, como leer el teclado, escribir en la pantalla, manejar nmeros, realizar funciones matemticas, etc. Las libreras estn clasificadas por el tipo de trabajos que hacen, hay libreras de entrada y salida, matemticas, de manejo de memoria, de manejo de textos, etc. Hay un conjunto de libreras muy especiales, que se incluyen con todos los compiladores de C y de C++. Son las libreras ANSI o estndar. Pero tambin hay libreras no estndar, y dentro de estas las hay pblicas y comerciales. En este nos centraremos en la librera estndar STL.
TEMA 1 ANTECEDENTES.
Presentar a los alumnos las estructuras de datos bsicas y su transformacin en estructuras ms complejas. Se pretende que los alumnos puedan definir o elegir estructuras adecuadas para la resolucin de problemas especficos de la vida real apoyados en las tcnicas computacionales.
organizar los programas de forma ms efectiva. La POO permite descomponer un problema en subgrupos relacionados. Cada subgrupo pasa a ser un objeto autocontenido que contiene sus propias instrucciones y datos que le relacionan con ese objeto. De esta manera, la complejidad se reduce y el programador puede tratar programas ms largos. Todos los lenguajes de POO comparten tres caractersticas: encapsulacin, polimorfismo y herencia. La encapsulacin es el mecanismo que agrupa el cdigo y los datos que maneja y los mantiene protegidos frente a cualquier interferencia y mal uso. En un lenguaje orientado a objetos, el cdigo y los datos suelen empaquetarse de la misma forma en que se crea una caja negra autocontenida. Dentro de la caja son necesarios tanto el cdigo como los datos. Cuando el cdigo y los datos estn enlazados de esta manera, se ha creado un objeto. En otras palabras, un objeto es el dispositivo que soporta encapsulacin. Polimorfismo (del Griego, cuyo significado es muchas formas ) es la cualidad que permite que un nombre se utilice para dos o ms propsitos relacionados pero tcnicamente diferentes. El propsito del polimorfismo aplicado a la POO es permitir poder usar un nombre para especificar una clase general de acciones. Dentro de una clase general de acciones, la accin especfica a aplicar est determinada por el tipo de dato. El polimorfismo se puede aplicar tanto a funciones como a operadores, prcticamente todos los lenguajes de programacin contienen una aplicacin limitada de polimorfismo cuando se relaciona con los operadores aritmticos, por ejemplo, en C, el signo + se utiliza para aadir enteros, enteros largos, caracteres y valores reales. En estos casos, el compilador automticamente sabe qu tipo de aritmtica debe aplicar, en C++, se puede ampliar este concepto a otros tipos de datos que se definan, este tipo de polimorfismo se llama sobrecarga de operadores. La herencia es el proceso mediante el cual un objeto puede adquirir las propiedades de otro. Mas en concreto, un objeto puede heredar un conjunto general de propiedades a alas que puede aadir aquellas caractersticas que son especficamente suyas. La herencia es importante porque permite que un objeto soporte el concepto de clasificacin jerrquica. Mucha informacin se hace manejable gracias a esta clasificacin, por ejemplo, la descripcin de una casa. Una casa es parte de una clase general llamada edificio, a su vez, edificio es una parte de la clase ms general estructura, que es parte de la clase an ms general de objetos que se puede llamar obra-hombre.
1.5
Secuencial. Para acceder a un objeto se debe acceder a los objetos almacenados previamente en el archivo. El acceso secuencial exige elemento a elemento, es necesario una exploracin secuencial comenzando desde el primer elemento. Directo o Aleatorio. Se accede directamente al objeto, sin recorrer los anteriores. El acceso directo permite procesar o acceder a un elemento determinado haciendo una referencia directamente por su posicin en el soporte de almacenamiento.
1.6 Iteradores.
Un iterador es una especie de puntero utilizado por un algoritmo para recorrer los elementos almacenados en un contenedor. Dado que los distintos algoritmos necesitan recorrer los contenedores de diversas maneras para realizar diversas operaciones, y los contenedores deben ser accedidos de formas distintas, existen diferentes tipos de iteradores. Cada contenedor de la Librera Estndar puede generar un iterador con funcionalidad adecuada a la tcnica de almacenamiento que utiliza. Es precisamente el tipo de iterador requerido como argumento, lo que distingue que algoritmos STL pueden ser utilizados con cada clase de contenedor. Por ejemplo, si un contenedor solo dispone de iteradores de acceso secuencial, no pueden utilizarse con algoritmos que exijan iteradores de acceso aleatorio. Un puntero es una variable destinada a contener una direccin de memoria. Esta direccin generalmente corresponde a otra variable, decimos entonces que el puntero contiene la direccin de la variable o que apunta a sta. En el siguiente esquema suponemos que la variable puntero est cargada con el nmero 4A20. Decimos, entonces, que la direccin 0x4A20 es apuntada por el puntero.
Entre las ventajas que encontramos al usar estos elementos estn: 1) Permiten el acceso a cualquier posicin de la memoria, para ser leda o para ser escrita (en los casos en que esto sea posible). 2) Permiten la transferencia de argumentos a las funciones, de modo que puedan retener un valor nuevo, que resulta de aplicarles la funcin. 3) Permiten solicitar memoria que no fue reservada al inicio del programa. Esto es el uso de memoria dinmica. 4) Son el soporte de enlace que utilizan estructuras avanzadas de datos en memoria dinmica como las listas, pilas, colas y rboles. 5) Operan ms eficientemente en los arrays, en comparacin con el uso de subndices.
10
// Declaracin de la plantilla de funcin. template <class T> T minimo( T a, T b); En ese caso con <classT> se est indicando que se trata de una plantilla cuyo parmetro va a ser el tipo T y que tanto el valor de retorno como cada uno de los dos argumentos va a ser de este tipo de dato T. En la definicin y declaracin de la plantilla puede ser que se necesite utilizar ms de un tipo de dato e incluido algn otro parmetro constante que pueda ser utilizado en las declaraciones. Por ejemplo, si hubiera que pasar dos tipos a la plantilla, se podra escribir: // Declaracin de la plantilla de funcin con dos tipos de datos template <class T1, class T2> void combinar(T1 a, T2 b); Podra darse el caso tambin de que alguno de los argumentos o el valor de retorno fuese de un tipo de dato constante y conocido. En ese caso se indicara explcitamente como en una funcin convencional. La definicin de la plantilla de funcin es como sigue: // Definicin de la plantilla de funcin template <class T> T minimo(T a, T b) {
11
if(a <= b) return a; else return b; } Puede pensarse que las plantillas y el polimorfismo son dos utilidades que se excluyen mutuamente. Aunque es verdad que el parecido entre ambas es grande, hay tambin algunas diferencias que pueden hacer necesarias ambas caractersticas. El polimorfismo necesita punteros y su generalidad se limita a jerarquas. Recurdese que el polimorfismo se basa en que en el momento de compilacin se desconoce a qu clase de la jerarqua va a apuntar un puntero que se ha definido como puntero a la clase base. Desde este punto de vista las plantillas pueden considerarse como una ampliacin del polimorfismo. Una desventaja de las plantillas es que tienden a crear un cdigo ejecutable grande porque se crean tantas versiones de las funciones como son necesarias.
12
Tambin incluye "objetos funcin", que son generalizaciones de funciones (clases tiles por el procesamiento que realizan y no por los datos que contienen), y "adaptadores", que modifican el interfaz de ciertos contenedores e iteradores de forma puedan ser manejados ms fcilmente. Esta biblioteca es genrica en tanto sus componentes estn altamente parametrizados, ya que casi todos son patrones, lo que permite su instancia con cualquier otro tipo de objeto, lo que hace que la STL se configure como una gran herramienta para la programacin de aplicaciones en C++. Los tipos de contenedores que nos podemos encontrar en la biblioteca son los siguientes: Secuenciales: o Vectores: contienen elementos contiguos almacenados al estilo de un array o vector del lenguaje C++. o Listas: secuencias de elementos almacenados en una lista enlazada. o Deques: contenedores parecidos a los vectores, excepto que permiten inserciones y borrados en tiempo constante tanto al principio como al final. Adaptadores: o Colas: contenedores que ofrecen la funcionalidad de listas "primero en entrar, primero en salir". o Pilas: contenedores asociados a listas "primero en entrar, ltimo en salir". o Colas con prioridad: en este caso, los elementos de la cola salen de ella de acuerdo con una prioridad (que se estableci en la insercin). Asociativos. o Conjuntos de bits: contenedor para almacenar bits. o Mapas: almacenan pares "clave, objeto", es decir, almacenan objetos referidos mediante un identificador nico. o Multimapas: mapas que permiten claves duplicadas. o Conjuntos: conjuntos ordenados de objetos nicos. o Multiconjuntos: conjuntos ordenados de objetos que pueden estar duplicados.
13
Todas estas clases de objetos tienen la posibilidad de poder ser "recorridas" utilizan iteradores. Para ello, cada una de ellas tiene una subclase (o varias subclases) que nos permiten colocarnos en el primer elemento de un objeto, avanzar al siguiente elemento, ver el elemento (o modificarlo) y comprobar si ya hemos llegado hasta el final.
14
Preguntas de autoevaluacin.
15
TEMA 2 ARREGLOS.
Identificar y usar el tipo de estructura conocida como arreglo para dar solucin a necesidades de organizacin de datos que se presenten.
16
y luego se utiliza la funcin malloc (contenida en stdlib.h) para reservar memoria: nombre_de_array=(tipo_de_elemento *)malloc(tamao); donde tamao es el nmero de elementos del array por el tamao en bytes de cada elemento. La funcin malloc devuelve un puntero void, que indica la posicin del primer elemento. Antes de asignarlo a nuestro puntero, hay que convertir el puntero que devuelve el malloc al tipo de nuestro puntero (ya que no se pueden igualar punteros de distintos tipos).
17
Esto es muy importante, y hay que tener mucho cuidado, por ejemplo: int Vector[10]; Crear un array con 10 enteros a los que accederemos como Vector[0] a Vector[9]. Como subndice podremos usar cualquier expresin entera. Los arrays pueden ser inicializados en la declaracin. Ejemplos: float R[10] = {2, 32, 4.6, 2, 1, 0.5, 3, 8, 0, 12}; float S[] = {2, 32, 4.6, 2, 1, 0.5, 3, 8, 0, 12}; int N[] = {1, 2, 3, 6}; int M[][3] = { 213, 32, 32, 32, 43, 32, 3, 43, 21}; char Mensaje[] = "Error de lectura"; char Saludo[] = {'H', 'o', 'l', 'a', 0}; En estos casos no es obligatorio especificar el tamao para la primera dimensin, como ocurre en los ejemplos de las lneas 2, 3, 4, 5 y 6. En estos casos la dimensin que queda indefinida se calcula a partir del nmero de elementos en la lista de valores iniciales. En el caso 2, el nmero de elementos es 10, ya que hay diez valores en la lista. En el caso 3, ser 4. En el caso 4, ser 3, ya que hay 9 valores, y la segunda dimensin es 3: 9/3=3. Y en el caso 5, el nmero de elementos es 17, 16 caracteres ms el cero de fin de cadena.
18
19
20
Punteros a estructura Sintaxis: struct tipo_estructura * nombre_estructura; tipo_estructura es un rtulo de una estructura. nombre_estructura es el identificador del puntero.
Ejemplo: Se crea un tipo de dato estructura con el nombre fecha. Luego se declara una variable de tipo estructura-fecha con el nombre hoy, y finalmente un puntero a estructura-fecha llamado F. struct fecha { int da; int mes; int anio;
21
F todava no apunta a una direccin vlida. Hacemos que F apunte a hoy, cargndolo con la direccin de esa variable tipo estructura-fecha. F = &hoy; Observe la presencia del operador &. Es necesario no confundir una estructura con un arreglo. En el caso de las estructuras, el nombre es el identificador de la variable y representa a la variable misma, no a su direccin. Por eso usamos el operador mencionado.
22
23
Veamos un ejemplo. El siguiente programa muestra dos constructores simples: #include <iostream> #include <cassert> #include <vector> using namespace std; int main() { cout << "Demostrando los constructores ms simple del vector" << endl; vector<char> vector1, vector2(3, 'x'); assert (vector1.size() == 0); assert (vector2.size() == 3); assert (vector2[0] == 'x' && vector2[1] == 'x' && vector2[2] == 'x'); assert (vector2 == vector<char>(3, 'x') && vector2 != vector<char>(4, 'x')); cout << " --- Ok." << endl; return 0; }
24
Preguntas de autoevaluacin.
25
TEMA 3 LISTAS.
Identificar y usar el tipo de estructura conocida como lista para dar solucin a necesidades de organizacin de datos que se presenten.
En el ejemplo, cada elemento de la lista slo contiene un dato de tipo entero, pero en la prctica no hay lmite en cuanto a la complejidad de los datos a almacenar.
26
Dnde: tipoNodo es el tipo para declarar nodos. pNodo es el tipo para declarar punteros a un nodo. Lista es el tipo para declarar listas. Como puede verse, un puntero a un nodo y una lista son la misma cosa. En realidad, cualquier puntero a un nodo es una lista, cuyo primer elemento es el nodo apuntado, por ejemplo:
Es muy importante que un programa nunca pierda el valor del puntero al primer elemento, ya que si no existe ninguna copia de ese valor, y se pierde, ser imposible acceder al nodo y no podremos liberar el espacio de memoria que ocupa.
27
El contenedor de decencia LIST cuenta con una eficiente combinacin para las operaciones de insercin y eliminacin en cualquier posicin del contenedor. La clase LIST se implementa como una lista doblemente enlazada: cada nodo en una lista contiene un apuntador al nodo anterior y al nodo siguiente de esta lista. Esto permite a la clase LIST soportar iteradotes bidireccionales que permiten que el contenedor se recorra tanto hacia delante como hacia atrs. Adems de las funciones miembro de todos los contenedores de la STL y de las funciones miembro comunes de todos los contenedores de secuencia, la clase LIST cuenta con otras ocho funciones miembro: splice: elimina elementos de una estructura y los almacena en otra, utiliza distintos formatos. remove: elimina el elemento especificado de la lista. unique: elimina elementos duplicados de una lista. merge: elimina elementos de una estructura y los almacena en otra, de manera ordenada. reverse: invierte los elementos de una lista. sort: ordena los elementos de la lista. push_front: inserta un elemento en la parte frontal de la lista. pop_front: elimina un elemento de la parte frontal de la lista.
28
List::const_iterator (STL/CLR)
En esta aplicacin se declara el uso de un iterador constante y es el iterador quien se encarga de mostrar la estructura de la lista.Definir un tipo de un iterador constante para la secuencia controlada.
typedef T2 const_iterator;
Se describe un objeto de tipo no especificado T2 que servira como un iterador de acceso aleatorio constante para la secuencia controlada.
// cliext_list_const_iterator.cpp // compile with: /clr #include <cliext/list> int main() { cliext::list<wchar_t> c1; c1.push_back(L'a'); c1.push_back(L'b'); c1.push_back(L'c'); // display contents " a b c" cliext::list<wchar_t>::const_iterator cit = c1.begin(); for (; cit != c1.end(); ++cit) System::Console::Write(" {0}", *cit); System::Console::WriteLine(); return (0); }
29
List::const_reference (STL/CLR) En este ejercicio se hace uso de un tipo constante que toma el lugar del iterador para mostrar la estructura de la lista. El tipo de una constante referencia a un elemento.
typedef value_type% const_reference; // cliext_list_const_reference.cpp // compile with: /clr #include <cliext/list> int main() { cliext::list<wchar_t> c1; c1.push_back(L'a'); c1.push_back(L'b'); c1.push_back(L'c'); // display initial contents " a b c" cliext::list<wchar_t>::const_iterator cit = c1.begin(); for (; cit != c1.end(); ++cit) { // get a const reference to an element cliext::list<wchar_t>::const_reference cref = *cit; System::Console::Write(" {0}", cref); } System::Console::WriteLine(); return (0); }
abc
List::iterator (STL/CLR)
En este ejercicio el iterador es declarado pero noten como tiene acceso aleatorio directo a los elementos de la lista.El tipo de un iterador para la secuencia controlada. typedef T1 iterator; El tipo describe un objeto de tipo no especificado T1 que sirve como un iterador de acceso aleatorio para la secuencia controlada.
// cliext_list_iterator.cpp // compile with: /clr #include <cliext/list> int main() { cliext::list<wchar_t> c1; c1.push_back(L'a');
30
c1.push_back(L'b'); c1.push_back(L'c'); // display contents " a b c" cliext::list<wchar_t>::iterator it = c1.begin(); for (; it != c1.end(); ++it) System::Console::Write(" {0}", *it); System::Console::WriteLine(); // alter first element and redisplay it = c1.begin(); *it = L'x'; for (; it != c1.end(); ++it) System::Console::Write(" {0}", *it); System::Console::WriteLine(); return (0); }
Resultado:
a b c x b c
31
El proceso sigue siendo muy sencillo: 1. Hacemos que nodo->siguiente apunte a Lista. 2. Hacemos que Lista apunte a nodo.
El proceso en este caso tampoco es excesivamente complicado: 1. Necesitamos un puntero que seale al ltimo elemento de la lista. La manera de conseguirlo es empezar por el primero y avanzar hasta que el nodo que tenga como siguiente el valor NULL. 2. Hacer que nodo->siguiente sea NULL. 3. Hacer que ultimo->siguiente sea nodo.
32
33
Preguntas de autoevaluacin.
34
TEMA 4 PILAS.
Identificar y usar el tipo de estructura conocida como pila para dar solucin a necesidades de organizacin de datos que se presenten.
35
Los tipos que se definen normalmente para manejar pilas son casi los mismos que para manejar listas, tan slo se cambian algunos nombres de la siguiente manera:
Dnde: tipoNodo es el tipo para declarar nodos, evidentemente. pNodo es el tipo para declarar punteros a un nodo. Pila es el tipo para declarar pilas. As una manera grfica de ver la estructura sera:
Es evidente, a la vista del grfico, que una pila es una lista abierta. As que sigue siendo muy importante que un programa nunca pierda el valor del puntero al primer elemento, igual que pasa con las listas abiertas.
36
37
intDequePila.push( i ); intVectorPila.push( i ); intListaPila.push( i ); } // fin de instruccin for // mostrar y eliminar elementos de cada pila cout << "Sacando de intDequePila: "; sacarElementos( intDequePila ); cout << "\nSacando de intVectorPila: "; sacarElementos( intVectorPila ); cout << "\nSacando de intListaPila: "; sacarElementos( intListaPila ); cout << endl; return 0; } // fin de main // sacar elementos del objeto pila al que hace referencia stackRef template< class T > void sacarElementos( T &stackRef ) { while ( !stackRef.empty() ) { cout << stackRef.top() << ' '; // ver elemento superior stackRef.pop(); // eliminar elemento superior } // fin de instruccin while } // fin de la funcin sacarElementos
38
La forma de los programas es igual a la que ya se ha visto por lo que slo se expondr la parte inicial donde se hace referencia a la definicin de la pila.
#include <iostream> #include <stack> using namespace std; main() { stack < int> s; s.push(1); s.push(2); s.push(3); while(!s.empty()){ cout<<" s.pop(); } cout<<" "; }
" <<s.top()<<endl;
system("pause");
39
4.5Construccin de Pilas.
Supongamos que queremos construir una pila para almacenar nmeros enteros. 1. Creamos un nodo para el valor que colocaremos en la pila. 2. Hacemos que nodo->siguiente apunte a Pila. 3. Hacemos que Pila apunte a nodo.
Algoritmo de la funcin "pop": 1. Hacemos que nodo apunte al primer elemento de la pila, es decir, a Pila. 2. Asignamos a Pila la direccin del segundo nodo de la pila: Pila->siguiente. 3. Guardamos el contenido del nodo para devolverlo como retorno. 4. Liberamos la memoria asignada al primer nodo, el que queremos eliminar.
40
Tambin puede hacerse uso de clases. Las clases para pilas son versiones simplificadas de las mismas clases que usamos para listas. Para empezar, necesitaremos dos clases, una para nodo y otra para pila. Adems la clase para nodo debe ser amiga de la clase pila, ya que sta debe acceder a los miembros privados de nodo.
41
Preguntas de autoevaluacin.
42
TEMA 5 COLAS.
Identificar y usar el tipo de estructura conocida como cola para dar solucin a necesidades de organizacin de datos que se presenten.
43
El nodo tpico para construir colas es el mismo para la construccin de listas y pilas:
Los tipos que se definen normalmente para manejar colas son casi los mismos que para manejar listas y pilas, tan slo se cambian algunos nombres:
Dnde: tipoNodo es el tipo para declarar nodos. pNodo es el tipo para declarar punteros a un nodo. Cola es el tipo para declarar colas. De manera similar a las pilas, una cola se puede representar grficamente como:
Es evidente que una cola es una lista abierta. As que sigue siendo muy importante que un programa nunca pierda el valor del puntero al primer elemento, igual que pasa con las listas abiertas. Adems, debido al funcionamiento de las colas, tambin se debe mantener un puntero para el ltimo elemento de la cola, que ser el punto donde insertemos nuevos nodos. Teniendo en cuenta que las lecturas y escrituras en una cola se hacen siempre en extremos distintos, lo ms fcil ser insertar nodos por el final, a continuacin del nodo que no tiene nodo siguiente, y leerlos desde el principio, hay que recordar que leer un nodo implica eliminarlo de la cola.
44
45
Algoritmo de la funcin "leer": 1. Hacemos que nodo apunte al primer elemento de la cola, es decir a primero. 2. Asignamos a primero la direccin del segundo nodo de la cola: primero->siguiente. 3. Guardamos el contenido del nodo para devolverlo como retorno. 4. Liberamos la memoria asignada al primer nodo, el que queremos eliminar. 5. Si primero es NULL, haremos que ltimo tambin apunte a NULL, ya que la cola habr quedado vaca. int Leer(pNodo *primero, pNodo *ultimo) { pNodo nodo; /* variable auxiliar para manipular nodo */ int v; /* variable auxiliar para retorno */ /* Nodo apunta al primer elemento de la pila */ nodo = *primero;
46
if(!nodo) return 0; /* Si no hay nodos en la pila retornamos 0 */ /* Asignamos a primero la direccin del segundo nodo */ *primero = nodo->siguiente; /* Guardamos el valor de retorno */ v = nodo->valor; /* Borrar el nodo */ free(nodo); /* Si la cola qued vaca, ultimo debe ser NULL tambin*/ if(!*primero) *ultimo = NULL; return v; }
47
Preguntas de autoevaluacin.
48
TEMA 6 ARBOLES.
Identificar y usar el tipo de estructura conocida como rbol para dar solucin a necesidades de organizacin de datos que se presenten.
En relacin con nodos se pueden definir conceptos como: Nodo hijo: cualquiera de los nodos apuntados por uno de los nodos del rbol. En el ejemplo, 'L' y 'M' son hijos de 'G'. Nodo padre: nodo que contiene un puntero al nodo actual. En el ejemplo, el nodo 'A' es padre de 'B', 'C' y 'D'. En cuanto a la posicin dentro del rbol, encontramos: y y Nodo raz: nodo que no tiene padre. Este es el nodo que usaremos para referirnos al rbol. En el ejemplo, ese nodo es el 'A'. Nodo hoja: nodo que no tiene hijos. En el ejemplo hay varios: 'F', 'H', 'I', 'K', 'L', 'M', 'N' y 'O'.
49
Nodo rama: aunque esta definicin apenas la usaremos, estos son los nodos que no pertenecen a ninguna de las dos categoras anteriores. En el ejemplo: 'B', 'C', 'D', 'E', 'G' y 'J'.
Un rbol en el que en cada nodo o bien todos o ninguno de los hijos existe, se llama rbol completo. Los rboles se parecen al resto de las estructuras que hemos visto: dado un nodo cualquiera de la estructura, podemos considerarlo como una estructura independiente, es decir, un nodo cualquiera puede ser considerado como la raz de un rbol completo.
50
51
En el caso de un rbol binario con tres nodos, uno de estos ser la raz y los otros dos se dividirn entre los subrboles de la izquierda y derecha en una de las siguientes formas: 2 + 0, 1 + 1 y 0 + 2.
Como hay dos rboles binarios con dos nodos y solo un rbol vaco, en el primer caso da dos rboles binarios. El tercero tambin lo hace. En el segundo caso, los subrboles izquierdo y derecho tienen un nodo, y solo hay un rbol binario con un nodo y por eso hay uno en el segundo. As pues, en total existen cinco rboles binarios con tres nodos. Un rbol binario tiene una representacin natural en el almacenamiento de listas ligadas.
52
6.4Recorrido de rboles.
El modo evidente de moverse a travs de las ramas de un rbol es siguiendo los punteros, del mismo modo en que nos movamos a travs de las listas. Esos recorridos dependen en gran medida del tipo y propsito del rbol, pero hay ciertos recorridos que usaremos frecuentemente. Se trata de aquellos recorridos que incluyen todo el rbol. Hay tres formas de recorrer un rbol completo, y las tres se suelen implementar mediante recursividad. En los tres casos se sigue siempre a partir de cada nodo todas las ramas una por una. Supongamos que tenemos un rbol de orden tres, y queremos recorrerlo por completo. Partiremos del nodo raz: RecorrerArbol(raiz); La funcin RecorrerArbol, aplicando recursividad, ser tan sencilla como invocar de nuevo a la funcin RecorrerArbol para cada una de las ramas: void RecorrerArbol(Arbol a) { if(a == NULL) return; RecorrerArbol(a->rama[0]); RecorrerArbol(a->rama[1]); RecorrerArbol(a->rama[2]); } Lo que diferencia los distintos mtodos de recorrer el rbol no es el sistema de hacerlo, sino el momento que elegimos para procesar el valor de cada nodo con relacin a los recorridos de cada una de las ramas.
53
Pre-orden: En este tipo de recorrido, el valor del nodo se procesa antes de recorrer las ramas: void PreOrden(Arbol a) { if(a == NULL) return; Procesar(dato); RecorrerArbol(a->rama[0]); RecorrerArbol(a->rama[1]); RecorrerArbol(a->rama[2]); } Si seguimos el rbol del ejemplo en pre-orden, y el proceso de los datos es sencillamente mostrarlos por pantalla, obtendremos algo as: ABEKFCGLMDHIJNO In-orden: En este tipo de recorrido, el valor del nodo se procesa despus de recorrer la primera rama y antes de recorrer la ltima. Esto tiene ms sentido en el caso de rboles binarios, y tambin cuando existen ORDEN-1 datos, en cuyo caso procesaremos cada dato entre el recorrido de cada dos ramas (este es el caso de los rboles-b): void InOrden(Arbol a) { if(a == NULL) return; RecorrerArbol(a->rama[0]); Procesar(dato); RecorrerArbol(a->rama[1]); RecorrerArbol(a->rama[2]); } Si seguimos el rbol del ejemplo en in-orden, y el proceso de los datos es sencillamente mostrarlos por pantalla, obtendremos algo as: KEBFALGMCHDINJO
Post-orden: En este tipo de recorrido, el valor del nodo se procesa despus de recorrer todas las ramas: void PostOrden(Arbol a) { if(a == NULL) return; RecorrerArbol(a->rama[0]); RecorrerArbol(a->rama[1]); RecorrerArbol(a->rama[2]); Procesar(dato); } Si seguimos el rbol del ejemplo en post-orden, y el proceso de los datos es sencillamente mostrarlos por pantalla, obtendremos algo as: K E F B L M G C H I N O J D A
54
55
Si el valor del nodo raz es menor que el elemento que buscamos, continuaremos la
bsqueda en el rbol derecho. El valor de retorno de una funcin de bsqueda en un ABB puede ser un puntero al nodo encontrado, o NULL, si no se ha encontrado. Insertar un elemento. Para insertar un elemento nos basamos en el algoritmo de bsqueda. Si el elemento est en el rbol no lo insertaremos. Si no lo est, lo insertaremos a continuacin del ltimo nodo visitado. Para ello, se necesita un puntero auxiliar para conservar una referencia al padre del nodo raz actual. El valor inicial para ese puntero es NULL. y y Padre = NULL nodo = Raiz
y Bucle: mientras actual no sea un rbol vaco o hasta que se encuentre el elemento. o Si el valor del nodo raz es mayor que el elemento que buscamos, continuaremos
la bsqueda en el rbol izquierdo: Padre=nodo, nodo=nodo->izquierdo o Si el valor del nodo raz es menor que el elemento que buscamos, continuaremos la bsqueda en el rbol derecho: Padre=nodo, nodo=nodo->derecho. Si nodo no es NULL, el elemento est en el rbol, por lo tanto salimos. Si Padre es NULL, el rbol estaba vaco, por lo tanto, el nuevo rbol slo contendr el nuevo elemento, que ser la raz del rbol. Si el elemento es menor que el Padre, entonces insertamos el nuevo elemento como un nuevo rbol izquierdo de Padre. Si el elemento es mayor que el Padre, entonces insertamos el nuevo elemento como un nuevo rbol derecho de Padre.
y y y y
56
6.7rboles degenerados.
Los rboles binarios de bsqueda tienen un gran inconveniente. Por ejemplo, supongamos que creamos un ABB a partir de una lista de valores ordenada: 2, 4, 5, 8, 9, 12 Difcilmente podremos llamar a la estructura resultante un rbol:
Esto es lo que llamamos un rbol binario de bsqueda degenerado, y el rbol AVL, es la estructura que resuelve este problema, generando rboles de bsqueda equilibrados.
57
6.8Aplicaciones de rboles.
Un ejemplo de estructura en rbol es el sistema de directorios y ficheros de un sistema operativo. Aunque en este caso se trata de rboles con nodos de dos tipos, nodos directorio y nodos archivo, podramos considerar que los nodos hoja son archivos y los nodos rama son directorios. Otro ejemplo podra ser la tabla de contenido de un libro, por ejemplo de este mismo manual, dividido en captulos, y cada uno de ellos en subcaptulos. Aunque el libro sea algo lineal, como una lista, en el que cada captulo sigue al anterior, tambin es posible acceder a cualquier punto de l a travs de la tabla de contenido. Tambin se suelen organizar en forma de rbol los organigramas de mando en empresas o en el ejrcito, y los rboles genealgicos.
58
Preguntas de autoevaluacin.
59
CONCLUSIONES
Las estructuras de datos y algoritmos que faciliten su comprensin y desarrollo, constituyen elementos bsicos en el almacenamiento y tratamiento de la informacin. El entendimiento y conocimiento del concepto de estructuras y sus representaciones y mtodos que desembocan en el desarrollo de programas constituyen un previo indispensable para introducirse en el mbito de la programacin.
60
BIBLIOGRAFA
Como programar C++ Deitel & Deitel 4 Ed. Pearson/Prentice Hall Desarrollo de algoritmos y sus aplicaciones en Basic, Cobol y C. Guillermo Correa Uribe. 3 Ed. McGraw Hill. Estructuras de datos y algoritmos. Alfred V. Aho, John E. Hopcroft, Jeffrey D. Ullman Addison-Wesley Iberoamericana. Estructuras de datos. Algoritmos, abstraccin y objetos. Luis Joyanes Aguilar, Ignacio Zahonero Martnez. McGraw Hill. Guia de Autoenseanza C++ Herbert Schildt McGraw Hill. Manual de Estructuras dinmicas de datos. Salvador Pozo.
61