Estructura de datos
-
Upload
octavio-molina-aguilar -
Category
Documents
-
view
1.813 -
download
0
Transcript of Estructura de datos
5/8/2018 Estructura de datos - slidepdf.com
http://slidepdf.com/reader/full/estructura-de-datos-559abe4db4fe4 1/62
ESTRUCTURA DEDATOSCuadernillo
El alumno aplicará las clases de la biblioteca estándar STLdel lenguaje C++ y será capaz de manejar las estructurasde datos dinámicas, para la elaboración de programasutilizando la programación orientada a objetos.
L.I. Octavio Molina Aguilar
13/07/2011
5/8/2018 Estructura de datos - slidepdf.com
http://slidepdf.com/reader/full/estructura-de-datos-559abe4db4fe4 2/62
INTRODUCCIÓN. ............................................................................................................................. 3
TEMA 1 .......................................................................................................................................... 4
ANTECEDENTES. ............................................................................................................................. 4
1.1 Introducción a la orientación a objetos. ................................................................................ 4
1.2 Tipos de datos abstractos. .................................................................................................... 6
1.3 Definición de estructuras de datos. ......................... ................................ ...................... ........ 7
1.4 Colecciones genéricas 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 autoevaluación. .................................................................................................. 15TEMA 2 ........................................................................................................................................ 16
ARREGLOS. ................................................................................................................................... 16
2.1 Arreglos lineales dinámicos. .......................... ................................ ...................... ................ 16
2.2 Representación de arreglos lineales en memoria ............................ ....................... ............. 18
2.3 Operaciones con arreglos. .................................................................................................. 19
2.4 Arreglos dinámicos. ............................................................................................................ 20
2.5 Punteros y arreglos de punteros. ........................................................................................ 21
2.6 La clase VECTOR. ................................................................................................................ 23
Preguntas de autoevaluación. .................................................................................................. 25
TEMA 3 ........................................................................................................................................ 26
LISTAS. ......................................................................................................................................... 26
3.1 Definición de lista. .............................................................................................................. 26
3.2 Asignación de memoria a la lista. ........................................................................................ 27
3.3 La clase lista de STL. ............................................................................................................ 28
3.4 Iteradores para la clase lista................................................................................................ 29
3.5 Construcción de listas. ........................................................................................................ 32
3.6 Algoritmos genéricos sobre colecciones de STL. ............................... ...................... ............. 33
Preguntas de autoevaluación. .................................................................................................. 34
TEMA 4 ........................................................................................................................................ 35
PILAS. ........................................................................................................................................... 35
5/8/2018 Estructura de datos - slidepdf.com
http://slidepdf.com/reader/full/estructura-de-datos-559abe4db4fe4 3/62
4.1 Definición de pilas. ............................................................................................................. 35
4.2 Implementación de pilas. ........................ ................................ ....................... ..................... 36
4.3 La clase STACK de STL ......................................................................................................... 37
4.4 Iteradores para la clase Stack. ............................................................................................. 39
4.5 Construcción de Pilas. ......................................................................................................... 40
Preguntas de autoevaluación. .................................................................................................. 42
TEMA 5 ........................................................................................................................................ 43
COLAS. ......................................................................................................................................... 43
5.1 Definición de colas. ............................................................................................................. 43
5.2 Construcción de colas. ........................................................................................................ 44
5.3 La clase queue de STL. ........................................................................................................ 45
5.4 Iteradores para la clase Queue. .......................................................................................... 46Preguntas de autoevaluación. .................................................................................................. 48
TEMA 6 ........................................................................................................................................ 49
ARBOLES. ..................................................................................................................................... 49
6.1 Definición de árbol. ............................................................................................................ 49
6.2 Árboles binarios. ................................................................................................................. 51
6.3 Representación de árboles binarios en memoria. ............................................................... 52
6.4 Recorrido de árboles........................................................................................................... 53
6.5 Arboles binarios de búsqueda. ............................................................................................ 55
6.6 Búsqueda e inserción de árboles binarios de búsqueda. ............................................ ......... 56
6.7 Árboles degenerados. ......................................................................................................... 57
6.8 Aplicaciones de árboles. ..................................................................................................... 58
Preguntas de autoevaluación. .................................................................................................. 59
CONCLUSIONES ............................................................................................................................ 60
BIBLIOGRAFÍA .............................................................................................................................. 61
5/8/2018 Estructura de datos - slidepdf.com
http://slidepdf.com/reader/full/estructura-de-datos-559abe4db4fe4 4/62
INTRODUCCIÓN.
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 características de
un compilador en cuanto a palabras reservadas del lenguaje, comportamiento de los elementosque 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 homologación o etiqueta de calidad de un compilador.
Todos los compiladores incluyen, además del ANSI, ciertas características no ANSI, por ejemplo
librerías para gráficos. Pero mientras no usemos ninguna de esas características, sabremos que
nuestros programas son transportables, es decir, que podrán ejecutarse en cualquier ordenador y
con cualquier sistema operativo.
Junto con los compiladores de C y C++, se incluyen ciertos ficheros llamados librerías. Las librerías
contienen el código objeto de muchos programas que permiten hacer cosas comunes, como leer
el teclado, escribir en la pantalla, manejar números, realizar funciones matemáticas, etc. Las
librerías están clasificadas por el tipo de trabajos que hacen, hay librerías de entrada y salida,
matemáticas, de manejo de memoria, de manejo de textos, etc.
Hay un conjunto de librerías muy especiales, que se incluyen con todos los compiladores de C y de
C++. Son las librerías ANSI o estándar. Pero también hay librerías no estándar, y dentro de estas las
hay públicas y comerciales. En este nos centraremos en la librería estándar STL.
5/8/2018 Estructura de datos - slidepdf.com
http://slidepdf.com/reader/full/estructura-de-datos-559abe4db4fe4 5/62
4
TEMA 1
ANTECEDENTES.
Presentar a los alumnos las estructuras de datos básicas y su transformación en estructuras más
complejas. Se pretende que los alumnos puedan definir o elegir estructuras adecuadas para la
resolución de problemas específicos de la vida real apoyados en las técnicas computacionales.
1.1 Introducción a la orient ación a objetos.
La programación orientada a objetos (POO) es una nueva manera de enfocar la programación.
Desde sus comienzos, la programación ha estado gobernada por varias metodologías. En cada
punto crítico de la evolución de la programación se creaba un nuevo enfoque para ayudar al
programador a manejar programas cada vez más complejos. Los primeros programas se crearon
mediante un proceso de cambio de los conmutadores del panel frontal de la computadora.
Obviamente, este enfoque solo es adecuado para programas pequeños. A continuación se inventó
el lenguaje ensamblador que permitió escribir programas más largos. El siguiente avance ocurrió
en los años 50 cuando se inventó el primer lenguaje de alto nivel (FORTRAN).
Mediante un lenguaje de alto nivel, un programador estaba capacitado para escribir programas
que tuvieran una longitud de varios miles de líneas. Sin embargo, el método de programación
usado en el comienzo era un enfoque adhoc que no solucionaba mucho. Mientras que esto está
bien para programas relativamente cortos, se convierte en código espagueti ilegible y difícil detratar cuando se aplica a programas más largos. La eliminación del código espagueti se consiguió
con la creación de los lenguajes de programación estructurados en los años sesenta. Estos
lenguajes incluyen ALGOL y PASCAL. En definitiva, C es un lenguaje estructurado, y casi todos los
tipos de programas que se han estado haciendo se podrían llamar programas estructurados.
Los programas estructurados se basan en estructuras de control bien definidas, bloques de código,
la ausencia del GOTO, y subrutinas independientes que soportan recursividad y variables locales.
La esencia de la programación estructurada es la reducción de un programa a sus elementos
constitutivos. Mediante la programación estructurada un programador medio puede crear y
mantener programas de una longitud superior a 50,000 líneas.
Aunque la programación estructurada nos ha llevado a excelentes resultados cuando se ha
aplicado a programas moderadamente complejos, llega a fallar en algún punto cuando el
programa alcanza un cierto tamaño. Para poder escribir programas de mayor complejidad se
necesitaba de un nuevo enfoque en la tarea de programación. A partir de este punto nace la
programación orientada a objetos (POO). La POO toma las mejores ideas incorporadas en la
programación estructurada y las combina con nuevos y potentes conceptos que permiten
5/8/2018 Estructura de datos - slidepdf.com
http://slidepdf.com/reader/full/estructura-de-datos-559abe4db4fe4 6/62
organizar los programas de forma más 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 más largos.
Todos los lenguajes de POO comparten tres características: encapsulación, polimorfismo yherencia.
La encapsulación es el mecanismo que agrupa el código y los datos que maneja y los mantiene
protegidos frente a cualquier interferencia y mal uso. En un lenguaje orientado a objetos, el código
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 código como los datos. Cuando el código
y los datos están enlazados de esta manera, se ha creado un objeto. En otras palabras, un objeto
es el dispositivo que soporta encapsulación.
Polimorfismo (del Griego, cuyo significado es muchas formas) es la cualidad que permite que un
nombre se utilice para dos o más propósitos relacionados pero técnicamente diferentes. El
propósito 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 acción específica a
aplicar está determinada por el tipo de dato.
El polimorfismo se puede aplicar tanto a funciones como a operadores, prácticamente todos los
lenguajes de programación contienen una aplicación limitada de polimorfismo cuando se relaciona
con los operadores aritméticos, por ejemplo, en C, el signo + se utiliza para añadir enteros,
enteros largos, caracteres y valores reales. En estos casos, el compilador automáticamente sabe
qué tipo de aritmética 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
añadir aquellas características que son específicamente suyas. La herencia es importante porque
permite que un objeto soporte el concepto de clasificación jerárquica. Mucha información se hace
manejable gracias a esta clasificación, por ejemplo, la descripción de una casa.
Una casa es parte de una clase general llamada edificio, a su vez, edificio es una parte de la clase
más general estructura, que es parte de la clase aún más general de objetos que se puede llamar
obra-hombre.
5/8/2018 Estructura de datos - slidepdf.com
http://slidepdf.com/reader/full/estructura-de-datos-559abe4db4fe4 7/62
1.2 Tipos de datos abstractos.
Los tipos de datos abstractos (TDA) encapsulan datos y funciones que trabajan con estos datos.
Los datos no son visibles para el usuario en un tipo de dato abstracto y el acceso a los datos es
exclusivamente bajo el llamado a funciones, también llamadas métodos. Así, el tipo de datoabstracto es especificado por los métodos, no por los datos. En C++, los tipos de datos abstractos
son representados por clases, las cuales presentan a pequeña deficiencia: el dato que representa
el estado de un objeto de este tipo de dato abstracto es visible (algunas veces no accesible) en la
parte private de la clase declarada para cada programa, la clase es reconocida mediante la vía
#include. Ejemplos de tipos de datos abstractos son: stack, queue, etc
Los TDA por lo general manejan memoria dinámica, esto es, la asignación dinámica de memoria es
una característica que le permite al usuario crear tipos de datos y estructuras de cualquier
tamaño de acuerdo a las necesidades que se tengan en el programa, para ello se emplean
funciones típicas como malloc y free.
5/8/2018 Estructura de datos - slidepdf.com
http://slidepdf.com/reader/full/estructura-de-datos-559abe4db4fe4 8/62
1.3 Definición de estructuras de datos.
En programación, una estructura de datos es una forma de organizar un conjunto de datos
elementales (un dato elemental es la mínima información que se tiene en el sistema) con el
objetivo de facilitar la manipulación de estos datos como un todo y/o individualmente.
Una estructura de datos define la organización e interrelacionamiento de estos, y un conjunto de
operaciones que se pueden realizar sobre él. Las operaciones básicas son:
Alta, adicionar un nuevo valor a la estructura.
Baja, borrar un valor de la estructura.
Búsqueda, encontrar un determinado valor en la estructura para realizar una operación
con este valor, en forma SECUENCIAL o BINARIO (siempre y cuando los datos estén
ordenados).
Otras operaciones que se pueden realizar son:
y Ordenamiento, de los elementos pertenecientes a la estructura.
y Apareo, dadas dos estructuras originar una nueva ordenada y que contenga a las
apareadas.
5/8/2018 Estructura de datos - slidepdf.com
http://slidepdf.com/reader/full/estructura-de-datos-559abe4db4fe4 9/62
8
1.4 Colecciones genéricas de datos.
Cada estructura ofrece ventajas y desventajas en relación a la simplicidad y eficiencia para la
realización de cada operación. De esta forma, la elección de la estructura de datos apropiada para
cada problema depende de factores como las frecuencias y el orden en que se realiza cadaoperación sobre los datos.
Algunas estructuras de datos utilizadas en programación son:
Arrays (Arreglos)
o Vectores
o Matrices
Listas Enlazadas
o Listas Simples
o Listas Dobles
o Listas Circulares
Pilas (stack)
Colas (queue)
Árboles
o Árboles Binarios
Árbol binario de búsqueda
y Árbol binario de búsqueda autoajustable
y Árboles Biselados (Árboles Splay)
o Árboles Multicamino (Multirrama)
Árboles B
Árboles B+
Árboles B*
Conjuntos (set)
Grafos
Montículos (o heaps)
5/8/2018 Estructura de datos - slidepdf.com
http://slidepdf.com/reader/full/estructura-de-datos-559abe4db4fe4 10/62
9
1.5 Acceso directo y secuencial a los datos.
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 exploración 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 posición en el soporte de almacenamiento.
5/8/2018 Estructura de datos - slidepdf.com
http://slidepdf.com/reader/full/estructura-de-datos-559abe4db4fe4 11/62
1
1.6 Iteradores.
Un iterador es una especie de puntero utilizado por un algoritmo para recorrer los elementosalmacenados en un contenedor. Dado que los distintos algoritmos necesitan recorrer los
contenedores de diversas maneras para realizar diversas operaciones, y los contenedores debenser accedidos de formas distintas, existen diferentes tipos de iteradores. Cada contenedor de laLibrería Estándar puede generar un iterador con funcionalidad adecuada a la técnica dealmacenamiento que utiliza. Es precisamente el tipo de iterador requerido como argumento, loque 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 puedenutilizarse con algoritmos que exijan iteradores de acceso aleatorio.
Un puntero es una variable destinada a contener una dirección de memoria.
Esta dirección generalmente corresponde a otra variable, decimos entonces que el punterocontiene la dirección de la variable o que apunta a ésta.
En el siguiente esquema suponemos que la variable puntero está cargada con el número 4A20.Decimos, entonces, que la dirección 0x4A20 es apuntada por el puntero.
Entre las ventajas que encontramos al usar estos elementos están:
1) Permiten el acceso a cualquier posición de la memoria, para ser leída o para ser escrita (enlos casos en que esto sea posible).
2) Permiten la transferencia de argumentos a las funciones, de modo que puedan retener unvalor nuevo, que resulta de aplicarles la función.
3) Permiten solicitar memoria que no fue reservada al inicio del programa. Esto es el uso dememoria dinámica.
4) Son el soporte de enlace que utilizan estructuras avanzadas de datos en memoriadinámica como las listas, pilas, colas y árboles.
5) Operan más eficientemente en los arrays, en comparación con el uso de subíndices.
5/8/2018 Estructura de datos - slidepdf.com
http://slidepdf.com/reader/full/estructura-de-datos-559abe4db4fe4 12/62
1
1.7 Plantillas (templates).
La generalidad es una propiedad que permite definir una clase o una función sin tener queespecificar el tipo de todos o alguno de sus miembros. Esta propiedad no es imprescindible en unlenguaje de programación orientado a objetos y ni siquiera es una de sus características. Esta
característica del C++ apareció mucho más tarde que el resto del lenguaje, al final de la década delos ochenta. Esta generalidad se alcanza con las plantillas (templates).
La utilidad principal de este tipo de clases o funciones es la de agrupar variables cuyo tipo no estépredeterminado. Así el funcionamiento de una pila, una cola, una lista, un conjunto, undiccionario o un array es el mismo independientemente del tipo de datos que almacene (int,long, double, char, u objetos de una clase definida por el usuario). En definitiva estas clases sedefinen independientemente del tipo de variables que vayan a contener y es el usuario de la claseel que debe indicar ese tipo en el momento de crear un objeto de esa clase.
Plantillas de funciones
Supóngase que se quiere crear una función que devolviese el mínimo entre dos valoresindependientemente de su tipo (se supone que ambos tienen el mismo tipo). Se podría pensar endefinir la función tantas veces como tipos de datos se puedan presentar (int, long, float, double,etc.). Aunque esto es posible, éste es uncaso ideal para aplicar plantillas de funciones. Esto sepuede hacer de la siguiente manera:
// Declaración de la plantilla de función.
template <class T> T minimo( T a, T b);
En ese caso con <classT> se está indicando que se trata de una plantilla cuyo parámetro vaa 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 definición y declaración de la plantilla puede ser que senecesite utilizar más de un tipo de dato e incluido algún otro parámetro constante que pueda
ser utilizado en las declaraciones. Por ejemplo, si hubiera que pasar dos tipos a la plantilla,se podría escribir:
// Declaración de la plantilla de función con dos tipos de datos
template <class T1, class T2> void combinar(T1 a, T2 b);
Podría darse el caso también de que alguno de los argumentos o el valor de retorno fuese deun tipo de dato constante y conocido. En ese caso se indicaría explícitamente como en una
función convencional. La definición de la plantilla de función es como sigue:
// Definición de la plantilla de función
template <class T> T minimo(T a, T b)
{
5/8/2018 Estructura de datos - slidepdf.com
http://slidepdf.com/reader/full/estructura-de-datos-559abe4db4fe4 13/62
1
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 tambiénalgunas diferencias que pueden hacer necesarias ambas características. El polimorfismo
necesita punteros y su generalidad se limita a jerarquías. Recuérdese que el polimorfismo se basa en que en el momento de compilación se desconoce a qué clase de la
jerarquía 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 ampliación del polimorfismo. Una desventaja de las plantillas es que tienden a crear un código ejecutablegrande porque se crean tantas versiones de las funciones como son necesarias.
5/8/2018 Estructura de datos - slidepdf.com
http://slidepdf.com/reader/full/estructura-de-datos-559abe4db4fe4 14/62
1
1.8 La biblioteca STL.
La Biblioteca Estándar de Patrones, comúnmente conocida en inglés por sus siglas STL (Standard
Template Library) es una biblioteca de C++ que incluye la mayoría de algoritmos y estructuras de
datos que se suelen utilizar en Informática. Básicamente está compuesta de:
clases contenedoras, es decir, patrones (templates) que permiten almacenar objetos de
muy diversos tipos.
algoritmos de uso frecuente.
iteradores, que nos permitirán recorrer los elementos incluidos en los contenedores.
También incluye "objetos función", 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 más fácilmente.
Esta biblioteca es genérica en tanto sus componentes están 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 programación 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 inserción).
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.
5/8/2018 Estructura de datos - slidepdf.com
http://slidepdf.com/reader/full/estructura-de-datos-559abe4db4fe4 15/62
1
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.
5/8/2018 Estructura de datos - slidepdf.com
http://slidepdf.com/reader/full/estructura-de-datos-559abe4db4fe4 16/62
1
Pregunt as de autoevaluación.
5/8/2018 Estructura de datos - slidepdf.com
http://slidepdf.com/reader/full/estructura-de-datos-559abe4db4fe4 17/62
1
TEMA 2
ARREGLOS.
Identificar y usar el tipo de estructura conocida como arreglo para dar solución a necesidades de
organización de datos que se presenten.
2.1 Arreglos lineales dinámicos.
Los arreglos (arrays) permiten agrupar datos usando un mismo identificador. Todos los elementos
de un array son del mismo tipo, y para acceder a cada elemento se usan subíndices.
Sintaxis:
<tipo><identificador>[<núm_elemen>][[<núm_elemen>]...];
Los valores para el número de elementos deben ser constantes, y se pueden usar tantas
dimensiones como queramos, limitado sólo por la memoria disponible.
Cuando sólo se usa una dimensión se suele hablar de listas o vectores, cuando se usan dos, de
tablas.
Ahora podemos ver que las cadenas de caracteres son un tipo especial de arrays. Se trata en
realidad de arrays de una dimensión de objetos de tipo char.
Los subíndices son enteros, y pueden tomar valores desde 0 hasta <número de elementos>-1.
En general C++ no verifica el ámbito de los subíndices. Si declaramos un array de 10 elementos, no
obtendremos errores al acceder al elemento 11. Sin embargo, si asignamos valores a elementos
fuera del ámbito declarado, estaremos accediendo a zonas de memoria que pueden pertenecer a
otras variables o incluso al código ejecutable de nuestro programa, con consecuencias
generalmente desastrosas.
Ejemplo:
int Tabla[10][10];
char DimensionN[4][15][6][8][11];
...DimensionN[3][11][0][4][6] = DimensionN[0][12][5][3][1];
Tabla[0][0] += Tabla[9][9];
Si al iniciar un programa no se sabe el número de elementos del que va a constar el array, o no se
quiere poner un límite predetermiado, lo que hay que hacer es definir el array dinámicamente.
Para hacer esto, primero se define un puntero, que señalará la dirección de memoria del primer
elemento del array: tipo_de_elemento *nombre_de_array;
5/8/2018 Estructura de datos - slidepdf.com
http://slidepdf.com/reader/full/estructura-de-datos-559abe4db4fe4 18/62
1
y luego se utiliza la función malloc (contenida en stdlib.h) para reservar memoria:
nombre_de_array=(tipo_de_elemento *)malloc(tamaño);
donde tamaño es el número de elementos del array por el tamaño en bytes de cada elemento. La
función malloc devuelve un puntero void, que indica la posición del primer elemento. Antes de
asignarlo a nuestro puntero, hay que convertir el puntero que devuelve el malloc al tipo denuestro puntero (ya que no se pueden igualar punteros de distintos tipos).
5/8/2018 Estructura de datos - slidepdf.com
http://slidepdf.com/reader/full/estructura-de-datos-559abe4db4fe4 19/62
1
2.2 Represent ación de arreglos lineales en memoria
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 subíndice podremos usar cualquier expresión entera.
Los arrays pueden ser inicializados en la declaración.
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 tamaño para la primera dimensión, como ocurre en
los ejemplos de las líneas 2, 3, 4, 5 y 6. En estos casos la dimensión que queda indefinida se calcula
a partir del número de elementos en la lista de valores iniciales.
En el caso 2, el número 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 dimensión es 3: 9/3=3.
Y en el caso 5, el número de elementos es 17, 16 caracteres más el cero de fin de cadena.
5/8/2018 Estructura de datos - slidepdf.com
http://slidepdf.com/reader/full/estructura-de-datos-559abe4db4fe4 20/62
1
2.3 Operaciones con arreglos.
Ya hemos visto que se puede usar el operador de asignación con arrays para asignar valores
iniciales. El otro operador que tiene sentido con los arrays es sizeof.
Aplicado a un array, el operador sizeof devuelve el tamaño de todo el array en bytes. Podemosobtener el número de elementos dividiendo ese valor entre el tamaño de uno de los elementos.
#include <iostream>using namespace std;
int main(){
int array[231];cout << "Número de elementos: "
<< sizeof(array)/sizeof(int) << endl;
cout << "Número de elementos: "<< sizeof(array)/sizeof(array[0]) << endl;cin.get();
return 0;}
Las dos formas son válidas, pero la segunda es, tal vez, más general.
5/8/2018 Estructura de datos - slidepdf.com
http://slidepdf.com/reader/full/estructura-de-datos-559abe4db4fe4 21/62
2
2.4 Arreglos dinámicos.
Si al iniciar un programa no se sabe el número de elementos del que va a constar el array, o no se
quiere poner un límite predetermiado, lo que hay que hacer es definir el array dinámicamente.
Para hacer esto, primero se define un puntero, que señalará la dirección de memoria del primerelemento del array:
tipo_de_elemento *nombre_de_array;
y luego se utiliza la función malloc (contenida en stdlib.h) para reservar memoria:
nombre_de_array=(tipo_de_elemento *)malloc(tamaño);
Donde tamaño es el número de elementos del array por el tamaño en bytes de cada elemento. La
función malloc devuelve un puntero void, que indica la posición del primer elemento. Antes de
asignarlo a nuestro puntero, hay que convertir el puntero que devuelve el malloc al tipo denuestro puntero (ya que no se pueden igualar punteros de distintos tipos).
Para arrays bidimensionales, hay que hacerlo dimensión a dimensión; primero se define un
puntero de punteros:
int **mapa;
Luego se reserva memoria para los punteros:
mapa=(int **)malloc(sizeof(int *)*N1);
y, por último, para cada puntero se reserva memoria para los elementos:
for(i1=0;i1<N1;i1++)
mapa[i1]=(int *)malloc(sizeof(int)*N2);
Ya se puede utilizar el array normalmente. Para arrays de más de dos dimensiones, se hace de
forma similar.
5/8/2018 Estructura de datos - slidepdf.com
http://slidepdf.com/reader/full/estructura-de-datos-559abe4db4fe4 22/62
2
2.5 Punteros y arreglos de punteros.
Un puntero es una variable destinada a contener una dirección de memoria.
Esta dirección generalmente corresponde a otra variable, decimos entonces que el puntero
contiene la dirección de la variable o que apunta a ésta.
Sintaxis para declarar punteros:
tipo * nombre_puntero;
nombre_puntero es el identificador de la variable.
El * es el operador de indirección que nos indica que la variable es de tipo puntero.
Tipo indica el tipo de la variable apuntada por el puntero (se lo denomina tipo base).
Ejemplo:
En la siguiente declaración, p es un puntero a float, i es una variable tipo int y q es un puntero a
int.
int i, *q;
float *p;
Punteros a estructura
Sintaxis:
struct tipo_estructura * nombre_estructura;
tipo_estructura es un rótulo 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 día;
int mes;
int anio;
5/8/2018 Estructura de datos - slidepdf.com
http://slidepdf.com/reader/full/estructura-de-datos-559abe4db4fe4 23/62
2
};
struct fecha hoy;
struct fecha * F;
F todavía no apunta a una dirección válida. Hacemos que F apunte a hoy, cargándolo con la
dirección 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 dirección. Por eso usamos el operador mencionado.
5/8/2018 Estructura de datos - slidepdf.com
http://slidepdf.com/reader/full/estructura-de-datos-559abe4db4fe4 24/62
2
2.6 La clase VECTOR.
Aunque cada uno de los contenedores que ofrece la STL tienen características diferentes, en esta
sección presentaremos el contenedor vector. El contenedor vector permite almacenar cero o más
objetos del mismo tipo, pudiendo acceder a ellos individualmente mediante un índice, es decir,acceso aleatorio. En este sentido, es una extensión del vector o array que ofrece C++, aunque en
este caso el número de elementos de un objeto vector puede variar dinámicamente. La gestión de
la memoria se hace de manera totalmente transparente al usuario. Se define como una clase
patrón, lo que implica que puede albergar objetos de cualquier tipo. En cuanto a las operaciones
más frecuentes, ofrece un tiempo constante en inserción y borrados de elementos al final, y lineal
al comienzo o en la mitad del vector.
La declaración más común de un objeto de tipo vector se realiza de la siguiente manera:
vector<tipo> objeto
donde tipo puede ser cualquier tipo o clase de los que ofrece C++, así como cualquier otra clase
implementada por un usuario. Así, podríamos declarar los siguientes vectores:
vector<double> vectorReales; // De números reales.
vector<string> vectorCadenas; // De cadenas de caracteres.
vector<MiClase> vectorObj; // Contendrá objetos de una clase construida por un usuario
Una declaración:
vector <int> vectorEnteros(10);
Crea un vector de diez enteros. Si deseamos inicializarlo a algún valor en concreto, entoncesañadimos un argumento más al constructor:
vector <int> vectorEnteros(10,-1)
De manera general las funciones miembro y operadores manejados por vector más utilizadas son:
5/8/2018 Estructura de datos - slidepdf.com
http://slidepdf.com/reader/full/estructura-de-datos-559abe4db4fe4 25/62
2
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 más 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;
}
5/8/2018 Estructura de datos - slidepdf.com
http://slidepdf.com/reader/full/estructura-de-datos-559abe4db4fe4 26/62
2
Pregunt as de autoevaluación.
5/8/2018 Estructura de datos - slidepdf.com
http://slidepdf.com/reader/full/estructura-de-datos-559abe4db4fe4 27/62
2
TEMA 3
LISTAS.
Identificar y usar el tipo de estructura conocida como lista para dar solución a necesidades de
organización de datos que se presenten.
3.1 Definición de list a.
Una lista es un conjunto de elementos del mismo tipo. Una propiedad importante con la que se
caracteriza a las listas es que su longitud puede aumentar o disminuir, según se requiera. Es más,podemos insertar o eliminar elementos en cualquier posición de una lista.
Las listas se pueden implementar de 2 modos distintos: mediante vectores o mediante estructuras
dinámicas enlazadas por apuntadores. El trabajo de listas con vectores tiene una limitante: las
listas tienen una longitud variable (dinámicas) y los vectores tienen longitud estática. No
podríamos definir un arreglo de tamaño N donde solamente utilicemos los primero N-m cajones.
O viceversa, declarar un arreglo demasiado pequeño para nuestras necesidades. Esto es el porqué
de las estructuras dinámicas de datos.
La forma más simple de estructura dinámica es la lista. En esta forma los nodos se organizan demodo que cada uno apunta al siguiente, y el último no apunta a nada, es decir, el puntero del
nodo siguiente vale NULL.
En las listas abiertas existe un nodo especial: el primero. Normalmente diremos que nuestra lista
es un puntero a ese primer nodo y llamaremos a ese nodo la cabeza de la lista. Eso es porque
mediante ese único puntero podemos acceder a toda la l ista.
Cuando el puntero que usamos para acceder a la lista vale NULL, diremos que la lista está vacía. El
nodo típico para construir listas tiene esta forma:
En el ejemplo, cada elemento de la lista sólo contiene un dato de tipo entero, pero en la práctica
no hay límite en cuanto a la complejidad de los datos a almacenar.
5/8/2018 Estructura de datos - slidepdf.com
http://slidepdf.com/reader/full/estructura-de-datos-559abe4db4fe4 28/62
2
3.2 Asignación de memoria a la list a.
Normalmente se definen varios tipos que facilitan el manejo de las listas, la declaración de tipos
puede tener una forma en memoria parecida a esta:
Dónde:
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.
5/8/2018 Estructura de datos - slidepdf.com
http://slidepdf.com/reader/full/estructura-de-datos-559abe4db4fe4 29/62
2
3.3 La clase list a de STL.
El contenedor de decencia LIST cuenta con una eficiente combinación para las operaciones de
inserción y eliminación en cualquier posición 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 atrás.
Además 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.
5/8/2018 Estructura de datos - slidepdf.com
http://slidepdf.com/reader/full/estructura-de-datos-559abe4db4fe4 30/62
2
3.4 Iteradores para la clase list a.
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.
Gracias a los iteradores tendremos un pequeño repertorio de operaciones básicas que se pueden
realizar:
y Añadir o insertar elementos.
y Buscar o localizar elementos.
y Borrar elementos.
y Moverse a través de una lista, anterior, siguiente, primero.
Cada una de estas operaciones tendrá varios casos especiales, por ejemplo, no será lo mismo
insertar un nodo en una lista vacía, o al principio de una lista no vacía, o la final, o en una posición
intermedia.
A continuación se describen algunos programas de ejmplo con iteradores.
List::const_iterator (STL/CLR)
En esta aplicación 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);}
El Resultado debería ser el siguiente: a b c
5/8/2018 Estructura de datos - slidepdf.com
http://slidepdf.com/reader/full/estructura-de-datos-559abe4db4fe4 31/62
3
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 elementcliext::list<wchar_t>::const_reference cref = *cit;System::Console::Write(" {0}", cref);}
System::Console::WriteLine();return (0);
}
El resultado debera ser: a b c
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');
5/8/2018 Estructura de datos - slidepdf.com
http://slidepdf.com/reader/full/estructura-de-datos-559abe4db4fe4 32/62
3
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 redisplayit = 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
5/8/2018 Estructura de datos - slidepdf.com
http://slidepdf.com/reader/full/estructura-de-datos-559abe4db4fe4 33/62
3
3.5 Construcción de list as.
Partimos de un nodo a insertar, con un puntero que apunte a él, y de una lista, en este caso no
vacía:
El proceso sigue siendo muy sencillo:
1. Hacemos que nodo->siguiente apunte a Lista.
2. Hacemos que Lista apunte a nodo.
En algunos casos partimos de una lista no vacía:
El proceso en este caso tampoco es excesivamente complicado:
1. Necesitamos un puntero que señale 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.
5/8/2018 Estructura de datos - slidepdf.com
http://slidepdf.com/reader/full/estructura-de-datos-559abe4db4fe4 34/62
3
3.6 Algoritmos genéricos sobre colecciones de STL.
La librería estándar proveeherramientasquefacilitanla programacion.Eselcasodelos
string,quepermitenevitarlosproblemasmas clásicos conlascadenasdecaracteresalaC.
strings1(Primera);
strings2=Segunda;
strings3=s1+ y +s2;
s3.append(y aun mas);
La librera estándar también provee,fueradetodaclase/patron, código
generico,implementadocomo funcionespatrones.Sonabstraccionesdefuncionesrecurrentesen
código C++.
Esta funcion copiatodosloselementosdentrodeunarreglo,dentrodeunoslimites(dadosen términos
deapuntadores),haciaotroarreglo.Seahorraescribirciclos!
Como estaimplementadocomo template,sepuedeusar cualquiertipodeapuntador.
5/8/2018 Estructura de datos - slidepdf.com
http://slidepdf.com/reader/full/estructura-de-datos-559abe4db4fe4 35/62
3
Pregunt as de autoevaluación.
5/8/2018 Estructura de datos - slidepdf.com
http://slidepdf.com/reader/full/estructura-de-datos-559abe4db4fe4 36/62
3
TEMA 4
PILAS.
Identificar y usar el tipo de estructura conocida como pila para dar solución a necesidades de
organización de datos que se presenten.
4.1 Definición de pilas.
Una pila es un tipo especial de lista abierta en la que sólo se pueden insertar y eliminar nodos en
uno de los extremos de la lista. Estas operaciones seconocen como "push" y "pop",
respectivamente "empujar" y "tirar". Además, las escrituras de datos siempre son inserciones de
nodos, y las lecturas siempre eliminan el nodo leído.
Estas características implican un comportamiento de lista LIFO (Last In First Out), el último en
entrar es el primero en salir. La más sencilla de las estructuras dinámicas de datos es la pila, las
pilas son utilizadas sobre todo por los sistemas operativos y los controladores de los lenguajes de
alto nivel. Una pila es dinámica: crece y encoge a medida que es necesario.
Una manera de ver esta estructura es pensar en las pilas como si fuese una pila de bandejas de un
autoservicio. Las bandejas se ponen en la pila por arriba, la bandeja de arriba se la lleva de la pila
un cliente que este en la cola. Este escenario se denomina modelo del último en llegar-primero
en salir: la última bandeja que se ponga en la pila será la primera que se lleven.
5/8/2018 Estructura de datos - slidepdf.com
http://slidepdf.com/reader/full/estructura-de-datos-559abe4db4fe4 37/62
3
4.2 Implement ación de pilas.
El nodo típico para construir pilas es el siguiente:
Los tipos que se definen normalmente para manejar pilas son casi los mismos que para manejar
listas, tan sólo se cambian algunos nombres de la siguiente manera:
Dónde:
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 gráfica de ver la estructura sería:
Es evidente, a la vista del gráfico, 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.
5/8/2018 Estructura de datos - slidepdf.com
http://slidepdf.com/reader/full/estructura-de-datos-559abe4db4fe4 38/62
3
4.3 La clase STACK de STL
La clase STACK permite insertar a, y eliminar de, la estructura de datos subyacente en un extremo.
Una pila puede implementarse con cualquiera de los contenedores de secuencia; vector, list y
deque.
De manera predeterminada, una pila se implementa con un deque. Las operaciones de la pila son:
push para insertar un elemento en la parte superior, pop para eliminar el elemento de la pila, top
para obtener una referencia al elemento de la pila, empty para determinar si la pila se encuentra
vacía o no y size para obtener el número de elementos de la pila.
Para poder hacer uso de la clase STACK es necesario incluir el archivo de encabezado <stack>, por
ejemplo, el siguiente codigo crea tres pilas de enteros utilizando cada uno de los contenedores de
secuencia de la STL como estructura de datos subyacente para representar al adaptador STACK.
// Programa de prueba para el adaptador stack de la Biblioteca estándar.
#include <iostream>
using std::cout;
using std::endl;
#include <stack> // definición del adaptador stack
#include <vector> // definición de la plantilla de clase vector
#include <list> // definición de la plantilla de clase list
// prototipo de la plantilla de función sacarElementostemplate< class T >
void sacarElementos( T &stackRef );
int main()
{
// pila con deque subyacente predeterminado
std::stack< int > intDequePila;
// pila con vector subyacente
std::stack< int, std::vector< int >> intVectorPila;
// pila con lista subyacente
std::stack< int, std::list< int >> intListaPila;
// meter los valores 0-9 en cada pila
for ( int i = 0; i < 10; ++i ) {
5/8/2018 Estructura de datos - slidepdf.com
http://slidepdf.com/reader/full/estructura-de-datos-559abe4db4fe4 39/62
3
intDequePila.push( i );
intVectorPila.push( i );
intListaPila.push( i );
} // fin de instrucción 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 instrucción while
} // fin de la función sacarElementos
5/8/2018 Estructura de datos - slidepdf.com
http://slidepdf.com/reader/full/estructura-de-datos-559abe4db4fe4 40/62
3
4.4 Iteradores para la clase St ack.
El termino iterar significa (en palabras sencillas) el método o forma que se usa para poder navegar
sobre los elementos de una lista específica. Luego, un iterador es como una especie de "puntero
especial" que nos permite leer o escribir valores sobre cada uno de los elementos en una lista. Los
iteradores pueden ser comparados con los índices que se emplean para leer o escribir valores
sobre los elementos de una lista. Igual a lo que sucede con los tipos de datos dentro de un arreglo
primitivo en donde para leer o escribir valores sobre los elementos se tiene que prestar atención
al tipo de dato, un iterador tiene que ser del tipo de dato que posee la lista. En ese sentido, si
tenemos por ejemplo un vector que posee datos de tipo entero (int) entonces el iterador tendrá
que ser de tipo entero; si por el contrario se tiene un vector cuyos datos son del tipo cadena
(string) entonces el iterador tiene que ser del tipo cadena.
La sintaxis general para la declaración de un iterador es:
NombrePlantilla<tipo>::iterator varid;
Donde,
NombrePlantilla Es el nombre de una STL
tipo Es el tipo usado para la plantilla
::iterator Es el método para obtener el iterador
varid Es el nombre de la variable
La forma de los programas es igual a la que ya se ha visto por lo que sólo se expondrá la parte
inicial donde se hace referencia a la definición 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.top()<<endl;
s.pop();
} cout<<" ";
system("pause");
}
5/8/2018 Estructura de datos - slidepdf.com
http://slidepdf.com/reader/full/estructura-de-datos-559abe4db4fe4 41/62
4
4.5Construcción de Pilas.
Supongamos que queremos construir una pila para almacenar números 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 función "pop":
1. Hacemos que nodo apunte al primer elemento de la pila, es decir, a Pila.
2. Asignamos a Pila la dirección 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.
5/8/2018 Estructura de datos - slidepdf.com
http://slidepdf.com/reader/full/estructura-de-datos-559abe4db4fe4 42/62
4
También 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. Además la clase para nodo
debe ser amiga de la clase pila, ya que ésta debe acceder a los miembros privados de nodo.
5/8/2018 Estructura de datos - slidepdf.com
http://slidepdf.com/reader/full/estructura-de-datos-559abe4db4fe4 43/62
4
Pregunt as de autoevaluación.
5/8/2018 Estructura de datos - slidepdf.com
http://slidepdf.com/reader/full/estructura-de-datos-559abe4db4fe4 44/62
4
TEMA 5
COLAS.
Identificar y usar el tipo de estructura conocida como cola para dar solución a necesidades de
organización de datos que se presenten.
5.1 Definición de colas.
Una cola es un tipo especial de lista abierta en la que sólo se puede insertar nodos en uno de los
extremos de la lista y sólo se pueden eliminar nodos en el otro. Además, como sucede con las
pilas, las escrituras de datos siempre son inserciones de nodos, y las lecturas siempre eliminan el
nodo leído.
Este tipo de lista es conocido como lista FIFO (First In First Out), el primero en entrar es el primero
en salir.
Un ejemplo cotidiano es una cola para comprar, por ejemplo, las entradas del cine. Los nuevos
compradores sólo pueden colocarse al final de la cola, y sólo el primero de la cola puede comprar
la entrada.
5/8/2018 Estructura de datos - slidepdf.com
http://slidepdf.com/reader/full/estructura-de-datos-559abe4db4fe4 45/62
4
5.2 Construcción de colas.
El nodo típico para construir colas es el mismo para la construcción de listas y pilas:
Los tipos que se definen normalmente para manejar colas son casi los mismos que para manejar
listas y pilas, tan sólo se cambian algunos nombres:
Dónde:
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 gráficamente 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. Además, debido al funcionamiento de las colas, también 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 más fácil será insertar nodos por el final, a continuación del nodo que no tiene nodo
siguiente, y leerlos desde el principio, hay que recordar que leer un nodo implica eliminarlo de la
cola.
5/8/2018 Estructura de datos - slidepdf.com
http://slidepdf.com/reader/full/estructura-de-datos-559abe4db4fe4 46/62
4
5.3 La clase queue de STL.
La clase QUEUE permite inserciones en la parte final de la estructura de datos subyacentes y
eliminaciones en la parte inicial de la misma. Una cola puede implementarse con la estructura de
datos list o deque de la STL, de manera predeterminada una cola se implementa con deque.
Las operaciones comunes de un adaptador queue son push para insertar un elemento en su parte
final, pop para eliminar el elemento en la parte inicial de la cola, front para obtener una referencia
al primer elemento de la cola, back para obtener una referencia al último elemento de la cola,
empty para determinar si la cola está o no vacía y size para obtener el número de elementos de la
cola.
El archivo de encabezado <queue> debe incluirse para poder utilizar esta clase. Por ejemplo, el
siguiente codigo muestra el uso de la clase queue.
// Programa de prueba para el adaptador queue de la Biblioteca estándar.
#include <iostream>
using std::cout;
using std::endl;
#include <queue> // definición del adaptador queue
int main()
{
std::queue< double >valores;
// meter elementos en la cola valores
valores.push( 3.2 );valores.push( 9.8 );
valores.push( 5.4 );
cout << "Sacando de valores: ";
while ( !valores.empty() ) {
cout << valores.front() << ' '; // ver elemento inicial
valores.pop(); // eliminar elemento
} // fin de instrucción while
cout << endl;
return 0;
} // fin de main
5/8/2018 Estructura de datos - slidepdf.com
http://slidepdf.com/reader/full/estructura-de-datos-559abe4db4fe4 47/62
4
5.4 Iteradores para la clase Queue.
Supóngase que construimos una cola para almacenar números enteros.
1. Creamos un nodo para el valor que colocaremos en la cola.
2. Hacemos que nodo->siguiente apunte a NULL.
3. Si "ultimo" no es NULL, hacemos que ultimo->siguiente apunte a nodo.
4. Actualizamos "ultimo" haciendo que apunte a nodo.
5. Si "primero" es NULL, hacemos que apunte a nodo.
void Anadir(pNodo *primero, pNodo *ultimo, int v) {pNodo nuevo;
/* Crear un nodo nuevo */nuevo = (pNodo)malloc(sizeof(tipoNodo));nuevo->valor = v;/* Este será el último nodo, no debe tener siguiente */nuevo->siguiente = NULL;/* Si la cola no estaba vacía, añadimos el nuevo a continuación de ultimo */if(*ultimo) (*ultimo)->siguiente = nuevo;/* Ahora, el último elemento de la cola es el nuevo nodo */*ultimo = nuevo;/* Si primero es NULL, la cola estaba vacía, ahora primero apuntará también al
nuevo nodo */
if(!*primero) *primero = nuevo;}
Algoritmo de la función "leer":
1. Hacemos que nodo apunte al primer elemento de la cola, es decir a primero.
2. Asignamos a primero la dirección 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 también apunte a NULL, ya que la cola habrá quedado
vacía.
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;
5/8/2018 Estructura de datos - slidepdf.com
http://slidepdf.com/reader/full/estructura-de-datos-559abe4db4fe4 48/62
4
if(!nodo) return 0; /* Si no hay nodos en la pila retornamos 0 *//* Asignamos a primero la dirección del segundo nodo */*primero = nodo->siguiente;/* Guardamos el valor de retorno */v = nodo->valor;/* Borrar el nodo */free(nodo);/* Si la cola quedó vacía, ultimo debe ser NULL también*/if(!*primero) *ultimo = NULL;return v;
}
5/8/2018 Estructura de datos - slidepdf.com
http://slidepdf.com/reader/full/estructura-de-datos-559abe4db4fe4 49/62
4
Pregunt as de autoevaluación.
5/8/2018 Estructura de datos - slidepdf.com
http://slidepdf.com/reader/full/estructura-de-datos-559abe4db4fe4 50/62
4
TEMA 6
ARBOLES.
Identificar y usar el tipo de estructura conocida como árbol para dar solución a necesidades de
organización de datos que se presenten.
6.1 Definición de árbol.
Un árbol es una estructura no lineal en la que cada nodo puede apuntar a uno o varios nodos.
También se suele dar una definición recursiva: un árbol es una estructura en compuesta por un
dato y varios árboles, la forma gráfica se puede apreciar como sigue:
En relación 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 posición dentro del árbol, encontramos:
y Nodo raíz: nodo que no tiene padre. Este es el nodo que usaremos para referirnos al
árbol. En el ejemplo, ese nodo es el 'A'.
y Nodo hoja: nodo que no tiene hijos. En el ejemplo hay varios: 'F', 'H', 'I', 'K', 'L', 'M', 'N' y
'O'.
5/8/2018 Estructura de datos - slidepdf.com
http://slidepdf.com/reader/full/estructura-de-datos-559abe4db4fe4 51/62
5
y Nodo rama: aunque esta definición apenas la usaremos, estos son los nodos que no
pertenecen a ninguna de las dos categorías 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 raíz de un árbol completo.
5/8/2018 Estructura de datos - slidepdf.com
http://slidepdf.com/reader/full/estructura-de-datos-559abe4db4fe4 52/62
5
6.2 Árboles binarios.
Los árboles de orden dos son bastante especiales, de hecho les dedicaremos varios capítulos.
Estos árboles se conocen también como árboles binarios.
Frecuentemente, aunque no es estrictamente necesario, para hacer más fácil el moverse a través
del árbol, se añade un puntero a cada nodo que apunte al nodo padre. De este modo podremos
avanzar en dirección a la raíz, y no sólo hacia las hojas.
Un árbol binario esta vacío o consta de un nodo denominado raíz junto con dos árboles binarios
llamados subárbol izquierdo y subárbol derecho de la raíz.
Además de que los árboles binarios se emplean para búsquedas, la recuperación de información
es una de las aplicaciones más importantes, y para ello existen los árboles de búsqueda binaria.
5/8/2018 Estructura de datos - slidepdf.com
http://slidepdf.com/reader/full/estructura-de-datos-559abe4db4fe4 53/62
5
6.3 Represent ación de árboles binarios en memoria.
La única manera de construir un árbol binario con un nodo consiste en hacer que el nodo sea su
raíz y que estén vacíos sus subárboles izquierdo y derecho (representan un apuntador a NULL),
esto significa que se trata de un árbol ordinario.
Con dos nodos en el árbol, uno de ellos será la raíz y el otro estará en un subárbol. Así, uno de los
subárboles de la izquierda o derecha debe estar vacío y el otro contendrá un nodo. De ahí que
haya dos árboles binarios diferentes con dos nodos.
En el caso de un árbol binario con tres nodos, uno de estos será la raíz y los otros dos se dividirán
entre los subárboles 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 vacío, en el primer caso da dos
árboles binarios. El tercero también lo hace. En el segundo caso, los subárboles 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 representación natural en el almacenamiento de listas ligadas.
5/8/2018 Estructura de datos - slidepdf.com
http://slidepdf.com/reader/full/estructura-de-datos-559abe4db4fe4 54/62
5
6.4Recorrido de árboles.
El modo evidente de moverse a través de las ramas de un árbol es siguiendo los punteros, del
mismo modo en que nos movíamos a través de las listas.
Esos recorridos dependen en gran medida del tipo y propósito 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 raíz:
RecorrerArbol(raiz);
La función RecorrerArbol, aplicando recursividad, será tan sencilla como invocar de nuevo a la
función 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 métodos de recorrer el árbol no es el sistema de hacerlo, sino el
momento que elegimos para procesar el valor de cada nodo con relación a los recorridos de cada
una de las ramas.
Los tres tipos son:
5/8/2018 Estructura de datos - slidepdf.com
http://slidepdf.com/reader/full/estructura-de-datos-559abe4db4fe4 55/62
5
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í:
A B E K F C G L M D H I J N O
In-orden:
En este tipo de recorrido, el valor del nodo se procesa después de recorrer la primera rama y antes
de recorrer la última. Esto tiene más sentido en el caso de árboles binarios, y también 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í:
K E B F A L G M C H D I N J O
Post-orden:
En este tipo de recorrido, el valor del nodo se procesa después 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
5/8/2018 Estructura de datos - slidepdf.com
http://slidepdf.com/reader/full/estructura-de-datos-559abe4db4fe4 56/62
5
6.5 Arboles binarios de búsqueda.
Se trata de árboles de orden 2 en los que se cumple que para cada nodo, el valor del nodo raíz del
subárbol izquierdo es menor que el valor del nodo raíz y que el valor del nodo raíz del subárbol
derecho es mayor que el valor del nodo raíz.
5/8/2018 Estructura de datos - slidepdf.com
http://slidepdf.com/reader/full/estructura-de-datos-559abe4db4fe4 57/62
5
6.6Búsqueda e inserción de árboles binarios de búsqueda.
Buscar un elemento.
Partiendo siempre del nodo raíz, el modo de buscar un elemento se define de forma recursiva
como:
Si el árbol está vacío, terminamos la búsqueda: el elemento no está en el árbol.
Si el valor del nodo raíz es igual que el del elemento que buscamos, terminamos la
búsqueda con éxito.
Si el valor del nodo raíz es mayor que el elemento que buscamos, continuaremos la
búsqueda en el árbol izquierdo.
Si el valor del nodo raíz es menor que el elemento que buscamos, continuaremos la
búsqueda en el árbol derecho.
El valor de retorno de una función de búsqueda en un ABB puede ser un puntero al nodoencontrado, o NULL, si no se ha encontrado.
Insertar un elemento.
Para insertar un elemento nos basamos en el algoritmo de búsqueda. Si el elemento está en el
árbol no lo insertaremos. Si no lo está, lo insertaremos a continuación del último nodo visitado.
Para ello, se necesita un puntero auxiliar para conservar una referencia al padre del nodo raíz
actual. El valor inicial para ese puntero es NULL.
y Padre = NULL
y nodo = Raiz
y Bucle: mientras actual no sea un árbol vacío o hasta que se encuentre el elemento. o Si el valor del nodo raíz es mayor que el elemento que buscamos, continuaremos
la búsqueda en el árbol izquierdo: Padre=nodo, nodo=nodo->izquierdo
o Si el valor del nodo raíz es menor que el elemento que buscamos, continuaremos
la búsqueda en el árbol derecho: Padre=nodo, nodo=nodo->derecho.
y Si nodo no es NULL, el elemento está en el árbol, por lo tanto salimos.
y Si Padre es NULL, el árbol estaba vacío, por lo tanto, el nuevo árbol sólo contendrá elnuevo elemento, que será la raíz del árbol.
y Si el elemento es menor que el Padre, entonces insertamos el nuevo elemento como un
nuevo árbol izquierdo de Padre.
y Si el elemento es mayor que el Padre, entonces insertamos el nuevo elemento como un
nuevo árbol derecho de Padre.
Este modo de actuar asegura que el árbol sigue siendo ABB.
5/8/2018 Estructura de datos - slidepdf.com
http://slidepdf.com/reader/full/estructura-de-datos-559abe4db4fe4 58/62
5
6.7 Árboles degenerados.
Los árboles binarios de búsqueda 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
Difícilmente podremos llamar a la estructura resultante un árbol:
Esto es lo que llamamos un árbol binario de búsqueda degenerado, y el árbol AVL, es la estructura
que resuelve este problema, generando árboles de búsqueda equilibrados.
5/8/2018 Estructura de datos - slidepdf.com
http://slidepdf.com/reader/full/estructura-de-datos-559abe4db4fe4 59/62
5
6.8 Aplicaciones 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,
podríamos considerar que los nodos hoja son archivos y los nodos rama son directorios.
Otro ejemplo podría ser la tabla de contenido de un libro, por ejemplo de este mismo manual,
dividido en capítulos, y cada uno de ellos en subcapítulos. Aunque el libro sea algo lineal, como
una lista, en el que cada capítulo sigue al anterior, también es posible acceder a cualquier punto
de él a través de la tabla de contenido.
También se suelen organizar en forma de árbol los organigramas de mando en empresas o en el
ejército, y los árboles genealógicos.
5/8/2018 Estructura de datos - slidepdf.com
http://slidepdf.com/reader/full/estructura-de-datos-559abe4db4fe4 60/62
5
Pregunt as de autoevaluación.
5/8/2018 Estructura de datos - slidepdf.com
http://slidepdf.com/reader/full/estructura-de-datos-559abe4db4fe4 61/62
6
CONCLUSIONES
Las estructuras de datos y algoritmos que faciliten su comprensión y desarrollo, constituyen
elementos básicos en el almacenamiento y tratamiento de la información.
El entendimiento y conocimiento del concepto de estructuras y sus representaciones y métodos
que desembocan en el desarrollo de programas constituyen un previo indispensable para
introducirse en el ámbito de la programación.
5/8/2018 Estructura de datos - slidepdf.com
http://slidepdf.com/reader/full/estructura-de-datos-559abe4db4fe4 62/62
6
BIBLIOGRAFÍA
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, abstracción y objetos.Luis Joyanes Aguilar, Ignacio Zahonero Martínez.
McGraw Hill.
Guia de Autoenseñanza C++
Herbert Schildt
McGraw Hill.
Manual de Estructuras dinámicas de datos.
Salvador Pozo.