191
UNIVERSIDAD NACIONAL ABIERTA Y A DISTANCIA UNAD ESCUELA DE CIENCIAS BÁSICAS TECNOLOGÍA E INGENIERÍA CONTENIDO DIDÁCTICO DEL CURSO: 301305 ESTRUCTURA DE DATOS UNIVERSIDAD NACIONAL ABIERTA Y A DISTANCIA ESCUELA DE CIENCIAS BÁSICAS TECNOLOGÍA E INGENIERÍA PROGRAMA INGENIERÍA DE SISTEMAS 301305 ESTRUCTURA DE DATOS HERMES MOSQUERA ANGULO (Director Nacional) CARLOS ROBERTO ROJAS Acreditador POPAYAN Enero de 2011

301305 Estructura de Datos

Embed Size (px)

Citation preview

Page 1: 301305 Estructura de Datos

UNIVERSIDAD NACIONAL ABIERTA Y A DISTANCIA – UNAD ESCUELA DE CIENCIAS BÁSICAS TECNOLOGÍA E INGENIERÍA CONTENIDO DIDÁCTICO DEL CURSO: 301305 – ESTRUCTURA DE DATOS

UNIVERSIDAD NACIONAL ABIERTA Y A DISTANCIA

ESCUELA DE CIENCIAS BÁSICAS TECNOLOGÍA E INGENIERÍA

PROGRAMA INGENIERÍA DE SISTEMAS

301305 – ESTRUCTURA DE DATOS

HERMES MOSQUERA ANGULO

(Director Nacional)

CARLOS ROBERTO ROJAS

Acreditador

POPAYAN

Enero de 2011

Page 2: 301305 Estructura de Datos

UNIVERSIDAD NACIONAL ABIERTA Y A DISTANCIA – UNAD ESCUELA DE CIENCIAS BÁSICAS TECNOLOGÍA E INGENIERÍA CONTENIDO DIDÁCTICO DEL CURSO: 301305 – ESTRUCTURA DE DATOS

INDICE DE CONTENIDO

UNIDAD 1. MEMORIA DINÁMICA……………..……………………………………..13

CAPITULO 1: APUNTADORES ........................................................................... 15

Lección 1: Conceptos básicos de apuntadores .................................................. 15

Lección 2: Variables Automáticas y Apuntadores .............................................. 18

Lección 3: Apuntadores y Cadenas ................................................................... 21

Lección 4: Paso de Arreglos Como Parámetros ................................................ 23

Lección 5: Apuntadores a Apuntadores ............................................................. 27

CAPITULO 2: GESTIÓN DINÁMICA DE MEMORIA ............................................ 31

Lección 6: Conceptos Básicos de Memoria ....................................................... 31

Lección 7: Tipos de datos comunes ................................................................... 32

Lección 8: Tipos de Variables ............................................................................ 35

Lección 9: Variables Dinámicas ......................................................................... 36

Lección 10: Asignar y Liberar Espacios de Memoria ......................................... 37

CAPITULO 3: OPERADORES Y FUNCIONES EN LA GESTIÓN DE MEMORIA .............................................................................................................................. 40

Lección 11: Operadores New y Delete ............................................................... 40

Lección 12: Más acerca de la Implementación de New y Delete ....................... 44

Lección 13: Funciones Malloc() y Free() ............................................................ 47

Lección 14: Aplicación a la asignación de memoria con Malloc() y Free() ......... 48

Lección 15: Otras funciones para asignar memoria dinámica ............................ 50

Page 3: 301305 Estructura de Datos

UNIVERSIDAD NACIONAL ABIERTA Y A DISTANCIA – UNAD ESCUELA DE CIENCIAS BÁSICAS TECNOLOGÍA E INGENIERÍA CONTENIDO DIDÁCTICO DEL CURSO: 301305 – ESTRUCTURA DE DATOS

UNIDAD 2. ESTRUCTURAS DE DATOS LINEALES……………………….……...56

CAPITULO 4: PILAS ............................................................................................ 59

Lección 1: Conceptos básicos de pilas .............................................................. 59

Lección 2: Operaciones realizadas con pilas ..................................................... 60

Lección 3: Operaciones básicas con pilas paso a paso ..................................... 62

Lección 4: Análisis del código propuesto para implementar una pila ................. 70

Lección 5: Aplicación de las estructuras lineales tipo pilas ................................ 75

CAPITULO 5: COLAS .......................................................................................... 82

Lección 6: Conceptos básicos de colas ............................................................. 82

Lección 7: Operaciones básicas con colas ........................................................ 84

Lección 8: Implementación de las Colas por medio de Punteros ....................... 87

Lección 9: Implementación del código completo de la cola ............................... 90

Lección 10: Aplicación de una cola en un entorno real planificador de citas ..... 93

CAPITULO 6: LISTAS .......................................................................................... 97

Lección 11: Concepto básicos de Listas ............................................................ 97

Lección 12: Listas enlazadas ............................................................................. 99

Lección 13: Más a cerca de listas enlazadas ................................................... 105

Lección 14: Listas doblemente enlazadas ....................................................... 109

Lección 15: Listas circulares ............................................................................ 117

UNIDAD 3. ESTRUCTURAS DE DATOS NO LINEALES……….………...……..125

CAPITULO 7: ÁRBOLES ................................................................................... 131

Lección 1: Teoría general de Árboles .............................................................. 131

Lección 2: Otros conceptos de la teoría general de árboles ........................... 132

Lección 3: Árbol completo ................................................................................ 133

Page 4: 301305 Estructura de Datos

UNIVERSIDAD NACIONAL ABIERTA Y A DISTANCIA – UNAD ESCUELA DE CIENCIAS BÁSICAS TECNOLOGÍA E INGENIERÍA CONTENIDO DIDÁCTICO DEL CURSO: 301305 – ESTRUCTURA DE DATOS

Lección 4: Estructura para la creación de un árbol de orden tres .................... 134

Lección 5. Introducción al Modo Gráfico de C++ ............................................. 136

CAPITULO 8: ÁRBOLES BINARIOS ................................................................. 142

Lección 6: Conceptualización de Arboles Binarios........................................... 142

Lección 7: Clasificación de los árboles binarios ............................................. 1477

Lección 8: Formas de Recorrer un Árbol Binario ............................................. 149

Lección 9: Ábol binario de búsqueda (ABB) ..................................................... 154

Lección 10: Operaciones en ABB .................................................................... 157

CAPITULO 3: GRAFOS...................................................................................... 176

Lección 11: Conceptos básicos de grafos ........................................................ 176

Lección 12: Grafo no dirigido ........................................................................... 178

Lección 13: Representación de los grafos ..................................................... 1800

Lección 14: Representación mediante listas de Adyacencia ......................... 1833

Lección 15: Exploración de grafos ................................................................. 1855

Page 5: 301305 Estructura de Datos

UNIVERSIDAD NACIONAL ABIERTA Y A DISTANCIA – UNAD ESCUELA DE CIENCIAS BÁSICAS TECNOLOGÍA E INGENIERÍA CONTENIDO DIDÁCTICO DEL CURSO: 301305 – ESTRUCTURA DE DATOS

LISTADO DE TABLAS

Tabla 1………………………………………………………………………………….30

Tabla 2………………………………………………………………………………….31

Page 6: 301305 Estructura de Datos

UNIVERSIDAD NACIONAL ABIERTA Y A DISTANCIA – UNAD ESCUELA DE CIENCIAS BÁSICAS TECNOLOGÍA E INGENIERÍA CONTENIDO DIDÁCTICO DEL CURSO: 301305 – ESTRUCTURA DE DATOS

LISTADO DE GRÁFICOS Y FIGURAS

Figura 1 Salida en pantallade progra1.cpp ............................................................ 17

Figura 2 Salida en pantalla de progra2.cpp ........................................................... 19

Figura 3 Salida en pantalla de progra3.cpp ........................................................... 21

Figura 4 Salida en pantalla de progra4.cpp ........................................................... 22

Figura 5 Salida en pantalla de progra5.cpp ........................................................... 23

Figura 6 Salida en pantalla de progra6.cpp ........................................................... 25

Figura 7 Salida en pantalla de progra7.cpp ........................................................... 26

Figura 8 Salida en pantalla de progra8.cpp ........................................................... 27

Figura 9 Salida en pantalla de progra9.cpp ........................................................... 28

Figura 10 Salida en pantalla de progra10.cpp ....................................................... 30

Figura 11 Salida en pantalla de progra11.cpp ....................................................... 34

Figura 12 Salida en pantalla de progra12.cpp ....................................................... 36

Figura 13Salida en pantalla de progra13.cpp ........................................................ 37

Figura 14 Salida en pantalla de progra14.cpp ....................................................... 39

Figura 15 Salida en pantalla de progra15.cpp ....................................................... 42

Figura 16 Salida en pantalla de progra16.cpp ....................................................... 45

Figura 17 Salida en pantalla de progra17.cpp ....................................................... 46

Figura 18 Salida en pantalla de progra18.cpp ....................................................... 48

Figura 19 Salida en pantalla de progra19.cpp ....................................................... 50

Figura 20 Representación gráfica de una pila de monedas .................................. 60

Figura 21 Entrada y salida de elementos de una pila ............................................ 61

Page 7: 301305 Estructura de Datos

UNIVERSIDAD NACIONAL ABIERTA Y A DISTANCIA – UNAD ESCUELA DE CIENCIAS BÁSICAS TECNOLOGÍA E INGENIERÍA CONTENIDO DIDÁCTICO DEL CURSO: 301305 – ESTRUCTURA DE DATOS

Figura 22 Declaración de la estructura pila ........................................................... 64

Figura 23 Menú de opciones de la pila .................................................................. 66

Figura 24 Definición de la función insertar() .......................................................... 66

Figura 25 La función insertar() en el case 1 .......................................................... 67

Figura 26 Instrucciones de la función insertar() ..................................................... 68

Figura 27 Vista de la definición de las funciones insertar, visualizar y extraer ...... 70

Figura 28 Salida en pantalla de Progra21.cpp ...................................................... 75

Figura 29 Salida en pantalla de Progra22.cpp ...................................................... 78

Figura 30 Salida en pantalla de Progra23.cpp ...................................................... 81

Figura 31 Representación gráfica de una cola de personas. ................................ 83

Figura 32 Representación gráfica de una cola ...................................................... 84

Figura 33 Salida en pantalla de progra24.............................................................. 87

Figura 34 Salida en pantalla de Progra25.cpp ...................................................... 93

Figura 35 Salida en pantalla de progra26.cpp ....................................................... 96

Figura 36 Representación gráfica de una lista contigua ........................................ 99

Figura 37 Representación gráfica de listas enlazadas ........................................ 100

Figura 38 Salida en pantalla de Progra27.cpp .................................................... 105

Figura 39 Salida en pantalla de progra28.cpp ..................................................... 106

Figura 40 Salida en pantalla de progra29.cpp ..................................................... 108

Figura 41 Representación gráfica de una lista doblemente enlazada ................. 109

Figura 42 Salida en pantalla de progra30.cpp ..................................................... 117

Figura 43 Representación gráfica de una Lista Circular ...................................... 118

Figura 44 Lista circular simplemente enlazada ................................................... 119

Figura 45 Lista circular doblemente enlazada ..................................................... 119

Page 8: 301305 Estructura de Datos

UNIVERSIDAD NACIONAL ABIERTA Y A DISTANCIA – UNAD ESCUELA DE CIENCIAS BÁSICAS TECNOLOGÍA E INGENIERÍA CONTENIDO DIDÁCTICO DEL CURSO: 301305 – ESTRUCTURA DE DATOS

Figura 46 Primer nodo de la lista circular ............................................................ 120

Figura 47 Inserción del segundo nodo ................................................................ 120

Figura 48 Nuevo nodo insertado en la lista circular ............................................. 121

Figura 49 Salida en pantalla de progra31.cpp ..................................................... 124

Figura 50 Representación gráfica de árboles ...................................................... 132

Figura 51 Interfaz gráfica del compilador Borland C++ 5.5. ................................ 138

Figura 52 Activación de las librerías Gráficas .......... ¡Error! Marcador no definido.

Figura 53 Configuración de directorio para BGI .................................................. 139

Figura 54 Interfaz de directorios de C++. ............................................................ 139

Figura 55 Inclusión de la ruta C:\TC\BGI ............................................................. 140

Figura 56 Salida en pantalla de progra32 Modo grafico de C++. ........................ 141

Figura 57 Estructura de un árbol binario ............................................................. 142

Figura 58 Representación gráfica de un árbol binario ......................................... 143

Figura 59 Representación gráfica del subárbol izquierdo.................................... 143

Figura 60 Representación gráfica del subárbol derecho ..................................... 144

Figura 61 Representación gráfica de un nodo padre .......................................... 144

Figura 62 Representación gráfica de un nodo hoja ............................................. 145

Figura 63 Camino del árbol ................................................................................. 145

Figura 64 Longitud del árbol binario .................................................................... 146

Figura 65 Nivel del árbol...................................................................................... 147

Figura 66 Representación gráfica de un árbol binario completo. ........................ 147

Figura 67 Representación gráfica de Árbol binario igual ..................................... 148

Figura 68 Representación gráfica de árboles semejantes................................... 149

Figura 69 Representación gráfica de árboles isomorfos ..................................... 149

Page 9: 301305 Estructura de Datos

UNIVERSIDAD NACIONAL ABIERTA Y A DISTANCIA – UNAD ESCUELA DE CIENCIAS BÁSICAS TECNOLOGÍA E INGENIERÍA CONTENIDO DIDÁCTICO DEL CURSO: 301305 – ESTRUCTURA DE DATOS

Figura 70 Recorrido del árbol binario en preorden ............................................. 150

Figura 71 Resultado del recorrido en preorden del árbol .................................... 150

Figura 72 Representación gráfica del recorrido en Inorden................................. 152

Figura 73 Recorrido en Postorden del árbol binario. ........................................... 153

Figura 74 Árbol binario como aplicación a los tres recorridos ............................. 154

Figura 75 Borrado de un nodo rama con intercambio de nodo hoja .................... 157

Figura 76 Representación gráfica de un árbol binario de búsqueda ................... 158

Figura 77 Borrado de un nodo rama con intercambio de nodo rama .................. 158

Figura 78 Intercambio de un nodo rama con intercambio de nodo rama ............ 159

Figura 79 Salida en pantalla de progra34............................................................ 167

Figura 80 Representación gráfica de los grafos .................................................. 177

Figura 81 Representación gráfica de un gráfo dirigido ........................................ 178

Figura 82 Representación gráfica de un grafo no dirigido ................................... 178

Figura 83 Representación gráfica de grafos etiquetados .................................... 179

Figura 84 Representación gráfica de la longitud del camino de un grafo ............ 179

Figura 85 Grafo dirigido ...................................................................................... 181

Figura 86 Representación gráfica de la matriz de adyacencia ............................ 181

Figura 87 Representación gráfica de un grafo por lista de adyacencia ............... 183

Figura 88 Representación grafica de un grafo .................................................... 186

Page 10: 301305 Estructura de Datos

UNIVERSIDAD NACIONAL ABIERTA Y A DISTANCIA – UNAD ESCUELA DE CIENCIAS BÁSICAS TECNOLOGÍA E INGENIERÍA CONTENIDO DIDÁCTICO DEL CURSO: 301305 – ESTRUCTURA DE DATOS

ASPECTOS DE PROPIEDAD INTELECTUAL Y VERSIONAMIENTO

La versión uno del presente módulo fue diseñado en el año 2004 por el Ing. Iván Arturo López, docente de la UNAD, ubicado en el CEAD de Popayán, el Ing. López es Ingeniero de Sistemas, Especialista en Pedagogía Para el Desarrollo del Aprendizaje Autónomo y Magister en Educación y TIC’s, se ha desempeñado como Tutor y Docente de la UNAD desde el año 2000. La versión dos del presente módulo fue desarrollada por el Ing. Hermes Mosquera Angulo en el año 2007, quien ha sido Tutor de la UNAD en el CEAD Popayán, desde el año 2006, se desempeña actualmente como Director del cuso a nivel nacional desde el año 2007.

Page 11: 301305 Estructura de Datos

UNIVERSIDAD NACIONAL ABIERTA Y A DISTANCIA – UNAD ESCUELA DE CIENCIAS BÁSICAS TECNOLOGÍA E INGENIERÍA CONTENIDO DIDÁCTICO DEL CURSO: 301305 – ESTRUCTURA DE DATOS

INTRODUCCIÓN

El curso de estructura de datos cobra vital importancia en la aplicación de la programación estructurada y al cual se le puede sacar el máximo provecho, puesto que se requiere que los estudiantes que abordan el curso tengan los conocimientos previos, tratados en los cursos anteriores de Algoritmos e Introducción a la programación. Estructura de datos es un curso metodológico de compuesto de tres unidades didácticas en donde se combina la parte teórica con la parte práctica, con el desarrollo de pequeños programas de aplicación basados en entornos reales.

En ese sentido, el curso inicia con la primera unidad en la que se tratan temas como los fundamentos básicos de apuntadores, asignación dinámica de memoria al igual que los operadores y funciones para la gestión de memoria. Se propone una metodología de trabajo en la que se invita al estudiante a realizar una lectura detallada de cada lección con el propósito de profundizar en la conceptualización; posteriormente en la mayoría de temas se proponen códigos fuente completos que sirven como ejemplos de programas de aplicación a la temática tratada. Estos códigos pueden ser llevados a cualquier compilador de C++, para el curso se propone el compilador Turbo C++ 3.0 para plataformas Windows XP y el compilador Borland C++ 5.5 para plataformas Windows Vista y Windows 7, por su facilidad de uso amigabilidad y preconfiguración, para el caso de plataforma Linux puede emplearse el editor que trae por defecto para programas C++. Los compiladores pueden ser descargados directamente del sitio https://sites.google.com/site/hhmosquera/file-cabinet.

En la segunda unidad se profundiza en temas relacionados con las estructuras de datos lineales, donde se abordan los temas como pilas, colas, listas, desarrollados con apuntadores, brindando al estudiante los fundamentos y competencias necesarias para brindar soluciones en programación a entornos reales.

Final en la tercera unidad se continúa con la profundización y aplicación de las estructura de datos no lineales se podría hablar de estructuras jerárquicas con los temas de árboles y grafos los cuales inducen al estudiante a trabajar con el modo gráfico de C++ como acercamiento a la programación orientada a objetos. En el curso se incluyen ejercicios prácticos, realizados por diferentes autores, sitios web como referencia y una amplia bibliografía externa y también existente en la biblioteca virtual de la UNAD, que sin duda llevara al estudiante a un aprendizaje autónomo y significativo.

Page 12: 301305 Estructura de Datos

12

UNIVERSIDAD NACIONAL ABIERTA Y A DISTANCIA – UNAD ESCUELA DE CIENCIAS BÁSICAS TECNOLOGÍA E INGENIERÍA CONTENIDO DIDÁCTICO DEL CURSO: 301305 – ESTRUCTURA DE DATOS

UNIDAD 1

Nombre de la Unidad MEMORIA DINÁMICA

Introducción

La memoria del computador es un recurso invaluable de mucha importancia en el procesamiento de información, que requiere darle un buen uso por parte de los programadores con el fin de optimizar espacios en memoria. Por esta razón, en esta, la primera unidad del curso, se hace una introducción a conceptos básicos como apuntadores, asignación dinámica de memoria y operadores como new y delete propios de C++ y funciones como Malloc() y free(), propios de C.

Igualmente están implícitas diferentes estrategias de pensamiento de orden superior que el estudiante irá descubriendo gracias al apoyo permanente del tutor, quien en es el mediador del proceso de aprendizaje.

En el transcurso de la unidad, se desarrollan actividades que buscan determinar el grado de apropiación del conocimiento, basados en los tres momentos: reconocimiento, profundización y transferencia, sin dejar al lado el desarrollo del componente práctico que tiene como finalidad afianzar los conocimientos en pro de lograr la competencia del curso.

Justificación

La memoria de la computadora es un recurso invaluable y finito en cuanto asu capacidad, con muchos usos. Para el caso de los programadores de computados, solo uno y es guardar información. Por tal razón es importante darle un buen manejo a la memoria y esto se puede hacer cuando en el desarrollo de programas informáticos, se hace una buena definición de las de variables de acuerdo al tipo de información que se requiera almacena. Los datos significan la información con la cual trabaja un programa. En este mundo competitivo quien tiene la información tiene el poder. Ya sea que el programa esté trabajando con una lista de direcciones, monitoreando la bolsa de valores, manejando el presupuesto nacional o

Page 13: 301305 Estructura de Datos

13

UNIVERSIDAD NACIONAL ABIERTA Y A DISTANCIA – UNAD ESCUELA DE CIENCIAS BÁSICAS TECNOLOGÍA E INGENIERÍA CONTENIDO DIDÁCTICO DEL CURSO: 301305 – ESTRUCTURA DE DATOS

cualquier otra situación, la información (nombres, precios de acciones, gastos) es guardada en la RAM de la computadora mientras el programa se esté ejecutando.

Entra aquí el concepto de la gestión dinámica de memoria y los apuntadores, como un tipo de variables que permiten por medio de funciones y operadores asignar y liberar memoria dinámicamente en tiempo de ejecución, es decir mientras el programa está en marcha. Profundizar en la conceptualización del tipo de datos y los bytes requeridos que se manejan en el leguaje C++ contribuye al buen desarrollo de programas informáticos.

Intencionalidades Formativas

Conocer y aplicar el funcionamiento de las estructuras de datos lineales. Profundizar en aspectos básicos en apuntadores y la asignación dinámica de memoria.

Diferenciar Conceptualmente el uso y la aplicación de las variables estáticas y las variables dinámicas. Aplicar la conceptualización de los operadores y funciones para el manejo de la memoria dinámica. Realizar aplicaciones en lenguaje C++ utilizando estructuras dinámicas de memoria

Capítulo 1 APUNTADORES Lección 1 Conceptos básicos de apuntadores Lección 2 Variables Automáticas y Apuntadores Lección 3 Apuntadores y Cadenas Lección 4 Paso de Arreglos Como Parámetros Lección 5 Apuntadores a Apuntadores Capítulo 2 GESTIÓN DINÁMICA DE MEMORIA Lección 6 Conceptos Básicos de Memoria Lección 7 Tipos de datos comunes Lección 8 Tipos de Variables Lección 9 Variables Dinámicas Lección 10 Asignar y Liberar Espacios de Memoria Capítulo 3 OPERADORES Y FUNCIONES PARA LA GESTIÓN DE

MEMORIA Lección 11 Operadores New y Delete Lección 12 Más acerca de la Implementación de New y Delete

Page 14: 301305 Estructura de Datos

14

UNIVERSIDAD NACIONAL ABIERTA Y A DISTANCIA – UNAD ESCUELA DE CIENCIAS BÁSICAS TECNOLOGÍA E INGENIERÍA CONTENIDO DIDÁCTICO DEL CURSO: 301305 – ESTRUCTURA DE DATOS

Lección 13 Funciones Malloc() y Free() Lección 14 Aplicación a la asignación de memoria con Malloc() y

Free() Lección 15 Otras funciones para asignar memoria dinámica

Page 15: 301305 Estructura de Datos

15

UNIVERSIDAD NACIONAL ABIERTA Y A DISTANCIA – UNAD ESCUELA DE CIENCIAS BÁSICAS TECNOLOGÍA E INGENIERÍA CONTENIDO DIDÁCTICO DEL CURSO: 301305 – ESTRUCTURA DE DATOS

CAPITULO 1: APUNTADORES

Introducción

En el presente capitulo se aborda la temática de los apuntadores y la aplicabilidad que tienen en el campo de la programación estructurada. Los apuntadores son un tipo especial de variables que guardan direcciones de otras variables. en los lenguajes de programación de C y C++. Proporcionan mucha utilidad al programador ya que permiten accesar y manipular datos de tal manera que no es posible realizarse en otros lenguajes llamados de alto nivel. Tambien son utiles para pasarle parametros a las funciones de tal modo que les permiten modificar y regresar valores a la rutina o función que hace el llamado. Cuando se utilizan incorrectamente, pueden producir algunos problemas de esrtabilidad en el sistema o también pueden presentar fallas en el programa en ejecución. De igualmanera se llevarán a cabo aplicaciones pequeñas de programas codificados en C++ como aplicación al uso de los apuntadores y a las operaciones que se pueden llevar a cabo. Cada uno de estos programas presenta en una figura la salida en pantalla, es decir todos están previamente compilados y depurados. Lección 1: Conceptos básicos de apuntadores Antes de definir qué es un puntero, veremos primero cómo se almacenan los datos en un computador. La memoria de un computador está compuesta por unidades básicas llamadas bits. Cada bit sólo puede tomar dos valores, normalmente denominados alto y bajo, ó 1 y 0. Pero trabajar con bits no es práctico, por eso se agrupan. Cada grupo de 8 bits forma un byte u octeto. En realidad el microprocesador, y por lo tanto nuestro programa, sólo puede manejar directamente bytes o grupos de dos o cuatro bytes. Para acceder a los bits hay que acceder antes a los bytes. Cada byte tiene una dirección, llamada normalmente dirección de memoria.

Definición de Apuntadores Un apuntador es una variable, que almacena como contenido una dirección de memoria, de otra variable a la que apunta, dicha dirección representa el lugar donde se almacena un dato. Los apuntadores tienen un tipo de dato específico y

Page 16: 301305 Estructura de Datos

16

UNIVERSIDAD NACIONAL ABIERTA Y A DISTANCIA – UNAD ESCUELA DE CIENCIAS BÁSICAS TECNOLOGÍA E INGENIERÍA CONTENIDO DIDÁCTICO DEL CURSO: 301305 – ESTRUCTURA DE DATOS

solo pueden apuntar a espacios de memoria con datos del mismo tipo. Por supuesto, a partir de esa dirección de memoria puede haber cualquier tipo de objeto: un char, un int, un float, un array, una estructura, una función u otro puntero. Serán los programadores los responsables de decidir ese contenido. Con los apuntadores es posible manipular estructuras de datos o asignar memoria dinámica. Los apuntadores son una de las herramientas más poderosas con que cuenta el Lenguaje C++. Desafortunadamente, muchos programadores han creado el mito de que el estudio de los apuntadores es muy complicado, lo cual ha desarrollado una fobia entre quienes se inician en el estudio de las estructuras dinámicas en lenguaje C++. Declaración de apuntadores Los apuntadores son variables automáticas cuyos valores representan direcciones de memoria correspondientes a otras variables del mismo tipo a las que apunta. La sintaxis para la declaración de una variable de tipo apuntador es la siguiente: tipo * identificador ; Donde, tipo hace referencia al tipo de datos de C++ como int, char, float, entre otros e identificador, hace referencia al nombre de la variable apuntador. Ejemplo: int *apunt; se declara el apuntador apunt de tipo entero. Se dice que: "apunt va a apuntar a variables de tipo int" donde apunt es el nombre del apuntador y (*) es el operador de indirección que indica que apunt es un apuntador.

En el ejemplo anterior, puede decirse que: *apunt se refiere al objeto apuntado por apunt. apunt es un apuntador a objetos de tipo int Observe que el operador de indirección utiliza el mismo símbolo que el operador de multiplicación. En este caso el asterisco le indica al sistema que se define una variable apuntador. Ejemplos: int *x; x es un apuntador de tipo entero. char *y; y es un apuntador de tipo carácter. double *r, *s; r y s son apuntadores de tipo real doble precisión.

Page 17: 301305 Estructura de Datos

17

UNIVERSIDAD NACIONAL ABIERTA Y A DISTANCIA – UNAD ESCUELA DE CIENCIAS BÁSICAS TECNOLOGÍA E INGENIERÍA CONTENIDO DIDÁCTICO DEL CURSO: 301305 – ESTRUCTURA DE DATOS

Operadores para trabajar apuntadores Los operadores utilizados para trabajar variables apuntadores son el ( * ) asterisco llamado operador de indirección, y el ( & ) ampersand, llamado operador de dirección.

* toma su operando como una dirección de memoria y retorna la información almacenada en ese lugar.

& devuelve la dirección de memoria de su operando. Aplicación práctica del uso de apuntadores Progra1.cpp #include <iostream.h> #include <conio.h> void main(void) { int x, y; //Define x, y variables enteras. int *p, *q; //Define p y q variables tipo apuntador. p = &x; //asigna a p la dirección de x. (p apunta a x). q = &y; //asigna a q la dirección de y. (q apunta a y). *p = 10; //almacena en x el valor 10. *q = *p * 2; //almacena en y el valor de x multiplicado por 2 (20). y = y + *p; //a la variable y le suma el valor en x (20+10). cout<<”El contenido de X es:” <<*p <\n; //imprime el contenido de x (10). cout<<,”El contenido de Y es:” <<*q; //imprime el contenido de y (30). getch(); } El resultado de la impresión en pantalla de Progra1 se puede visualizar en la gráfica 1.

Figura 1 Salida en pantallade progra1.cpp

Page 18: 301305 Estructura de Datos

18

UNIVERSIDAD NACIONAL ABIERTA Y A DISTANCIA – UNAD ESCUELA DE CIENCIAS BÁSICAS TECNOLOGÍA E INGENIERÍA CONTENIDO DIDÁCTICO DEL CURSO: 301305 – ESTRUCTURA DE DATOS

Lección 2: Variables Automáticas y Apuntadores Las variables automáticas se crean en tiempo de compilación y se destruyen al terminar la ejecución del módulo donde fueron declaradas. Aunque no es estrictamente necesario, se pueden manejar las variables automáticas por medio de apuntadores, se puede apreciar en el siguiente ejemplo. Implementación de variables automáticas Progra2.cpp #include <iostream.h> #include <conio.h> void main() { int automatica ; int *apunt ; automatica = 100 ; apunt = &automatica ; clrscr(); cout << "VALOR=" << automatica << " \n"; *apunt= 200 ; cout << "VALOR=" << automatica << " \n"; getch(); } Análisis de Progr2.cpp Progra2.cpp es el nombre del programa con su respectiva extensión .cpp. En la línea 1 y 2, se incluyen las librería o archivos de cabecera necesarios para el buen funcionamiento del programa y soportar la sintaxis del lenguaje, se pueden incluir otras según se requieran. En la línea 3, se define la función principal main() de tipo void, lo que indica que no retorna ningún valor. En la línea 4, se da apertura a la función por medio de una llave, dentro de ella van las instrucciones del programa y se cierra cuando finalizan las instrucciones o el código. En la línea 5, se declara la variable llamada automática que es de tipo entero. En la línea 6, se declara el apuntador llamado apunt, de tipo entero, que apunta a objetos de tipo int.

Page 19: 301305 Estructura de Datos

19

UNIVERSIDAD NACIONAL ABIERTA Y A DISTANCIA – UNAD ESCUELA DE CIENCIAS BÁSICAS TECNOLOGÍA E INGENIERÍA CONTENIDO DIDÁCTICO DEL CURSO: 301305 – ESTRUCTURA DE DATOS

En la línea 7, Se asigna el valor 100 a la variable automatica. En la línea 8, se asigna a apunt la dirección de memoria de la variable automática En la línea 9, se limpia pantalla por medio de la función clrscr() para que las salidas en pantalla de anteriores ejecuciones sigan mostrándose. En la línea 10, se muestra la salida en pantalla del valor de la variable automática que es 100. En la línea 11, se asigna el valor 200 al objeto apuntado por apunt. Es decir a la variable automática. En la línea 12, se muestra en pantalla el nuevo valor que tomó la variable automática que para este caso es 200. En la línea 13 se introduce la función getch() que hace la ejecución del programa termine solo cuando se presione una tecla. Finalmente en la línea 14 se cierra la llave indicando que terminan las instrucciones de la función principal. El resultado de Progra2.cpp se puede observar en la figura 2, que se muestra a continuación. Figura 2 Salida en pantalla de progra2.cpp

Más acerca de apuntadores Un apuntador es una variable que solo puede contener un valor a la vez, por lo que solo puede apuntar a un objeto al mismo tiempo. Por otro lado, una variable cualquiera puede ser apuntada (referenciada) por varios apuntadores, ya que su dirección de memoria puede ser almacenada en distintas variables a la vez.

Page 20: 301305 Estructura de Datos

20

UNIVERSIDAD NACIONAL ABIERTA Y A DISTANCIA – UNAD ESCUELA DE CIENCIAS BÁSICAS TECNOLOGÍA E INGENIERÍA CONTENIDO DIDÁCTICO DEL CURSO: 301305 – ESTRUCTURA DE DATOS

Al declarar un apuntador, se está especificando el tipo de variable al que va a apuntar. Por ejemplo, no podrá declararse un apuntador a objetos de tipo int y después intentar utilizarlo para apuntar a objetos de tipo float. Cuando se desee manejar un apuntador a cualquier tipo de objeto, se puede declarar de tipo void, como en: void *apuntadores ; Aplicación de apuntadores de tipo void En el siguiente listado se muestra un ejemplo de aplicación de un apuntador de tipo void. Progra3.cpp #include <iostream.h> #include <conio.h> void main() { int entero=1 ; float decimal=1.1 ; void *apvarios=&entero; // apvarios APUNTA A entero *(int *)apvarios="1" // ASIGNA 1 AL OBJETO APUNTADO POR apvarios cout << "El valor de entero es: "<<entero<<"\n" ; apvarios=&decimal ; // apvarios APUNTA A decimal *(float *)apvarios="1.1" // ASIGNA 1.1 AL OBJETO APUNTADO POR apvarios cout << "El valor de decimal es: "<<decimal ; getch(); } Análisis de Progra3.cpp Analicemos la siguiente instrucción: *(int *)apvarios = 1 ; En donde: Apvarios, es un apuntador de tipo void. (int *)apvarios está forzando a que apvarios apunte a objetos de tipo int. *(int *)apvarios se refiere a un objeto de tipo entero apuntado por apvarios. En la grafica 1.1 se obtiene la salida en pantalla de Progr3.cpp.

Page 21: 301305 Estructura de Datos

21

UNIVERSIDAD NACIONAL ABIERTA Y A DISTANCIA – UNAD ESCUELA DE CIENCIAS BÁSICAS TECNOLOGÍA E INGENIERÍA CONTENIDO DIDÁCTICO DEL CURSO: 301305 – ESTRUCTURA DE DATOS

Figura 3 Salida en pantalla de progra3.cpp

Lección 3: Apuntadores y Cadenas Una cadena se puede definir como un arreglo de caracteres cuyo último elemento es el caracter nulo. Utilizando la nomenclatura de arreglos, podemos declarar un arreglo llamado nombre[ ] de tipo carácter asignándole la frase COMERCIO: char nombre[ ] = "COMERCIO" ;

La misma asignación puede realizarse por medio de apuntadores, como se observa en el siguiente enunciado. char *nombre = "COMERCIO" ; En este caso se define a nombre como un apuntador que apunta a datos de tipo char, al que se le asigna la frase COMERCIO. Aplicación de apuntadores a cadenas Progra4.cpp

#include <iostream.h> #include <conio.h> #include <stdio.h> void main() { char *nombre = "COMERCIO" ; clrscr(); gotoxy(30,12); cout<< "!! HOLA, " ; puts(nombre); gotoxy(43,12); cout << " !!"; getch(); }

Page 22: 301305 Estructura de Datos

22

UNIVERSIDAD NACIONAL ABIERTA Y A DISTANCIA – UNAD ESCUELA DE CIENCIAS BÁSICAS TECNOLOGÍA E INGENIERÍA CONTENIDO DIDÁCTICO DEL CURSO: 301305 – ESTRUCTURA DE DATOS

En la figura 4, se visualiza la salida en pantalla de progra4.cpp, se presentan dos funciones objeto de análisis.

La función gotoxy() posiciona el mensaje o la salida en pantalla “!! HOLA” en las coordenadas x=30 y y=12.

La función puts() es propia para el manejo de cadena de caracteres, muestra en pantalla el contenido de la variable nombre.

Figura 4 Salida en pantalla de progra4.cpp

Arreglos de apuntadores Los apuntadores pueden manejarse en un arreglo, de tal forma que: char nombres[ ][5] = { "HUGO", "PACO", "LUIS" } ; es la declaración de un arreglo de cadenas, con asignación de valores iniciales. Su equivalente en notación de apuntadores es: char *nombres[ ] = { "HUGO", "PACO", "LUIS" } ;

En el que se declara un arreglo de apuntadores con tres valores asignados. El programa completo para el manejo de este ejemplo se presenta en el Progra5.cpp. Implementación de arreglos de apuntadores Progra5.cpp #include <iostream.h> #include <conio.h> #include <string.h> void main() { char *nombres[ ] = { "HUGO", "PACO", "LUIS" } ;

Page 23: 301305 Estructura de Datos

23

UNIVERSIDAD NACIONAL ABIERTA Y A DISTANCIA – UNAD ESCUELA DE CIENCIAS BÁSICAS TECNOLOGÍA E INGENIERÍA CONTENIDO DIDÁCTICO DEL CURSO: 301305 – ESTRUCTURA DE DATOS

char invitado[11]; int bandera; clrscr(); gotoxy(20,5); cout << "CUAL ES SU NOMBRE ?: " ; gotoxy(50,10); cin>> invitado ; gotoxy(20,7); for( int x = 0 ; x <3 ; x++ ) if(strcmp(invitado, nombres[x])== 0) bandera=0; if(bandera== 0) cout << "!! SIGA AMIGO ES BIENVENIDO " << invitado << " !!"; else cout << "!! USTED NO ES BIENVENIDO, " << invitado << " !!"; getch(); }

En la figura 5, se visualiza el resultado de la salida en pantalla de Progra5.cpp, en el que se incluye la librería <string.h> necesaria para el manejo de cadena de caracteres con las funciones de comparar cadena (strcmp); la cual compara el nombre solicitado por teclado con los nombres asignados al arreglo previamente, en caso de que coincida muestra el primer mensaje de bienvenida, de lo contrario muestra el segundo mensaje.

Figura 5 Salida en pantalla de progra5.cpp

Lección 4: Paso de Arreglos Como Parámetros

Un arreglo puede pasarse como parámetro a una función. Si tuviera que pasarse por valor un arreglo muy grande, sería un desperdicio de memoria y que es función de los programadores optimizar este recurso. En el Lenguaje C++, el paso

Page 24: 301305 Estructura de Datos

24

UNIVERSIDAD NACIONAL ABIERTA Y A DISTANCIA – UNAD ESCUELA DE CIENCIAS BÁSICAS TECNOLOGÍA E INGENIERÍA CONTENIDO DIDÁCTICO DEL CURSO: 301305 – ESTRUCTURA DE DATOS

de arreglos se hace por referencia, ya que el nombre del arreglo corresponde a un apuntador al primer elemento del arreglo. Al pasar un parámetro correspondiente a un arreglo, se pasa la dirección del primer elemento, por lo que la función invocada puede modificar cualquier elemento del arreglo. El siguiente programa maneja una función llamada valor(), la cual recibe como parámetro un arreglo de caracteres. Implementación de paso de arreglos como parámetros Progra6.cpp #include <iostream.h> #include <conio.h> #include <stdio.h> #include <string.h> void valor(char *); void main() { char cadena[81]; clrscr(); gotoxy(10,10); cout << "INGRESE UNA FRASE CORTA: "; gets(cadena); gotoxy(10,12); valor(cadena); getch(); } void valor(char arreglo[ ]) { int x=0; while(arreglo[x]) { cout << arreglo[x] ; x++; } } El resultado de la salida en pantalla de progra6.cpp se visualiza en la figura 6, que se muestra a continuación, en la que un arreglo de caracteres llamado cadena se pasa como parámetros a la función llamada valor.

Page 25: 301305 Estructura de Datos

25

UNIVERSIDAD NACIONAL ABIERTA Y A DISTANCIA – UNAD ESCUELA DE CIENCIAS BÁSICAS TECNOLOGÍA E INGENIERÍA CONTENIDO DIDÁCTICO DEL CURSO: 301305 – ESTRUCTURA DE DATOS

Figura 6 Salida en pantalla de progra6.cpp

Implementación de la función valor() por medio de apuntadores En el siguiente listado se muestra el manejo de la función valor(), por medio de apuntadores. Progra7.cpp #include <iostream.h> #include <conio.h> #include <stdio.h> #include <string.h> void valor(char *); void main() { char cadena[81]; clrscr(); gotoxy(10,5); cout << "ESCRIBA UNA CADENA: "; gets(cadena); gotoxy(10,7); valor(cadena); getch(); } void valor(char *apuntador) { while(*apuntador) cout << *apuntador++ ; } Analizando este listado y comparándolo con el progra6.cpp se observa que la diferencia radica en el parámetro de la función llamada valor() que par este caso es un apuntador de tipo char que guarda una cadena y para el progra6.cpp es un arreglo de caracteres, que igualmente almacena una cadena y posteriormente

Page 26: 301305 Estructura de Datos

26

UNIVERSIDAD NACIONAL ABIERTA Y A DISTANCIA – UNAD ESCUELA DE CIENCIAS BÁSICAS TECNOLOGÍA E INGENIERÍA CONTENIDO DIDÁCTICO DEL CURSO: 301305 – ESTRUCTURA DE DATOS

despliega el resultado, tal como se puede evidenciar en la figura 7, que se muestra a continuación.

Figura 7 Salida en pantalla de progra7.cpp

Paso de funciones como parámetros Toda función tiene asociada una dirección de inicio de código, la cual puede pasarse un apuntador como parámetro cuando se llama o se invoca a otra función. He aquí un ejemplo como aplicación al paso de funciones como parámetros a funciones. Implementación del paso de funciones como parámetros Progra8.cpp #include <iostream.h> #include <string.h> #include <conio.h> int cmpcad(char*, char*); void compara(char*, char*, int(*)(char*, char*)); void main() { char cadenax[80], cadenay[80]; clrscr(); gotoxy(10,5); cout << "ESCRIBA UNA CADENA : " ; cin>> cadenax; gotoxy(10,7); cout << "ESCRIBA OTRA CADENA : " ; cin>> cadenay; gotoxy(10,9); compara(cadenax, cadenay, cmpcad); gotoxy(1,24); } void compara(char *cadena1, char *cadena2, int (*cmpcad)(char*, char*)) { if(!(*cmpcad)(cadena1,cadena2))

Page 27: 301305 Estructura de Datos

27

UNIVERSIDAD NACIONAL ABIERTA Y A DISTANCIA – UNAD ESCUELA DE CIENCIAS BÁSICAS TECNOLOGÍA E INGENIERÍA CONTENIDO DIDÁCTICO DEL CURSO: 301305 – ESTRUCTURA DE DATOS

cout << "LAS CADENAS SON IGUALES"; else cout << "LAS CADENAS SON DISTINTAS"; } int cmpcad(char *x, char *y) { return(strcmp(x,y)); }

El resultado de la compilación y posterior ejecución del listado llamado progra8,cpp se conjuga en la salida en pantalla como se muestra en la figura 8.

Figura 8 Salida en pantalla de progra8.cpp

Explicando la expresión que puede ser un tanto desconocida del listado anterior, la expresión: int(*cmpcad)(char*, char*). Establece que cmpcad es un apuntador a una función, la cual devuelve un valor de tipo entero. Lección 5: Apuntadores a Apuntadores Tal como se trató al inicio de capítulo, un apuntador también es una variable. Su dirección puede ser almacenada por otra variable apuntador del mismo tipo, por lo que puede hablarse de un apuntador a un apuntador. Esto puede difundirse para dos o más variables, como se observa en el ejemplo siguiente de apuntadores a apuntadores.

Page 28: 301305 Estructura de Datos

28

UNIVERSIDAD NACIONAL ABIERTA Y A DISTANCIA – UNAD ESCUELA DE CIENCIAS BÁSICAS TECNOLOGÍA E INGENIERÍA CONTENIDO DIDÁCTICO DEL CURSO: 301305 – ESTRUCTURA DE DATOS

Implementación de apuntadores a apuntadores Progra9.cpp

#include <iostream.h> #include <conio.h> void main() { int x, *a, **b, ***c ; // 1 clrscr(); a = &x ; // 2 *a = 100 ; // 3 b = &a ; // 4 **b += *a ; // 5 c = &b ; // 6 ***c += **b + *a ; // 7 cout << " *a=" << *a << " \n" ; cout << " **b=" << **b << " \n" ; cout << "***c=" << ***c << " \n" ; getch(); }

En el listado se analizan tres variables de tipo apuntador que apuntan a objetos de tipo entero, es decir que *a es un apuntador, **b es un apuntador a apuntador y ***c es un apuntador a apuntador a apuntador.

Figura 9 Salida en pantalla de progra9.cpp

Operaciones con apuntadores

Se pueden realizar asignaciones entre punteros. int a = 15; int *p, *q;

Page 29: 301305 Estructura de Datos

29

UNIVERSIDAD NACIONAL ABIERTA Y A DISTANCIA – UNAD ESCUELA DE CIENCIAS BÁSICAS TECNOLOGÍA E INGENIERÍA CONTENIDO DIDÁCTICO DEL CURSO: 301305 – ESTRUCTURA DE DATOS

q = &a; p = q; /* se asigna la dirección que contiene q a p */ cout<<p; /* imprime la dirección almacenad en p. */

Se pueden operar solamente el +, el -, el ++ y el --.

Int p; p = p + 1; p avanza un entero. p = p – 2; p retrocede dos enteros. p++; p apunta al siguiente entero. p--; p apunta al entero anterior.

Los punteros se pueden comparar.

int a; int *b, *c; if (b + n > c) b = b +2;

Como aplicación a las operaciones que se pueden realizar con apuntadores, se presenta el siguiente código en un programa que emplea los operadores (& y *). Progra10.cpp #include <iostream.h> #include <conio.h> int main() { clrscr(); int a; //a es un puntero int * ap; //ap es un apuntador a un puntero a = 7; ap= & a; //ap toma la dirección de a cout <<"la dirección de a es " <<&a; cout<<" \n el Valor de ap es " << ap; cout <<"\n el valor de a es" <<a; cout<<"\n el valor de *ap es " << *ap; cout<<"\n\n\n Mostrando los valores de * y &" ; cout <<"\n &* ap = " <<&*ap; cout <<"\n *& ap = " << *&ap; getch(); return 0; }

Page 30: 301305 Estructura de Datos

30

UNIVERSIDAD NACIONAL ABIERTA Y A DISTANCIA – UNAD ESCUELA DE CIENCIAS BÁSICAS TECNOLOGÍA E INGENIERÍA CONTENIDO DIDÁCTICO DEL CURSO: 301305 – ESTRUCTURA DE DATOS

Análisis de Progra10.cpp Tal como se observa en la imagen es la salida en pantalla del programa en el que se aprecia la diferencia entre el valor de la variable a que devuelve un valor numérico igual a 7; mientras que la variable ap devuelve la dirección de memoria de a.

Figura 10 Salida en pantalla de progra10.cpp

Page 31: 301305 Estructura de Datos

31

UNIVERSIDAD NACIONAL ABIERTA Y A DISTANCIA – UNAD ESCUELA DE CIENCIAS BÁSICAS TECNOLOGÍA E INGENIERÍA CONTENIDO DIDÁCTICO DEL CURSO: 301305 – ESTRUCTURA DE DATOS

CAPITULO 2: GESTIÓN DINÁMICA DE MEMORIA

Introducción

La gestión dinámica de memoria hace referencia a la forma enque se almacenan los datos en la computadora. Se aborda la temática relacionada con los tipos de datos que maneja el lenguaje C++ y el número de bytes requeridos para almacenar cada tipo de datos, aunque este tema es transparente para el usuario normal de un sistema computacional, si debe ser motivo de preocupación para los programadores, que están llamados a hacer buen uso de los recursos tanto físicos como lógicos.

Por otro lado se aborda la temática relacionada con los tipos de varibles, variables estáticas y dinámicas. Así como también el uso y la aplicabilidad del operador sizeof en la gestión dinámica de memoria.

En la memoria del computador se guardan no solo las constantes y variables sinó también las instrucciones del programa. Cada objeto y cada instrucción en la memoria tienen previamente asignada una dirección única. Sólo se carga el programa principal en la memoria inicialmente. El resto de subprogramas, algoritmos y funciones se va cargando según se van requiriendo. Lección 6: Conceptos Básicos de Memoria Para iniciar este capítulo es importante darle un vistazo a la memoria de la computadora. Si usted ya sabe cómo funciona la memoria de la computadora, se puede saltar esta sección. Sin embargo, si no está seguro, es importante que la lea, le ayudara a comprender mejor ciertos aspectos de la programación. La computadora usa memoria de acceso aleatorio (RAM) para guardar información mientras está en funcionamiento. La RAM se encuentra en circuitos integrados o chips en el interior de la computadora. La RAM es volátil, lo que significa que es borrada y reemplazada con nueva información tan pronto como se necesita. La volatilidad también significa que la RAM “recuerda” solamente mientras la computadora está encendida, y pierde su información cuando se apaga o se reinicia la computadora. Cada computadora tiene una determinada cantidad de RAM instalada. La cantidad de RAM en un sistema se especifica por lo general en Megabytes (Mb) por ejemplo 256 Mb, 512 Mb, en ese orden de ideas se dice que un byte es la unidad

Page 32: 301305 Estructura de Datos

32

UNIVERSIDAD NACIONAL ABIERTA Y A DISTANCIA – UNAD ESCUELA DE CIENCIAS BÁSICAS TECNOLOGÍA E INGENIERÍA CONTENIDO DIDÁCTICO DEL CURSO: 301305 – ESTRUCTURA DE DATOS

de medida fundamental de la memoria de una computadora, de los cuales se obtiene los Kilobytes, Megabytes, Gigabytes, siendo estos los más usados. Un kilobytes de memoria equivale a 1,024 bytes.

Tipo de datos y bytes requeridos en memoria Para darse una idea de que tantos bytes se necesitan para guardar determinados tipos de datos se pone a disposición la tabla 2.1donde se muestran los espacios requeridos para guardar datos en la memoria del computador. Tabla1: Bytes requeridos para los tipos de datos

DATOS BYTES REQUERIDOS

La letra X

El número 100

El número 125.12

La frase Aprenda usted mismo

Una página escrita completamente

1

2

4

21

3000 (Aproximadamente)

La RAM en la computadora está organizada en forma secuencial, un byte tras otro. Cada byte de memoria tiene una dirección única mediante la cual es identificada, una dirección que también lo distingue de todos los otros bytes de la memoria. Las direcciones son asignadas a la memoria en orden, comenzando en 0 y aumentando hasta llegar al límite de memoria instalada en el sistema. Para ampliar un poco más la conceptualización a cerca de los tipos de datos se define todo el posible rango de valores que una variable puede tomar al momento de ser ejecutada en el programa al igual que en toda la vida útil del propio programa.

Lección 7: Tipos de datos comunes

En la tabla 1 se muestran los tipos de datos y el espacio en memoria de cada dato en bytes, sin embargo también es posible determinar el tamaño en bites para los tipos de datos más comunes utilizados frecuentemente en C++, tal como se muestra en la Tabla 2:

Page 33: 301305 Estructura de Datos

33

UNIVERSIDAD NACIONAL ABIERTA Y A DISTANCIA – UNAD ESCUELA DE CIENCIAS BÁSICAS TECNOLOGÍA E INGENIERÍA CONTENIDO DIDÁCTICO DEL CURSO: 301305 – ESTRUCTURA DE DATOS

Tabla 2: Otros tipos de datos comunes

TIPO DATO ESPACIO MEMORIA

RANGO PERMITIDO

unsigned char 8 bits 0 a 255 Char 8 bits -128 a 127 short int 16 bits -32,768 a 32,767 unsigned int 32 bits 0 a 4,294,967,295 Int 32 bits -2,147,483,648 a 2,147,483,647 unsigned long 32 bits 0 a 4,294,967,295 Enum 16 bits -2,147,483,648 a 2,147,483,647 Long 32 bits -2,147,483,648 a 2,147,483,647 Float 32 bits 3.4 x 10-38 a 3.4 x 10+38(6 dec) Doublé 64 bits 1.7 x 10-308 a 1.7*10+308(15 dec) long doublé 80 bits 3.4 x 10-4932 a 1.1 x 10+4932 Void sin valor

Fuente: http://www.wikilearning.com/tutorial/tutorial_de_c++-tipos_de_datos/9773-4

Es posible realizar una representación de la Tabla 2 en términos de programación para visualizar el tipo de datos y el espacio requerido en memoria presentado en bits como la mínima medida del sistema binario. Tal como se puede ver en el listado siguiente llamado Progra11.cpp. Progra11.cpp #include <iostream.h> #include <conio.h> int main () { cout<<"TIPOS DE DATOS Y TAMANO EN BITS\n\n"; cout<< "El tamano del tipo de dato int es :"<<sizeof(int)*8<<" bits\n"; cout<< "El tamano del tipo de dato short es :"<<sizeof(short)*8<<" bits\n"; cout<< "El tamano del tipo de dato long es :"<<sizeof(long)*8<<" bits\n"; cout<< "El tamano del tipo de dato char es :"<<sizeof(char)*8<<" bits\n"; cout<< "El tamano del tipo de dato float es :"<<sizeof(float)*8<<" bits\n"; cout<< "El tamano del tipo de dato double es:"<<sizeof(double)*8<<" bits\n"; getch(); return 0; } Ya se tiene el código fuente guardado con el nombre de Progra11.cpp, ahora solo resta compilar y ejecutar el código para obtener el siguiente resultado como salida en pantalla.

Page 34: 301305 Estructura de Datos

34

UNIVERSIDAD NACIONAL ABIERTA Y A DISTANCIA – UNAD ESCUELA DE CIENCIAS BÁSICAS TECNOLOGÍA E INGENIERÍA CONTENIDO DIDÁCTICO DEL CURSO: 301305 – ESTRUCTURA DE DATOS

Figura 11 Salida en pantalla de progra11.cpp

Usos de la Memoria RAM Seguramente con frecuencia alguien se ha planteado la siguiente pregunta ¿Para qué se usa la memoria RAM de la computadora?. Tiene varios usos, pero solamente uno, el almacenamiento de datos, le interesa al programador. Los datos significan la información con la cual trabaja un programa. Ya sea que el programa esté trabajando con una lista de direcciones, monitoreando la bolsa de valores, manejando un presupuesto, controlando la nómina de una empresa o cualquier otra tarea, la información de (nombres, precios de acciones, gastos, salarios) es guardada en la RAM de la computadora mientras el programa esté ejecutándose. Hasta el momento, la mayoría de los programas se han realizado definiendo variables, sin tener la preocupación de qué se está realizando internamente en el computador, muchas veces en forma indiscriminada, es decir sin una verdadera depuración, pero existen ocasiones en que no se sabe cuánta memora se requerirá para la ejecución de un determinado programa; por ejemplo, si deseamos realizar un procesador de textos, de entrada no se conoce cuál va hacer la longitud del texto. Por eso a veces es necesario poder reservar memoria según se va necesitando. Además de esta forma los programas en ejecución aprovecharán mejor la memoria del computador, usando sólo los recursos necesarios. Realmente la utilidad de asignación dinámica de memoria será aplicada en gran medida en los capítulos relacionados con las estructuras de datos lineales, tema que se trata en la unidad dos. De acurdo a lo anterior se puede identificar dos tipos de variables: estáticas y dinámicas para ampliar estos conceptos se invita a revisar la temática tratada en la Lección 3.

Page 35: 301305 Estructura de Datos

35

UNIVERSIDAD NACIONAL ABIERTA Y A DISTANCIA – UNAD ESCUELA DE CIENCIAS BÁSICAS TECNOLOGÍA E INGENIERÍA CONTENIDO DIDÁCTICO DEL CURSO: 301305 – ESTRUCTURA DE DATOS

Lección 8: Tipos de Variables Dependiendo del uso que se le dé a las variables por parte del programador en una rutina o tarea específica, se pueden identificar dos tipos de variables, las variables dinámicas y variables estáticas. Variables estáticas Las variables estáticas tal como se recuerda en los inicios de los fundamentos de programación, son aquellas que el programador les asigna memoria antes de la ejecución del programa o de una función. Las variables estáticas se llaman mediante el nombre de la misma, que ha sido declarada por el programador y su función principal dentro de un programa es almacenar información dependiendo del tipo de dato con que se haya declarado.

Aplicación de las variables estáticas A continuación se presenta el código fuente de un programa que hace uso de las variables estáticas. Progra12.cpp #include <stdio.h> #include <iostream.h> #include <stdlib.h> #include <conio.h> int priNumero; /* Las variables */ int segNumero; int suma; void main() { clrscr(); priNumero = 136; segNumero = 369; suma = priNumero + segNumero; cout<<"La suma es " <<suma; getch(); } Análisis de Progra12.cpp En el código del programa se hace uso de tres variables de tipo entero que son variables estáticas ellas son: priNumero que se le asigna el valor 136, mientras

Page 36: 301305 Estructura de Datos

36

UNIVERSIDAD NACIONAL ABIERTA Y A DISTANCIA – UNAD ESCUELA DE CIENCIAS BÁSICAS TECNOLOGÍA E INGENIERÍA CONTENIDO DIDÁCTICO DEL CURSO: 301305 – ESTRUCTURA DE DATOS

que a la variable segNumero se le asigna el valor 369, de igual manera a la variable suma calcula el resultado de sumar el valor de las dos variables. Aunque se trata de un programa sencillo de entender que solo muestra la suma de dos variables estáticas, vale la pena poner a disposición la salida en pantalla tal como se presenta a lo largo del curso. Figura 12 Salida en pantalla de progra12.cpp

Lección 9: Variables Dinámicas Las variables dinámicas deben su nombre al hecho de que pueden ser creadas y destruidas durante el tiempo de ejecución de un módulo. Para el manejo de variables dinámicas se hace indispensable la utilización de apuntadores, así como de funciones especiales para la asignación y liberación de la memoria correspondiente a dichas variables.

Aplicación de las variables dinámicas A continuación se presenta el código fuente completo de un programa que hace uso de las variables dinámicas. Progra13.cpp #include <iostream.h> #include <conio.h> void main() { int x, *a, **b, ***c ; // 1 clrscr(); a = &x ; // 2 *a = 100 ; // 3

Page 37: 301305 Estructura de Datos

37

UNIVERSIDAD NACIONAL ABIERTA Y A DISTANCIA – UNAD ESCUELA DE CIENCIAS BÁSICAS TECNOLOGÍA E INGENIERÍA CONTENIDO DIDÁCTICO DEL CURSO: 301305 – ESTRUCTURA DE DATOS

b = &a ; // 4 **b += *a ; // 5 c = &b ; // 6 ***c += **b + *a ; // 7 cout << " *a=" << *a << " \n" ; cout << " **b=" << **b << " \n" ; cout << "***c=" << ***c << " \n" ; getch(); } Análisis de Progra13.cpp En el listado del progra13.cpp se declaran tres variables de tipo apuntador que apuntan a datos de tipo entero, ellas son, *a, **b y **c. El apuntador a almacena la dirección de la variable x, luego a al apuntador a se le asigna el valor de 100, lo que indica que x vale 100, mientras que **b precedida de dos asteriscos indica que es una variable que apunta a un apuntador, para este caso b guarda la dirección de el puntero a, y ***c es un apuntador a apuntador a apuntador, lo cual puede simplificarse en que c guarda la dirección de b. El resultado del listado Progra13.cpp se puede visualizar en la Figura 13.

Figura 13Salida en pantalla de progra13.cpp

Lección 10: Asignar y Liberar Espacios de Memoria En el lenguaje C existen entre otras las funciones Malloc() y Free() para la asignación y liberación de memoria dinámicamente respectivamente. Cuando se ejecuta un programa, el sistema operativo reserva una zona de memoria para el código o instrucciones del programa y otra para las variables que se usan durante la ejecución. A menudo estas zonas son la misma zona, es lo que se llama memoria local. También hay otras zonas de memoria, como la pila, que se usa, entre otras cosas, para intercambiar datos entre funciones. El resto, la

Page 38: 301305 Estructura de Datos

38

UNIVERSIDAD NACIONAL ABIERTA Y A DISTANCIA – UNAD ESCUELA DE CIENCIAS BÁSICAS TECNOLOGÍA E INGENIERÍA CONTENIDO DIDÁCTICO DEL CURSO: 301305 – ESTRUCTURA DE DATOS

memoria que no se usa por ningún programa es lo que se conoce como "heap" o montón. Cuando el programador use memoria dinámica, normalmente usará memoria del montón, y no se llama así porque sea de peor calidad, sino porque suele haber realmente un montón de memoria de este tipo disponible para ser usado en la medida que se requiera. Profundizando un poco en la asignación dinámica, se encuentra el operador sizeof, el cual determina el tamaño en bytes que se requiere en la asignación dinámica de memoria, ya sea por medio de los operadores New y Delete, o por las funciones Malloc y Free, de un arreglo o de cualquier otro tipo de datos, Ejemplo utilizar el operador sizeof en una función con el propósito de determinar el tamaño en bytes de un parámetro. Aplicación del operador sizeof. En el siguiente listado se evidencia la aplicación y uso del operador sizeof en cada variable el cual devuelve el número de bytes dependiendo del tipo de variable. Implementación del uso de sizeof Progra14.cpp #include <iostream.h> #include <conio.h> void main() { char P; short R; int I; long L; float F; double D; long double LD; clrscr(); gotoxy(1,2); cout<<"valores utilizando sizeof para cada una de la varibles \n\n"; cout<<" variable P = " <<sizeof P; cout<<"\t tipo char = " <<sizeof (char); cout<<"\n variable R = " <<sizeof R; cout<<"\t tipo short = " <<sizeof (short); cout<<"\n variable I = " <<sizeof I; cout<<"\t tipo int = " <<sizeof (int); cout<<"\n variable L = " <<sizeof L; cout<<"\t tipo int = " <<sizeof (long);

Page 39: 301305 Estructura de Datos

39

UNIVERSIDAD NACIONAL ABIERTA Y A DISTANCIA – UNAD ESCUELA DE CIENCIAS BÁSICAS TECNOLOGÍA E INGENIERÍA CONTENIDO DIDÁCTICO DEL CURSO: 301305 – ESTRUCTURA DE DATOS

cout<<"\n variable F = " <<sizeof I; cout<<"\t tipo float = " <<sizeof (float); cout<<"\n variable D = " <<sizeof D; cout<<"\t tipo double = " <<sizeof (double); cout<<"\n variable LD = " <<sizeof LD; cout<<"\t tipo int = " <<sizeof (long double); cout<<"\n variable I = " <<sizeof I; cout<<"\t tipo int = " <<sizeof (int); getch(); } Análisis de Progra14.cpp En la siguiente gráfica se visualiza el resultado del progra13.cpp en laque se puede apreciar el resultado almacenado en la variable y los bytes requeridos para cada tipo de dato. Figura 14 Salida en pantalla de progra14.cpp

Page 40: 301305 Estructura de Datos

40

UNIVERSIDAD NACIONAL ABIERTA Y A DISTANCIA – UNAD ESCUELA DE CIENCIAS BÁSICAS TECNOLOGÍA E INGENIERÍA CONTENIDO DIDÁCTICO DEL CURSO: 301305 – ESTRUCTURA DE DATOS

CAPITULO 3: OPERADORES Y FUNCIONES EN LA GESTIÓN DE MEMORIA

Introducción

En el presente capítulo se trata la temática relacionada con los operadores y las funciones utilizadas para la gestión de memoria, en ese sentido se realizan programas como aplicación a los operadores new y delete propios de C++, al igual que las funciones malloc(), free() y calloc() y realloc() propias de C.

Al igual que en cada uno de los capítulos, se presentan programas de aplicación que dan respuesta a al temática planteada, estos programas están previamente compilados y depurados para garantizar que el estudiante pueda editarlos analizalos y plantear mejoras que contribuyan a su formación y al adquisición de la competencia del curso desarrollada en cada uno de sus capítulos.

Lección 11: Operadores New y Delete

El lenguaje C++ cuenta con dos operadores preconstruidos, ellos son: New y Delete, por esta razón no se requiere incluir ninguna librería o archivo de cabecera para utilizarlos.

El operador New: Realiza una labor parecida a la de la función malloc(), asignando un bloque de memoria según sea requerido. El operador Delete: Libera un bloque de memoria asignada por New en tiempo de ejecución, de manera semejante a como lo hace la función free().

La sintaxis para el uso del operador new es: Apuntador = new tipo_de_dato; Este operador hace una petición al sistema operativo para que se le asigne un espacio en memoria, con el tamaño acorde al tipo de datos (vale la pena recordar la función sizeof), si este espacio está disponible, la operación regresa la dirección real que se otorga, en caso de no haber espacio regresa el valor de NULL (0), La sintaxis para el uso del operador delete es: delete apuntador;

Page 41: 301305 Estructura de Datos

41

UNIVERSIDAD NACIONAL ABIERTA Y A DISTANCIA – UNAD ESCUELA DE CIENCIAS BÁSICAS TECNOLOGÍA E INGENIERÍA CONTENIDO DIDÁCTICO DEL CURSO: 301305 – ESTRUCTURA DE DATOS

La ejecución de este operador provoca que se libere espacio, dejando como valor indefinido, es decir el sistema operativo lo considera como memoria disponible. Hay una regla de oro utilizada por algunos autores, se refiere a que cuando se usa memoria dinámica, toda la memoria que se reserve durante el programa hay que liberarla antes de salir del programa. No seguir esta regla es una actitud muy irresponsable, y en la mayor parte de los casos tiene consecuencias desastrosas que atentan con la estabilidad de su sistema. No es bueno fiarse de lo que diga el compilador, de que estas variables se liberan solas al terminar la ejecución del programa, no siempre puede ser así.

Aplicación de los operadores New y Delete Se presenta un ejemplo como aplicación de los operadores de C++, utilizados para asignar y liberar memoria dinámicamente. “En el listado se declaran las variables index de tipo entero y los apuntadores point1 y point2 ambos de tipo entero. Progra15.cpp # include <iostream.h> # include <conio.h> main() { clrscr(); int index, *point1, *point2; point1 = &index; *point1 = 77; point2 = new int; *point2 = 173; cout <<"SALIDA DE LAS VARIABLES index, *point1 Y *point2\n\n"; cout <<"Los valores son " << index <<" " << *point1 << " "<< *point2 <<'\n'; point1 = new int; point2 = point1; *point1 = 999; cout <<"Los valores son " << index <<" " << *point1 << " "<< *point2 <<'\n'; delete point1; float *float_point1, *float_point2 = new float; float_point1 = new float; *float_point2 = 3.14159; *float_point1 = 2.4 * (*float_point2); delete float_point2; delete float_point1; char *c_point;

Page 42: 301305 Estructura de Datos

42

UNIVERSIDAD NACIONAL ABIERTA Y A DISTANCIA – UNAD ESCUELA DE CIENCIAS BÁSICAS TECNOLOGÍA E INGENIERÍA CONTENIDO DIDÁCTICO DEL CURSO: 301305 – ESTRUCTURA DE DATOS

c_point = new char; delete c_point; c_point = new char [sizeof(int) + 133]; delete c_point; getch(); return 0; } Análisis de Progra15.cpp

El resultado de la ejecución del listado llamado Progra16.cpp se visualiza en la Figura 15.

Figura 15 Salida en pantalla de progra15.cpp

En las primeras líneas del programa, se hace uso de los punteros tal como se hacen también en C.

point2 ilustra el uso del operador new. Este operador requiere un

modificador que debe ser un tipo. La parte new int significa que se crea un nuevo entero en la memoria, y devuelve la localización del entero creado. Esta localización es asignada a point2. La siguiente línea asigna 173 al entero al que apunta point2. Es importante distinguir entre point2, la localización del entero, y *point2, el entero. El puntero point2 apunta ahora a una variable entera que se ha reservado dinámicamente, y que puede utilizarse de igual forma que se hacía en C. Como ejemplo, se imprime el valor al que apunta.

A continuación, se reserva memoria para una nueva variable, y point2 se refiere a la misma variable reservada dinámicamente a la que apunta point1. En este caso, la referencia a la variable a la que point2 apuntaba previamente se ha perdido, y nunca podrá ser utilizada o su memoria liberada. Sólo cuando se vuelva al sistema operativo se liberará la memoria que ocupaba. Por tanto, no debe utilizarse.

Page 43: 301305 Estructura de Datos

43

UNIVERSIDAD NACIONAL ABIERTA Y A DISTANCIA – UNAD ESCUELA DE CIENCIAS BÁSICAS TECNOLOGÍA E INGENIERÍA CONTENIDO DIDÁCTICO DEL CURSO: 301305 – ESTRUCTURA DE DATOS

Ya que el puntero point1 en sí no ha cambiado, apunta realmente al dato original. Este dato podría referenciarse otra vez utilizando point1, pero no es una buena práctica de programación, ya que no hay garantía de lo que el sistema pueda hacer con el puntero o el dato. La localización del dato queda libre para ser reservada en una llamada subsiguiente, y será pronto reutilizada en cualquier programa.

Ya que el operador delete está definido para no hacer nada si se le pasa un valor NULL, se puede liberar la memoria ocupada por un dato al que apunta un puntero NULL, ya que realmente no se está haciendo nada. El operador delete sólo puede utilizarse para liberar memoria reservada con el operador new. Si se usa delete con cualquier otro tipo de dato, la operación no está definida, y por tanto nada sucede.

En el programa también declaramos algunas variables reales, y se realizan operaciones similares a las anteriores. De nuevo esto ilustra que en C++ las variables no tienen que ser declaradas al comienzo de cada bloque. Una declaración es una sentencia ejecutable y puede entonces aparecer en cualquier lugar en la lista de sentencias ejecutables.

Finalmente, ya que el operador new requiere un tipo para determinar el tamaño de un bloque dinámicamente reservado, se muestra cómo reservar un bloque de tamaño arbitrario. Esto es posible utilizando la construcción de las últimas líneas del programa, donde un bloque de 37 caracteres de tamaño (37 bytes) es reservado. Un bloque de 133 bytes mayor que el tamaño de un entero se reserva posteriormente. Por tanto, el operador new se puede utilizar con la misma flexibilidad de la función malloc() de C.

Cuando los datos reservados dinámicamente son borrados con delete, todavía quedan en memoria. Si repetimos la instrucción cout inmediatamente después de utilizar delete, veremos que todavía se conservan los valores. Si la repetimos de nuevo antes de dejar el programa, cuando el espacio que ocupaban debe haber sido sobrescrito, veremos que ya no es así. Incluso aunque el compilador nos dé los números correctos, no es una buena práctica pensar que esos datos están ahí todavía, porque en un programa dinámico largo la memoria se usará continuadamente.

Las funciones estándar utilizadas en C para manejo dinámico de memoria, malloc(), calloc() y free(), también se pueden utilizar en C++ de la misma forma que en C. Los operadores new y delete no deben mezclarse con estas funciones, ya que los resultados pueden ser impredecibles. Si se está partiendo de código C, lo mejor es continuar utilizando las funciones en las nuevas líneas de programa. Si no es así, se deben utilizar los nuevos

Page 44: 301305 Estructura de Datos

44

UNIVERSIDAD NACIONAL ABIERTA Y A DISTANCIA – UNAD ESCUELA DE CIENCIAS BÁSICAS TECNOLOGÍA E INGENIERÍA CONTENIDO DIDÁCTICO DEL CURSO: 301305 – ESTRUCTURA DE DATOS

operadores, ya que se han construido como parte del lenguaje en sí, más que añadirse, y por tanto son más eficientes”1.

Cuando se utiliza new para reservar memoria para un vector, el tamaño del vector se sitúa entre corchetes, siguiendo al tipo:

int *intvector; intvector = new int [20]; y se libera: delete [ ] intvector;

Lección 12: Más acerca de la Implementación de New y Delete El siguiente muestra un ejemplo de aplicación de los operadores new y delete. Progra16.cpp #include <iostream.h> //1 #include <conio.h> //2 void main() //3 { //4 clrscr(); //5 int *numero; //6 numero = new int ; //7 *numero = 10 ; //8 cout <<"VALOR DE NUMERO\n\n"; //9 cout <<"El resultado de numero es:" <<*numero ; //10 delete numero ; //11 getch(); //12 } //13

En el listado llamado Progra16.cpp, se supone que la reservación será exitosa porque existe espacio suficiente en el montículo.

Del listado se puede analizar lo siguiente:

En las líneas 1 y 2 se incluyen las librerías requeridas para la ejecución del programa sin errores de compilación y ejecución. En la línea 3 se incluye la función principal main() la cual no retorna ningún valor por estar declarada como tipo void. La línea 4 se incluye la llave que da apertura a la función principal.

1 Tomado de: http://www.pablin.com.ar/computer/cursos/c1/allocate.html

Page 45: 301305 Estructura de Datos

45

UNIVERSIDAD NACIONAL ABIERTA Y A DISTANCIA – UNAD ESCUELA DE CIENCIAS BÁSICAS TECNOLOGÍA E INGENIERÍA CONTENIDO DIDÁCTICO DEL CURSO: 301305 – ESTRUCTURA DE DATOS

La línea 5 se incluye la función clrscr() utilizada para limpiar pantalla de ejecuciones anteriores del programa. En la línea 6 se declara un puntero llamado numero y es de tipo entero. En la línea 7 se reserva un bloque de memoria dinámica de 2 bytes para manejarlo por medio de numero. En la línea 8 Asigna el valor 10 al objeto apuntado por numero. En la línea 9 se despliega un mensaje en pantalla. En la línea 10 se despliega el contenido del objeto apuntado por numero. La línea 11, libera el espacio de memoria asignado o manejado por numero. En la línea 12 se incluye la función getch(), la cual hace una parada del programa a la espera que se presione una tecla para finalizar la ejecución del programa. Finalmente la línea 13, se incluye la llave que cierra las instrucciones que hacen parte de la función principal.

El resultado de la salida en pantalla se puede visualizar en la Figura16.

Figura 16 Salida en pantalla de progra16.cpp

Pero ¿quién asegura que el espacio requerido por new está disponible?. Para controlar esta situación y evitar un mensaje de error por parte del sistema en tiempo de ejecución, en el listado siguiente se propone una nueva versión del programa. Implementación de New para verificación de memoria Progra17.cpp

#include <iostream.h> #include <stdlib.h> #include <conio.h> void main() { int *numero;

Page 46: 301305 Estructura de Datos

46

UNIVERSIDAD NACIONAL ABIERTA Y A DISTANCIA – UNAD ESCUELA DE CIENCIAS BÁSICAS TECNOLOGÍA E INGENIERÍA CONTENIDO DIDÁCTICO DEL CURSO: 301305 – ESTRUCTURA DE DATOS

if((numero = new int)==NULL) { cout << "NO hay espacio suficiente\n"; exit(1); } *numero=20 ; cout <<"Resultado\n\n"; cout << "El resultado de numero es:"<<*numero ; delete numero ; getch(); }

El resultado en pantalla de Progra17.cpp se puede visualizar en la Figura 17.

Figura 17 Salida en pantalla de progra17.cpp

Otro caso a considerar es la reserva de memoria con el operador new para un arreglo, un ejemplo sería la reserva de memoria para crear un arreglo de 25 elementos de tipo double, en el montículo, puede declararse como: Double *numero; numero = new double[25];

De igual manera en su forma equivalente se tiene: double *numero = new double[25]; En este ejemplo, se está declarando a número como un apuntador a variables dinámicas de tipo doble; al tiempo que se le asigna el valor retornado por new. El valor retornado por new es la dirección del inicio de un bloque de memoria del tamaño requerido para almacenar 25 elementos de tipo double. En caso de que el montículo no disponga del espacio requerido, new retorna el valor NULL (nulo).

Page 47: 301305 Estructura de Datos

47

UNIVERSIDAD NACIONAL ABIERTA Y A DISTANCIA – UNAD ESCUELA DE CIENCIAS BÁSICAS TECNOLOGÍA E INGENIERÍA CONTENIDO DIDÁCTICO DEL CURSO: 301305 – ESTRUCTURA DE DATOS

Lección 13: Funciones Malloc() y Free() La función Malloc() Es una de las funciones de asignación de memoria propias del lenguaje de programación C (acrónimo de memory allocation). Cuando se usa malloc () se pasa la cantidad de bytes de memoria que se necesita. Malloc () encuentra y reserva un bloque de menoría del tamaño pedido y regresa la dirección del primer byte del bloque. No hay de qué preocuparse sobre que parte de memoria se usa, ya que esto es manejado automáticamente. La función malloc () regresa una dirección, y su tipo de retorno es un apuntador a tipo void. ¿Por qué void?. Un apuntador a tipo void es compatible con todos los tipos de datos. Como la memoria asignada por malloc () puede ser usada para guardar cualquiera de los tipos de datos de C, es adecuado el tipo de retorno void.

La función Free() Al igual que malloc(), free() es una función del lenguaje de programación C, utilizado para liberar la memoria asignada por malloc (). Al usar la función free () se debe tener en cuenta la regla de oro explicada en el apartado del operador delete “toda la memoria que se reserve durante el programa hay que liberarla antes de salir del programa” Al usar las funciones malloc () y free () se debe incluir el archivo de cabecera o librería STDLIB.H. Ejemplos de aplicación Ejemplo 1 Asigna memoria para un arreglo de 50 enteros Int *numero; numero = (int * ) malloc (50 * sizeof (int)); Ejemplo 2 Asigna memoria para un arreglo de 10 valores float float *numero; numero = (float * ) malloc (10 * sizeof (float));

Page 48: 301305 Estructura de Datos

48

UNIVERSIDAD NACIONAL ABIERTA Y A DISTANCIA – UNAD ESCUELA DE CIENCIAS BÁSICAS TECNOLOGÍA E INGENIERÍA CONTENIDO DIDÁCTICO DEL CURSO: 301305 – ESTRUCTURA DE DATOS

Lección 14: Aplicación a la asignación de memoria con Malloc() y Free()

Una Buena aplicación de las funciones utilizadas para la gestión dinámica de memoria se puede visualizar en el siguiente listado llamado Progra18.cpp. Progra18.cpp #include <iostream.h> #include <conio.h> #include <stdlib.h> #include <stdio.h> int main() { clrscr(); int *p=NULL; int nbytes=100; p=(int *)malloc(nbytes); if(p==NULL) { cout<<"Insuficiente espacio en memoria\n"; return -1; } cout<< "Bytes Reservados\n\n"; cout<<"Se han asignado " <<nbytes <<" bytes de memoria\n"; free(p); getch(); } La salida en pantalla de Progra18.cpp se puede visualizar en la Figura 18 que se muestra a continuación. Figura 18 Salida en pantalla de progra18.cpp

El resultado del programa muestra un mensaje en pantalla confirmando que se realizó la asignación dinámica de memoria de 100 bytes con éxito. A continuación se presenta otro ejemplo de aplicación de la asignación dinámica de memoria utilizando las funciones malloc () y free (), con un ingrediente adicional

Page 49: 301305 Estructura de Datos

49

UNIVERSIDAD NACIONAL ABIERTA Y A DISTANCIA – UNAD ESCUELA DE CIENCIAS BÁSICAS TECNOLOGÍA E INGENIERÍA CONTENIDO DIDÁCTICO DEL CURSO: 301305 – ESTRUCTURA DE DATOS

el uso de una estructura llamada persona, la cual permita almacenar el registro de datos de una persona, dos tipos de datos diferentes, un dato de tipo carácter que almacena el nombre de la persona y otro dato de tipo entero para almacenar la edad. He aquí la implementación del programa completo.

Implementación del uso de Malloc() y Free() Progra19.cpp // Listado de librerías o archives de cabecera #include<iostream.h> #include<stdlib.h> #include<conio.h> // Definición de la función principal void main() { clrscr(); int n, i; // Definición de la estructura persona struct persona { char nombre[20]; int edad; }; // Definición del puntero p de tipo persona utilizado para reservar memoria persona *p; cout<<"PROGRAMA QUE GUARDA EL REGISTRO DE PERSONAS"<<"\n"; cout<<"\nNUMERO DE PERSONAS A INGRESAR : "; cin>>n; // Reserva de memoria dinámica a través de malloc () p =(persona *)malloc(sizeof(persona)); // El ciclo for usado para la entrada de los datos de la persona for(i=1;i<=n;i++) { cout<<"\nDIGITE EL NOMBRE " << i <<" : "; cin>>p[i].nombre; cout<<"DIGITE LA EDAD : "; cin>>p[i].edad; cout<<"\n";

Page 50: 301305 Estructura de Datos

50

UNIVERSIDAD NACIONAL ABIERTA Y A DISTANCIA – UNAD ESCUELA DE CIENCIAS BÁSICAS TECNOLOGÍA E INGENIERÍA CONTENIDO DIDÁCTICO DEL CURSO: 301305 – ESTRUCTURA DE DATOS

} clrscr(); cout<<"LISTADO DE PERSONAS REGISTRADAS "<<"\n"; // El ciclo for usado para la impresión o visulización de los datos registrados for(i=1;i<=n;i++) { cout<<" NOMBRE : "<<p[i].nombre<<"\n"; cout<<" EDAD : "<<p[i].edad<<"\n\n"; } getch(); // La función free () libera la memoria asignada al apuntador p free (p); }

Resultado en pantalla del Progra19.cpp La siguiente imagen muestra el resultado de en pantalla que registra el nombre y la edad de 3 tres personas. Figura 19 Salida en pantalla de progra19.cpp

Lección 15: Otras funciones para asignar memoria dinámica Aparte de la función Malloc() tratada en la sección anterior, utilizada para la gestión dinámica de memoria, existen dos funciones adicionales para reservar memoria, ellas son: calloc() y realloc().

La Funcione Calloc()

A continuación se presentan el prototipo para la definición de la función Calloc().

Page 51: 301305 Estructura de Datos

51

UNIVERSIDAD NACIONAL ABIERTA Y A DISTANCIA – UNAD ESCUELA DE CIENCIAS BÁSICAS TECNOLOGÍA E INGENIERÍA CONTENIDO DIDÁCTICO DEL CURSO: 301305 – ESTRUCTURA DE DATOS

void *calloc(size_t nmemb, size_t size); “Cuando se usa la función malloc() la memoria no es inicializada (a cero) o borrada. Si se quiere inicializar la memoria entonces se puede usar la función calloc. La función calloc es computacionalmente un poco más cara pero, ocasionalmente, más conveniente que malloc. Se debe observar también la diferencia de sintaxis entre calloc y malloc, ya que calloc toma el número de elementos deseados (nmemb) y el tamaño del elemento (size), como dos argumentos individuales. Por lo tanto para asignar a 100 elementos enteros que estén inicializados a cero se puede hacer: int *ip; ip = (int *) calloc(100, sizeof(int) );

La Función Realloc()

Esta función intenta cambiar el tamaño de un bloque de memoria previamente asignado. El nuevo tamaño puede ser más grande o más pequeño. Si el bloque se hace más grande, entonces el contenido anterior permanece sin cambios y la memoria es agregada al final del bloque. Si el tamaño se hace más pequeño entonces el contenido sobrante permanece sin cambios. El prototipo de definición para la función realloc() es como se presenta a continuación. void *realloc(void *ptr, size_t size); Si el tamaño del bloque original no puede ser redimensionado, entonces realloc intentará asignar un nuevo bloque de memoria y copiará el contenido anterior. Por lo tanto, la función devolverá un nuevo apuntador (o de valor diferente al anterior), este nuevo valor será el que deberá usarse. Si no puede ser reasignada nueva memoria la función realloc devuelve NULL.” 2 Si para el ejemplo anterior, se quiere reasignar la memoria a 60 enteros en vez de 100 apuntados por ip, se hará; ip = (int *) realloc ( ip, 60*sizeof(int) ); “Aplicación de Calloc

void *calloc(size_t nmemb, size_t tamano); 2 Tomado de: http://www.fismat.umich.mx/mn1/manual/node10.html

Page 52: 301305 Estructura de Datos

52

UNIVERSIDAD NACIONAL ABIERTA Y A DISTANCIA – UNAD ESCUELA DE CIENCIAS BÁSICAS TECNOLOGÍA E INGENIERÍA CONTENIDO DIDÁCTICO DEL CURSO: 301305 – ESTRUCTURA DE DATOS

Adjudica espacio para un array de nmemb objetos, cada cual tiene como tamaño tamano. El espacio es inicializado a cero todos los bits. La función calloc retorna o bien un puntero nulo o bien un puntero al espacio adjudicado.

Progra20.cpp

#include <stdio.h> #include <stdlib.h> #include <conio.h> int main( void ) { int *numPtr, i; size_t tamano=0; printf( "Introduzca el tamaño de la lista: " ); scanf( "%d", &tamano ); puts( "Adjudicamos espacio a la lista (con calloc)." ); numPtr = (int *)calloc( tamano, sizeof(int) ); for( i=0; i<tamano-1; i++ ) printf( "%d, ", numPtr[i] = rand() % 100 + 1 ); printf( "%d\n", numPtr[i] = rand() % 100 + 1 ); numPtr = (int *)realloc( numPtr, tamanyo/=2 ); printf( "Recortamos la lista a la mitad: %d\n", tamano ); for( i=0; i<tamano-1; i++ ) printf( "%d, ", numPtr[i] ); printf( "%d\n", numPtr[i] ); puts( "Liberamos el espacio (con realloc)." ); realloc( numPtr, 0 ); getch(); return 0; } //Fin de la implementación de la función Calloc”3

3 Tomado de: http://www.conclase.net/c/librerias/funcion.php?fun=calloc

Page 53: 301305 Estructura de Datos

53

UNIVERSIDAD NACIONAL ABIERTA Y A DISTANCIA – UNAD ESCUELA DE CIENCIAS BÁSICAS TECNOLOGÍA E INGENIERÍA CONTENIDO DIDÁCTICO DEL CURSO: 301305 – ESTRUCTURA DE DATOS

Actividades de Autoevaluación de la Unidad 1

Ejercicio 1. Teniendo en cuenta la conceptualización y la aplicabilidad en el campo de la programación frente al uso de las variables estáticas y las variables dinámicas, realice un cuadro comparativo de las características, ventajas y desventajas. Ejercicio 2. Se requiere gestionar cadenas de caracteres, a través de variables de tipo char, establezca diferencias para la declaración y definición de variables estáticas y las variables dinámicas (Apuntadores) para este tipo de datos. Ejercicio 3. Determinar las reglas del funcionamiento de los operadores new y delete e identifique las principales diferencias entre la utilización de new y delete, frente a la utilización de malloc() y free(). Ejercicio 4. Aplicación de operaciones con apuntadores. Teniendo en cuenta los fundamentos teóricos a cerca de las operaciones que se pueden realizar con apuntadores, documente cada línea de código de los siguientes enunciados. Enunciado 1 No. de Líneas de código int P = 10; // 1 int *x, *y; // 2 y = &P; // 3 x = y; // 4 cout<< “El resultado de x es :” << x ; // 5 Enunciado 2 Int punt; // 1 punt = punt + 1; // 2 punt = punt – 2; // 3 punt++; // 4 punt--; // 5 Ejercicio 5. Analice el siguiente código que es una aplicación de apuntadores a apuntadores, documente cada una de las 10 líneas de código y exprese el resultado de cada una de las variables.

Page 54: 301305 Estructura de Datos

54

UNIVERSIDAD NACIONAL ABIERTA Y A DISTANCIA – UNAD ESCUELA DE CIENCIAS BÁSICAS TECNOLOGÍA E INGENIERÍA CONTENIDO DIDÁCTICO DEL CURSO: 301305 – ESTRUCTURA DE DATOS

Enunciado 3 No. de Líneas de código void main() { int m, *h, **s, ***q ; // 1 clrscr(); h = &m ; // 2 *h = 80 ; // 3 s = &h ; // 4 **s += *h ; // 5 q = &s ; // 6 ***q += **s + *h ; // 7 cout << " *h=" << *h << " \n" ; //8 cout << " **s=" << **s << " \n" ; //9 cout << "***q=" << ***q << " \n" ; //10 getch(); } Ejercicio 6. Implemente un programa usando memoria dinámica con las funciones Malloc() y Free() para que imprima los datos básicos de dos personas haciendo uso de una estructura. Ejercicio 7. Implementar un programa que asigne memoria con new y delete, para un arreglo de estructuras, el cual desea llevar los registros básicos de 5 mascotas, como: raza, nombre, color y edad Ingresados por teclado, además de determinar en tiempo de ejecución el tamaño del arreglo a utilizar.

Ejercicio 8. Implemente un programa que imprima los datos básicos de un automóvil (Marca, modelo, color, cilindraje) usando una estructura llamada automóvil y incluya variables de tipo apuntador.

Page 55: 301305 Estructura de Datos

55

UNIVERSIDAD NACIONAL ABIERTA Y A DISTANCIA – UNAD ESCUELA DE CIENCIAS BÁSICAS TECNOLOGÍA E INGENIERÍA CONTENIDO DIDÁCTICO DEL CURSO: 301305 – ESTRUCTURA DE DATOS

Fuentes Documentales de la Unidad 1

AGUILAR, Luis (2003). Fundamentos de programación, algoritmos, estructura de datos y Objetos, Tercera edición. España: McGRAW-HILL. AGUILAR, Luis (200). Programación en C++, Algoritmos, estructura de datos y Objetos. España: McGRAW-HILL. AGUILAR, Luis (2003). Fundamentos de programación, algoritmos, estructura de datos y Objetos Tercera edición. España: McGRAW-HILL. AGUILAR Luis, ZAHONERO Martínez (2004). Algoritmos y Estructuras de Datos. Una perspectiva en C. Madrid-España: McGraw-Hill. BROOKSHEAR, J. Glenn (1995). Introducción a las ciencias de la Computación (Cuarta Edicón). Edición Española: Addison-Wesley Iberoamericana. DEYTEL Y DEYTEL(1999). Como programa C++. Segunda Edición. Mexico D.F: Prentice Hall. McGRAW-HILL. FARREL, Joyce (2000). Introducción a la programación lógica y diseño. Mexico D.F: Thomson. KENNETH C, Louden (2004). Lenguajes de programación. Segunda edición. MexicoD.F: Thomson. ESPINOZA, David (2004). Curso básico de Algoritmia. Consultado en Octubre, 24 de 2008 en http://www.geocities.com/david_ees/Algoritmia/curso.htm. MENDEZ, Justo (2004). Las tendencias en los lenguajes de programación. Consultado en Noviembre de 2008 en http://www.ilustrados.com/publicaciones/EpZVVEZpyEdFpAKxjH.php. CACERES, Abdiel (2005). Estructuras de datos en C++. Consultado en Febrero 25 de 2009 en http://computacion.cs.cinvestav.mx/~acaceres/courses/estDatosCPP/

ALGORITMIA.NET (2003). Grafos. Consultado en Noviembre de 2008 en http://www.algoritmia.net/articles.php?id=18. FUENTES, Arenas (1997). Reserva dinámica de Memoria. Consultado en Octubre 23 de 2008 en http://www.pablin.com.ar/computer/cursos/c1/allocate.html.

Page 56: 301305 Estructura de Datos

56

UNIVERSIDAD NACIONAL ABIERTA Y A DISTANCIA – UNAD ESCUELA DE CIENCIAS BÁSICAS TECNOLOGÍA E INGENIERÍA CONTENIDO DIDÁCTICO DEL CURSO: 301305 – ESTRUCTURA DE DATOS

TEJADA, Hector (2005). Asignación dinámica de Memoria y estructuras dinámicas. Consultado en Octubre 23 de 2008 en http://www.fismat.umich.mx/mn1/manual/node10.html. DAVINSON, Steven (2001). Función Calloc Ansi C. Consultado en Junio 23 de 2009 en http://www.conclase.net/c/librerias/funcion.php?fun=calloc. SOTO, Lauro (2005). Manejo de Memoria. Consultado en Junio 23 de 2009 en http://www.programacionfacil.com/estructura_de_datos/manejo_de_memoria.

Page 57: 301305 Estructura de Datos

57

UNIVERSIDAD NACIONAL ABIERTA Y A DISTANCIA – UNAD ESCUELA DE CIENCIAS BÁSICAS TECNOLOGÍA E INGENIERÍA CONTENIDO DIDÁCTICO DEL CURSO: 301305 – ESTRUCTURA DE DATOS

UNIDAD 2

Nombre de la Unidad

ESTRUCTURA DE DATOS LINEALES

Introducción

La presente Unidad se ha dividido en tres capítulos donde se aborda ampliamente la conceptualización de las estructura de datos lineales, con aplicación de programas completos, codificados en C++. Para la compilación de los programas, puede utilizarse cualquier compilador de C++ de los muchos que están disponibles como es el caso de Las versiones de Borland C++ 3.0, Borland C++ 4.5, Borland C++ 5.02 y Borland C++ 5.5 y DevC++ en cualquiera de sus versiones, esto solo por mencionar algunas. En el capítulo 4 se trata el tema de Pilas, profundizando en las operaciones que se pueden realizar con implementaciones de programas en C++. En el capítulo 5 se trata el tema de Colas con sus operaciones e implementación de programas codificados en C++. Finalmente en el capítulo 6 se aborda el tema de las listas, tipos de listas y sus operaciones con implementación de programas codificados en C++. Al final de la unidad, se plantean algunas actividades complementarias que buscan determinar el grado de apropiación del conocimiento, basados en los tres momentos: Reconocimiento, Profundización y transferencia, que pueden dar soporte valorativo al logro de las competencias del curso.

Justificación

El contenido de esta unidad tiene gran aplicabilidad en situaciones reales cotidianas que pueden ser representadas por medio de la pilas, colas y listas, es muy común y fácil de llevar a la realidad, por ejemplo una lista de clientes, proveedores, una pila de productos, una cola para realizar una consignación en un banco o un servidor para el manejo de impresiones, al igual que lo vemos representado a diario en el uso de cualquier herramienta de Oficce con la opción deshacer, al eliminar la última orden recibida.

Page 58: 301305 Estructura de Datos

58

UNIVERSIDAD NACIONAL ABIERTA Y A DISTANCIA – UNAD ESCUELA DE CIENCIAS BÁSICAS TECNOLOGÍA E INGENIERÍA CONTENIDO DIDÁCTICO DEL CURSO: 301305 – ESTRUCTURA DE DATOS

Intencionalidades Formativas

Conocer y aplicar el funcionamiento de las estructuras de datos lineales. Determinar las técnicas y estructuras utilizadas, desde las perspectivas de las aplicaciones de software, para resolver problemas mediante la utilización de las estructuras lineales pilas, colas y listas. Profundizar en la fundamentación teórica y práctica de las estructuras dinámicas lineales Pilas, Colas y Listas. Implementar el uso de las estructuras dinámicas lineales dando solución a situaciones reales.

Capítulo 4 Pilas Lección 1 Conceptos básicos de pilas Lección 2 Operaciones realizadas con pilas Lección 3 Operaciones básicas con pilas paso a paso Lección 4 Análisis del código propuesto para implementar una pila Lección 5 Aplicación de las estructuras lineales tipo pilas Capítulo 5 Colas Lección 6 Conceptos básicos de colas Lección 7 Operaciones básicas con colas Lección 8 Implementación de las Colas por medio de Punteros Lección 9 Implementación del código completo de la cola Lección 10 Aplicación de una cola en un entorno real planificador de citas Capítulo 6 Listas Lección 11 Concepto básicos de Listas Lección 12 Listas enlazadas Lección 13 Más a cerca de listas enlazadas Lección 14 Listas doblemente enlazadas Lección 15 Listas circulares

Page 59: 301305 Estructura de Datos

59

UNIVERSIDAD NACIONAL ABIERTA Y A DISTANCIA – UNAD ESCUELA DE CIENCIAS BÁSICAS TECNOLOGÍA E INGENIERÍA CONTENIDO DIDÁCTICO DEL CURSO: 301305 – ESTRUCTURA DE DATOS

CAPITULO 4: PILAS

Introducción

Las pilas son un tipo de estructura de datos de tipo lineal condicionadas donde las inserciones y eleminaciones se realizan por un mismo extremo. Se tratan los temas relacionados con los conceptos básicos de las pilas, las operaciones que se pueden realizar con las pilas, todo conjugado en programas de aplicación, implementados con apuntadores, al igual que en los anteriores capítulos, cada uno de los programas aquí presentados, están previamente compilados y depurados de tal manera que se mustra la salida en pantalla de cada uno. Lo anterior garantiza al estudiante que puede guiarse en el código fuente para hacerle modificaciones y proponer soluciones a entornos reales. Lección 1: Conceptos básicos de pilas La pila se considera un grupo ordenado de elementos porque estos están clasificados de acuerdo al tiempo en que estén residiendo en la pila, el elemento que se elimina de la cabeza es siempre el que lleve menos tiempo en ella. En resumen una pila es una lista en la cual los elementos solo pueden ser insertados y eliminados por un extremo de ella, este extremo es llamado la cima. De esta forma los elementos son eliminados en forma contraria a como fueron insertados.

Definición de una Pila Una pila llamada stack (en inglés) se puede definir como un tipo especial de lista lineal condicionada, en la que las inserciones y el borrado de nuevos elementos se realizan sólo por un extremo, que se denomina cima o tope top (en inglés). La pila es una estructura con numerosas analogías en la vida real: pila de platos, una pila de monedas, una pila de camisas, una pila de animales, etc. Como se muestra en la figura siguiente.

Page 60: 301305 Estructura de Datos

60

UNIVERSIDAD NACIONAL ABIERTA Y A DISTANCIA – UNAD ESCUELA DE CIENCIAS BÁSICAS TECNOLOGÍA E INGENIERÍA CONTENIDO DIDÁCTICO DEL CURSO: 301305 – ESTRUCTURA DE DATOS

Figura 20 Representación gráfica de una pila de monedas

Fuente: www.utpl.edu.ec/ecc/wiki/images/1/1e/Pilas.JPG

Una pila, a un nivel físico puede representarse tal como se muestra en figura 21, donde representa una pila de moneda o una pila de platos en un restaurante. Cuando se habla de una pila a nivel lógico, es una estructura de datos lineal compuesta de elementos del mismo tipo, en la cual cada uno de ellos solo puede ser insertado y eliminado por su parte final, es decir por el extremo final. La posición final la llamamos cima o también cabeza de la pila; para darse una mejor representación (abstracción) de ella, su representación gráfica en el papel la se hace en forma vertical, con la cima en la parte de arriba. De esta forma cuando se añade un nuevo elemento solo podrá ser colocado en la parte superior, piense en una pila de platos de cocina o en una pila de libros, los cuales se colocan en orden uno encima de otro. Por lo anterior las pilas también son llamadas listas en las cuales el último elemento en entrar es el primero en salir, en inglés el acrónimo LIFO(Last Input, First Out).

Lección 2: Operaciones realizadas con pilas Las operaciones básicas que se pueden realizar con la implementación de una lista lineal condicionada tipo pila son: la inserción la eliminación y la visualización de sus elementos. Esta implementación se lleva a cabo haciendo uso de punteros con listas enlazadas al igual que por medio de arreglos unidimensionales.

Page 61: 301305 Estructura de Datos

61

UNIVERSIDAD NACIONAL ABIERTA Y A DISTANCIA – UNAD ESCUELA DE CIENCIAS BÁSICAS TECNOLOGÍA E INGENIERÍA CONTENIDO DIDÁCTICO DEL CURSO: 301305 – ESTRUCTURA DE DATOS

Una Pila es una estructura de datos que almacena elementos de un tipo determinado, tal como se trató en la unidad uno en el tema relacionado con los tipos de datos. Es así como se sigue la política de que el primer elemento que se extrae, es decir se desapila, es el último que se introdujo o se apiló, cumpliendo con el enunciado que dice que el primero en salir, es el ultimo en entrar (LIFO). En la figura 22 se visualiza gráficamente la entrada y salida de elementos de una pila.

Figura 21 Entrada y salida de elementos de una pila

En principio, la pila está vacía y el puntero de la pila o CIMA debe estar en cero. Al insertar un elemento en la pila, se incrementa el puntero en una unidad. Mientras que al sacar un elemento de la pila se decrementa en una unidad el puntero, teniendo aplicabilidad las operaciones que se realizan con punteros tratadas en la Unidad uno. Siendo P el puntero (*P), al manipular una pila se deben realizar algunas comprobaciones. En una pila vacía no se pueden sacar datos, así que si (P = 0) no es posible eliminar elementos de la pila. En condiciones Ideales, una pila puede contener un número ilimitado de elementos y no producir nunca desbordamiento. En la práctica, el espacio de almacenamiento disponible es finito dependen de los recursos de memoria de la máquina (los recursos computacionales son finitos). La codificación de una pila requiere un cierto equilibrio, ya que si la longitud máxima de la pila es demasiado grande, se gasta mucha memoria, mientras que un valor pequeño producirá desbordamientos con mucha frecuencia.

Page 62: 301305 Estructura de Datos

62

UNIVERSIDAD NACIONAL ABIERTA Y A DISTANCIA – UNAD ESCUELA DE CIENCIAS BÁSICAS TECNOLOGÍA E INGENIERÍA CONTENIDO DIDÁCTICO DEL CURSO: 301305 – ESTRUCTURA DE DATOS

Para trabajar fácilmente con pilas, es conveniente diseñar funciones o subprogramas para cada una de las operaciones que se realizan con pilas, es decir una función para insertar (push) otra para extraer (pop) o eliminar elementos y la función para visualizar los elementos insertados en la pila. No hay que olvidar comprobar con frecuencia si la pila está vacía; si el puntero es igual a NULL (puntero=NULL). En la siguiente sección se enumeran los pasos algorítmicamente para la implementación de las operaciones que se realizan con las pilas. Para ello se declaran dos punteros: cima y auxiliar. Dado que los elementos se incorporan siempre por un extremo se tiene: 1. cima apunta al último elemento de la pila es decir a NULL. 2. Reservar memoria (auxiliar) 3. Se Introduce la información en auxiliar elemento 4. Se hace que auxiliar cima es decir que apunte a donde cima 5. Se cambia cima para que apunte a donde lo hace auxiliar 6. La pila tiene un elemento más. Esta rutina se repite para insertar los elementos requeridos en la pila. Los elementos se recuperan en orden inverso a como fueron introducidos. 1. Cima apunta al último elemento de la pila. 2. Se hace que auxiliar apunte a donde apuntaba cima 3. Se hace que cima pase a apuntar a donde cima cima 4. Liberar memoria reservada (auxiliar) 5. La pila tiene un elemento menos El prototipo de nodo típico para construir pilas es a través de las estructuras. struct pila { int dato; struct pila *siguiente; }; Lección 3: Operaciones básicas con pilas paso a paso Después de haber realizado la lectura detallada y analizado la aplicabilidad que se le puede dar a las pilas, se continúa con la implementación. Tal como se mencionó en capítulos anteriores. La implementación de las estructuras lineales se puede realizar por medio de listas enlazadas con punteros o por medio de arreglos. En este curso profundizaremos con más detalle en la implementación de las listas enlazadas con punteros, la razón se debe a que el tema de los arreglos se trata en

Page 63: 301305 Estructura de Datos

63

UNIVERSIDAD NACIONAL ABIERTA Y A DISTANCIA – UNAD ESCUELA DE CIENCIAS BÁSICAS TECNOLOGÍA E INGENIERÍA CONTENIDO DIDÁCTICO DEL CURSO: 301305 – ESTRUCTURA DE DATOS

detalle en los cursos Algoritmos e introducción a la programación, creando así la necesidad de profundizar en la implementación de las estructuras lineales con el tema de punteros. Se recomienda seguir las siguientes instrucciones paso a paso y obtendrá la implementación básica de una pila para el manejo de números enteros ingresados en tiempo de ejecución, es decir por teclado, para lo cual se hará uso de un menú de opciones y tres funciones básicas para insertar visualizar y extraer datos de la pila. Se inicia abriendo un documento nuevo en cualquier editor del cual disponga, inclusive puede trabajar en el bloc de notas que provee su sistema operativo, para este caso usaremos el editor de Turbo C++, ingrese los archivos de cabecera, también llamados librerías, estas son básicas por ser las más usadas. #include<iostream.h> #include<stdio.h> #include<stdlib.h> #include<conio.h> #include<dos.h> En este caso se crea una estructura para el manejo de la información que contendrá la pila, aunque solo se manejarán datos de tipo entero, es bueno recordar que una estructura es una colección de una o más variables, agrupadas bajo un solo nombre para facilitar su manejo, a diferencia de las que se encuentran en arreglos, pueden ser de diferentes tipos de variables del C++, incluyendo arreglos y otras estructuras. Cada variable dentro de una estructura se llama un miembro de la estructura. Después de cerrar la llave de la estructura y del punto y coma, en una línea aparte se declaran las variables apuntadores requeridas para manipular los datos de la pila, estos son del mismo tipo de la estructura inicializados a NULL, son ellos *inicio y *c. struct pila { int numero; struct pila *sig; }; struct pila *inicio=NULL; struct pila *c=NULL; Otra forma de declarar la estructura es poner a continuación de la definición de la estructura una lista de uno o más nombres de variables inicializadas llamadas instancias como se muestra acontinuación.

Page 64: 301305 Estructura de Datos

64

UNIVERSIDAD NACIONAL ABIERTA Y A DISTANCIA – UNAD ESCUELA DE CIENCIAS BÁSICAS TECNOLOGÍA E INGENIERÍA CONTENIDO DIDÁCTICO DEL CURSO: 301305 – ESTRUCTURA DE DATOS

struct pila { int numero; struct pila *sig; }*inicio=NULL, *c=NULL; Para continuar con el programa se escoge la segunda alternativa, que tiene entre sus miembros una variable llamada numero de tipo entero que guardará los números que serán ingresados, al igual que un puntero llamado sig del tipo struct pila, del mismo tipo de la estructura usado para apuntar al siguiente nodo de la pila. Finalmente se declaran como instancias, dos variables apuntador del mismo tipo de la estructura llamadas inicio y c inicializadas a NULL como buena costumbre. Estas variables son llamadas instancias que son del mismo tipo de la estructura, inicio usada para reservar memoria y c usada para recorrer la pila; una vista de lo hecho hasta ahora es:

Figura 22 Declaración de la estructura pila

Implementación del menú de opciones para manipular la pila Se continúa con la función principal haciendo uso de un menú de opciones que a mi juicio es la mejor alternativa para interactuar con las estructuras lineales. En este punto es importante compilar el programa para depurar y corregir los posibles errores de sintaxis o de estructura, por lo pronto en las 3 opciones del menú solo desplegará un corto mensaje ya que las funciones de insertar visualizar y extraer aun no han sido declaradas. Void main()

Page 65: 301305 Estructura de Datos

65

UNIVERSIDAD NACIONAL ABIERTA Y A DISTANCIA – UNAD ESCUELA DE CIENCIAS BÁSICAS TECNOLOGÍA E INGENIERÍA CONTENIDO DIDÁCTICO DEL CURSO: 301305 – ESTRUCTURA DE DATOS

{ textcolor(10); int opc=0; do { clrscr(); cout<<" MANEJO DE UNA ESTRUCTURA TIPO PILA "; cout<<"\n\n\n"); cout<<"1. Insertar\n"); cout<<"2. Extraer\n"); cout<<"3. Visualizar\n"); cout<<"4. Salir\n\n"); cout<<"Digite la opcion: "); cin >>opc; switch (opc) { case 1: cout<<"inserter"; break; case 2: cout<<"extraer"; break; case 3: cout<<"visualizar"; break; case 4: exit(1); } getch(); }while (opc!=4) } El código de la función main() o también llamada función principal que se incluye en el programa en construcción, no amerita algún tipo de explicación, es conocido y muy usado en el curso Introducción a la Programación. Guarde el programa con un nombre, puede ser Pila.cpp. Compile y ejecute el programa, si lo digitó cuidadosamente no generará errores de compilación tan poco errores de ejecución, se obtendrá el siguiente resultado después de haber digitado la opción 1.

Page 66: 301305 Estructura de Datos

66

UNIVERSIDAD NACIONAL ABIERTA Y A DISTANCIA – UNAD ESCUELA DE CIENCIAS BÁSICAS TECNOLOGÍA E INGENIERÍA CONTENIDO DIDÁCTICO DEL CURSO: 301305 – ESTRUCTURA DE DATOS

Figura 23 Menú de opciones de la pila

El color verde del texto es gracias a la función textcolor(10) incluida en la primera línea de código de la función principal main(). Hasta aquí todo va bien, ahora se va a alimentar el programa con la función de insertar, la cual insertará los datos numéricos en la pila. Implementación de la función insertar() de la pila Se define la función insertar(), no tiene parámetros y no devolverá ningún valor por eso es declarada de tipo void, esta línea de código se adiciona al código justo después de donde está definida la estructura, será el sitio dentro del código del programa para definir las tres funciones a utilizar tal como se muestra en la figura 25, una vez incluida la línea de código void insertar(void); Figura 24 Definición de la función insertar()

El otro cambio que se hará al código inicial, es en el case 1 del swich cambiamos el mensaje a desplegar cout<<”insertar”; por insertar(); usado por el programa principal para llamar a la función insertar(). Se visualiza en figura 26.

Page 67: 301305 Estructura de Datos

67

UNIVERSIDAD NACIONAL ABIERTA Y A DISTANCIA – UNAD ESCUELA DE CIENCIAS BÁSICAS TECNOLOGÍA E INGENIERÍA CONTENIDO DIDÁCTICO DEL CURSO: 301305 – ESTRUCTURA DE DATOS

Figura 25 La función insertar() en el case 1

El siguiente código contiene las instrucciones de la función insertar(), se incluirá al final del código, después de cerrar las instrucciones de la función principal main(). void insertar (void) { inicio=(struct pila *)malloc(sizeof(struct pila)); clrscr(); cout<<"Digite el dato de tipo ENTERO: "); cin>>inicio->numero; if (c==NULL) { c=inicio; inicio->sig=NULL; } else { inicio->sig=c; c=inicio; } } En la figura 27 se visualiza el código de las instrucciones de la función insertar().

Page 68: 301305 Estructura de Datos

68

UNIVERSIDAD NACIONAL ABIERTA Y A DISTANCIA – UNAD ESCUELA DE CIENCIAS BÁSICAS TECNOLOGÍA E INGENIERÍA CONTENIDO DIDÁCTICO DEL CURSO: 301305 – ESTRUCTURA DE DATOS

Figura 26 Instrucciones de la función insertar()

Hasta el momento se tiene definida la función insertar() al inicio del código, de igual manera se tiene todo el código de la función insertar() y la instrucción para llamar a insertar() desde la función principal en la opción 1 del case del menú de opciones. Este procedimiento se debe repetir para las otras dos funciones que faltan, es decir la función visualizar() y la función extraer(). Para probar lo hecho hasta el momento se ejecuta el código, pues ya se puede insertar los datos numéricos a la pila, pero que bueno sería si se pudiesen listar los datos insertados. Para ello incluiremos en el código en construcción la función visualizar() que es la opción 3 de el menú de opciones, se seguirán las indicaciones y los cambios al código que se llevaron a cabo para la función insertar(). Implementación de la función visualizar() de la pila Se inicia definiendo la función para viualizar los datos ingresados, la línea de código es: void visualizar(void); se incluye en el espacio usado para la definición de las funciones justo en la línea siguiente de donde se definió la función insertar. Posteriormente se modifica el case 3 del swich en el menú de opciones, cambiando el mensaje a desplegar cout<<”visualizar”; por visualizar(); usado para que el programa principal haga el llamado a la función y así poder seleccionar esta opción para tener en pantalla los datos previamente insertados a la pila. Siguiendo con la construcción de la pila queda adicionar al final del código principal la declaración completa de la función visualizar() que se incluye a continuación y que no hay código desconocido que amerite explicación alguna.

Page 69: 301305 Estructura de Datos

69

UNIVERSIDAD NACIONAL ABIERTA Y A DISTANCIA – UNAD ESCUELA DE CIENCIAS BÁSICAS TECNOLOGÍA E INGENIERÍA CONTENIDO DIDÁCTICO DEL CURSO: 301305 – ESTRUCTURA DE DATOS

void visualizar (void) { if (c==NULL) { clrscr(); cout<<"NO HAY ELEMENTOS A LISTAR"); } else { clrscr(); inicio=c; while (inicio!=NULL) { cout<<"Numero: "<<inicio->numero<<endl; inicio=inicio->sig; } } getch(); } Con la inclusión de este código ya se tiene el programa con las opciones de insertar y visualizar los datos de la pila, es importante que compile el programa para depurar y corregir posibles errores. Sin embargo si siguió las instrucciones paso a paso no debe haber errores de sintaxis. Finalmente, solo queda incluir la opción de extraer o eliminar datos de la pila con esta opción tendremos la implementación completa del programa básico para el manejo de una pila. Manos a la obra. Implementación de la función extraer de la pila Como en los dos casos anteriores se siguen las mismas directrices declarando la función extraer, en el espacio utilizado para tal fin, el código es: Void extraer(void); con esta se completa la declaración de las tres funciones como se puede observar en la figura 28.

Page 70: 301305 Estructura de Datos

70

UNIVERSIDAD NACIONAL ABIERTA Y A DISTANCIA – UNAD ESCUELA DE CIENCIAS BÁSICAS TECNOLOGÍA E INGENIERÍA CONTENIDO DIDÁCTICO DEL CURSO: 301305 – ESTRUCTURA DE DATOS

Figura 27 Vista de la definición de las funciones insertar, visualizar y extraer

Se continúa modificando el case 2 del swich cambiando el mensaje a desplegar cout<<”extraer”; por extraer(); usado para que el programa principal haga el llamado a la función y así se podrá seleccionar esta opción para la eliminación del último elemento que fue insertado a la pila, se puede comprobar haciendo uso de la opción 3 del menú de opciones se visualizarán los datos que aún quedan en la pila, pero no sin antes definir al final del código principal de la pila, las instrucciones completas de la función extraer() que se incluyen a continuación. void extraer (void) { if (c==NULL) { clrscr(); printf("NO HAY ELEMENTOS A ELIMINAR"); getch(); } else { inicio=c; cout<<"El dato a eliminar es: "<<inicio->numero; delay(1000); c=c->sig; free(inicio); } } Lección 4: Análisis del código propuesto para implementar una pila Al hacer una revisión detallada al código de la función insertar(), se encuentra la función malloc( ) tratada con detalle en la primera unidad, encargada de asignar un bloque de memoria del tamaño requerido y regresa un apuntador.

Page 71: 301305 Estructura de Datos

71

UNIVERSIDAD NACIONAL ABIERTA Y A DISTANCIA – UNAD ESCUELA DE CIENCIAS BÁSICAS TECNOLOGÍA E INGENIERÍA CONTENIDO DIDÁCTICO DEL CURSO: 301305 – ESTRUCTURA DE DATOS

El valor regresado por malloc( ) ha sido asignado a inicio, un apuntador al tipo struct pila, usando el apuntador y el operador de membresía indirecta (-->) se puede accesar a los miembros de la estructura como lo indica la línea de código siguiente. cin>>inicio->numero; se encuentra un condicional que indica que si no hay elementos en el apuntador c está en NULL, entonces se insertan datos por primera vez a la pila. El apuntador c apunta a donde apunta inicio, lo indica la línea de código c=inicio; indirectamente guardan la misma información, posteriormente se hace que el nuevo nodo apunte a NULL en la línea de código inicio->sig=NULL; Si la pila no está vacía se hace que el nuevo nodo inicio a punte a c como lo indica el código inicio->sig=c; ahora c es el nuvo nodo de la pila. Finaliza así las instrucciones de la función insertar( ). En cuanto a la función visualizar() no amerita un análisis profundo, dado que son instrucciones básicas como un condicional que verifica si el puntero c es igual a NULL, es decir si no hay elementos en la pila, saca un mensaje indicando que la pila está vacía, en caso contrario se hace un recorrido por cada elemento de la pila visualizando su contenido de la variable apuntador inicio. Revisando el código de la función extraer( ), se tiene que en el caso de que existan datos en la pila se guardan en inicio la ubicación de c según el código inicio=c; la instrucción cout<<"El dato a eliminar es: "<<inicio->numero; visualiza en pantalla el dato a eliminar, por medio de la función delay() se visualiza por un espacio de tiempo limitado el dato a eliminar. Finalmente es importante que analice el código de cada función con el objetivo de que lo entienda, lo comprenda y pueda realizar las actividades propuestas, como aplicación a situaciones reales. De igual manera puede plantear cambios para optimizar el código propuesto, en caso de tener inquietudes recuerde que apelar a la bibliografía propuesta en el curso así como también puede consultar al tutor del curso. Es importante aclarar que en esta implementación se plantea solo una de tantas alternativas posibles que se pueden usar para la implementación de una estructura de datos lineales tipo pila. Para resumir la implementación del manejo de la pila que se realizó paso a paso, se incluye el listado completo. Copie este código, en su editor que puede ser el Bloc de Notas y lo guarda con el nombre Progra21.cpp en el directorio de ejecución que por defecto está configurado el compilador C:\TC\BIN, con esto ya tiene listo el programa para que lo abra desde el compilador de Turbo C++ de cualquiera de sus versiones.

Page 72: 301305 Estructura de Datos

72

UNIVERSIDAD NACIONAL ABIERTA Y A DISTANCIA – UNAD ESCUELA DE CIENCIAS BÁSICAS TECNOLOGÍA E INGENIERÍA CONTENIDO DIDÁCTICO DEL CURSO: 301305 – ESTRUCTURA DE DATOS

Código completo de la implementación de la pila

Progra21.cpp #include <iostream.h> #include <stdio.h> #include <stdlib.h> #include <conio.h> #include <dos.h> struct pila { int numero; struct pila *sig; }*inicio=NULL, *c=NULL; void insertar(void); void extraer(void); void visualizar(void); void main() { textcolor(10); int opc=0; do { clrscr(); cout<<" MANEJO DE UNA ESTRUCTURA TIPO PILA "; cout<<"\n\n\n"; cout<<"1. Insertar\n"; cout<<"2. Extraer\n"; cout<<"3. Visualizar\n"; cout<<"4. Salir\n\n"; cout<<"Digite la opcion: "; cin >>opc; switch (opc) { case 1: insertar();

Page 73: 301305 Estructura de Datos

73

UNIVERSIDAD NACIONAL ABIERTA Y A DISTANCIA – UNAD ESCUELA DE CIENCIAS BÁSICAS TECNOLOGÍA E INGENIERÍA CONTENIDO DIDÁCTICO DEL CURSO: 301305 – ESTRUCTURA DE DATOS

break; case 2: extraer(); break; case 3: visualizar(); break; case 4: exit(1); } getch(); }while (opc!=4); } void insertar (void) { inicio=(struct pila *)malloc(sizeof(struct pila)); clrscr(); cout<<"Digite el dato de tipo ENTERO: "; cin>>inicio->numero; if (c==NULL) { c=inicio; inicio->sig=NULL; } else { inicio->sig=c; c=inicio; } } void visualizar (void) { if (c==NULL) { clrscr(); cout<<"NO HAY ELEMENTOS A LISTAR"; }

Page 74: 301305 Estructura de Datos

74

UNIVERSIDAD NACIONAL ABIERTA Y A DISTANCIA – UNAD ESCUELA DE CIENCIAS BÁSICAS TECNOLOGÍA E INGENIERÍA CONTENIDO DIDÁCTICO DEL CURSO: 301305 – ESTRUCTURA DE DATOS

else { clrscr(); inicio=c; while (inicio!=NULL) { cout<<"Numero: "<<inicio->numero<<endl; inicio=inicio->sig; } } getch(); } void extraer (void) { if (c==NULL) { clrscr(); cout<<"NO HAY ELEMENTOS A ELIMINAR"; getch(); } else { inicio=c; cout<<"El dato a eliminar es: "<<inicio->numero; getch(); // delay(1000); c=c->sig; free(inicio); } } El resultado de la salida en pantalla de la implementación de la pila se puede visualizar en la figura 29 que se presenta a continuación.

Page 75: 301305 Estructura de Datos

75

UNIVERSIDAD NACIONAL ABIERTA Y A DISTANCIA – UNAD ESCUELA DE CIENCIAS BÁSICAS TECNOLOGÍA E INGENIERÍA CONTENIDO DIDÁCTICO DEL CURSO: 301305 – ESTRUCTURA DE DATOS

Figura 28 Salida en pantalla de Progra21.cpp

Lección 5: Aplicación de las estructuras lineales tipo pilas

Al inicio del capítulo se mencionó las dos posibilidades para la implementación de las estructuras lineales por medio de listas enlazadas con punteros y por medio de arreglos unidimensionales, en el curso se hará énfasis en la implementación con listas enlazadas, es así como en el progra21.cpp se implementa una pila para gestionar datos de tipo entero, pero valdría la pena implementar una pila para la gestión de otro tipo de datos, para lo cual se pone a disposición un código completo para la implementación de una pila para gestionar datos de cadena de carácter con nombres de personas. Progra22.cpp #include <stdio.h> #include <conio.h> #include <stdlib.h> #include <iostream.h> void insertar(void); void extraer(void); void visualizar(void); struct pila { char nombre[20]; struct pila *ant; };

Page 76: 301305 Estructura de Datos

76

UNIVERSIDAD NACIONAL ABIERTA Y A DISTANCIA – UNAD ESCUELA DE CIENCIAS BÁSICAS TECNOLOGÍA E INGENIERÍA CONTENIDO DIDÁCTICO DEL CURSO: 301305 – ESTRUCTURA DE DATOS

struct pila *CAB=NULL,*AUX=NULL; main() { char opc; do { clrscr(); gotoxy(30,8); cout<<"1.- Insertar"; gotoxy(30,10); cout<<"2.- Extraer"; gotoxy(30,12); cout<<"3.- Visualizar la pila"; gotoxy(30,14); cout<<"4.- Salir"; gotoxy(20,16); cout<<"Ingrese una opcion : "; cin>> opc; // opc=getch( ); otra forma switch(opc) { case '1': insertar( ); break; case '2': extraer( ); break; case '3': visualizar( ); } // getch(); es opcional }while (opc!='4'); return 0; } //FUNCION PARA INSERTAR DATOS A LA PILA

Page 77: 301305 Estructura de Datos

77

UNIVERSIDAD NACIONAL ABIERTA Y A DISTANCIA – UNAD ESCUELA DE CIENCIAS BÁSICAS TECNOLOGÍA E INGENIERÍA CONTENIDO DIDÁCTICO DEL CURSO: 301305 – ESTRUCTURA DE DATOS

void insertar(void) { AUX=(struct pila *)malloc(sizeof(struct pila)); clrscr(); cout<<"INGRESAR DATOS DE LA PILA \n\n "; cout<<"Nombre: "; gets(AUX->nombre); if (CAB==NULL) { CAB=AUX; AUX->ant=NULL; } else { AUX->ant=CAB; CAB=AUX; } } //FUNCION DE ELINIMAR ELEMENTOS DE LA PILA void extraer(void) { if (CAB==NULL) return; AUX=CAB; CAB=CAB->ant; free(AUX); cout<<"\n Se elimino a " <<AUX->nombre <<" de la pila"; getch(); } //FUNCION DE VISUALIZAR LA PILA void visualizar(void) { if (CAB==NULL) return; clrscr();

Page 78: 301305 Estructura de Datos

78

UNIVERSIDAD NACIONAL ABIERTA Y A DISTANCIA – UNAD ESCUELA DE CIENCIAS BÁSICAS TECNOLOGÍA E INGENIERÍA CONTENIDO DIDÁCTICO DEL CURSO: 301305 – ESTRUCTURA DE DATOS

AUX=CAB; cout<<"DATOS DE LA PILA \n\n "; while (AUX!=NULL) { cout<<"Nombre: "<<AUX->nombre <<endl; AUX=AUX->ant; } getch( ); } El resultado después de haber compilado y ejecutado el listado llamado progra22 se conjuga en la figura22 que se muestra a continuación.

Figura 29 Salida en pantalla de Progra22.cpp

Progra23.cpp

#include <stdio.h> #include <conio.h> #include <stdlib.h> /*************** DEFINICION DEL NODO (Estructura) **************/ struct nodo { char nombre[40]; // Datos del nodo Entero int edad; double salario; struct nodo *sig; // Puntero a otro nodo }; /****************************************************************/ struct nodo *tope; // tope de nuestra PILA

Page 79: 301305 Estructura de Datos

79

UNIVERSIDAD NACIONAL ABIERTA Y A DISTANCIA – UNAD ESCUELA DE CIENCIAS BÁSICAS TECNOLOGÍA E INGENIERÍA CONTENIDO DIDÁCTICO DEL CURSO: 301305 – ESTRUCTURA DE DATOS

/************************ Push (Insertar) ***********************/ void Push() // Funcion que inserta datos a la pila { struct nodo *p; p = (struct nodo*) malloc(sizeof(struct nodo)); // reservamos // espacio para el nodo (dato, sig) printf("Escriba el nombre: "); scanf("%s",p->nombre); if(tope == NULL) { // si no hay elemetos el tope esta en NULL // insertamos por primera vez a la pila printf("Escriba la Edad: "); scanf("%d",&p->edad); printf("Escriba el Salario: "); scanf("%d",&p->salario); p->sig = NULL; // hacemos que el nuevo nodo apunte a NULL tope = p; // Ahora el tope es el nuevo nodo return; } // si no printf("Escriba la Edad: "); scanf("%d",&p->edad); printf("Escriba el Salario: "); scanf("%d",&p->salario); p->sig = tope; // hacemos que el nuevo nodo apunte al tope tope = p; // ahora el tope es el nuevo nodo } /************************** Pop (Sacar) *************************/ void Pop() { if(tope == NULL) { printf("PILA VACIA\n"); return; } int i; // es para almacenar el dato que tiene el tope struct nodo *tmp; // temporal para almacenar la direccion del tope tmp = tope; // guardamos en tmp la ubicacion del tope tope = tmp->sig; // hacemos que el tope sea el anterior nodo ingresado // sacamos el dato del nodo que estaba como tope

Page 80: 301305 Estructura de Datos

80

UNIVERSIDAD NACIONAL ABIERTA Y A DISTANCIA – UNAD ESCUELA DE CIENCIAS BÁSICAS TECNOLOGÍA E INGENIERÍA CONTENIDO DIDÁCTICO DEL CURSO: 301305 – ESTRUCTURA DE DATOS

printf("Nombre : %s\n", tmp->nombre); printf("Edad : %d\n", tmp->edad); printf("Salario : %d\n", tmp->salario); free(tmp); // liberamos la memoria reservada para el tope } int menu() { int o = 0; do{ clrscr(); // limpiar pantalla printf(" GESTION DE UNA PILA DE EMPLEADOS: NOMBRE, EDAD, SALARIO\n\n"); printf("1. Insertar Empleado\n"); printf("2. Sacar Empleado\n"); printf("3. Vaciar Pila de Empleados\n"); printf("4. Salir\n\n"); printf("Ingrese la opcion : "); scanf("%d",&o); // leer opcion del teclado }while( o < 1 || o > 4); // mientras sea menor que 1 o mayor que 4 clrscr(); return o; } int main() { tope = NULL; // hacemos que el tope no apunte a nada (pila vacia) int d = 0; do { d = menu(); // retorna opcion switch(d) { case 1: Push(); break; case 2: { Pop(); getch(); break; } case 3:

Page 81: 301305 Estructura de Datos

81

UNIVERSIDAD NACIONAL ABIERTA Y A DISTANCIA – UNAD ESCUELA DE CIENCIAS BÁSICAS TECNOLOGÍA E INGENIERÍA CONTENIDO DIDÁCTICO DEL CURSO: 301305 – ESTRUCTURA DE DATOS

{ while(tope != NULL) Pop(); printf("PILA VACIA"); getch(); break; } } }while(d != 4); // mientras que la opcion no sea 4 return 0; } La salida en pantalla de progra23.cpp que se implementa con la sintaxis del lenguaje C, se puede visualizar en la figura 31 como se muestra a continuación.

Figura 30 Salida en pantalla de Progra23.cpp

Page 82: 301305 Estructura de Datos

82

UNIVERSIDAD NACIONAL ABIERTA Y A DISTANCIA – UNAD ESCUELA DE CIENCIAS BÁSICAS TECNOLOGÍA E INGENIERÍA CONTENIDO DIDÁCTICO DEL CURSO: 301305 – ESTRUCTURA DE DATOS

CAPITULO 5: COLAS

Introducción

Las colas al igual que las pilas, son una estructura de datos de tipo lineal condicionadas donde las inserciones y eleminaciones se realizan por extremos diferentes. Se abordan los temas relacionados con los conceptos básicos de las colas, las operaciones que se pueden realizar con las colas, todo conjugado en programas de aplicación, implementados con apuntadores. Se hace uso de un menú de opciones para cada programa y funciones para la inserción, visualización, y eliminación de nodos de la cola. Al igual que en los anteriores capítulos, cada uno de los programas aquí presentados, están previamente compilados y depurados de tal manera que se mustra la salida en pantalla de cada uno. Lo anterior garantiza al estudiante que puede guiarse en el código fuente para hacerle modificaciones y proponer soluciones a entornos reales.

Lección 6: Conceptos básicos de colas Las colas son otro tipo de estructura de datos lineales, similar a las pilas, diferenciándose de ellas en el modo de insertar/eliminar elementos. Así pues, la diferencia con las pilas reside en el modo de entrada/salida de datos; en las colas las inserciones se realizan al final de la lista, no al principio. Por ello, las colas se usan para almacenar datos que necesitan ser procesados según el orden de llegada. Una aplicabilidad de las colas puede realizarse en un sistema de computacional manejado a través de una red de computadoras donde se comparte una sola impresora para todos los equipos conectados a la red; de tal manera que se imprimirán los documentos en el orden en que se hace la petición de impresión de cada usuario. Formando así una cola de impresión. Definición de una cola Una cola es una estructura lineal de datos condicionada, en la que las eliminaciones se realizan al principio de la lista, es decir, al frente, y las inserciones se realizan en el extremo opuesto de la lista, es decir, al final. En las colas el elemento que entró de primero sale también de primero; por ello se conocen como listas FIFO, en ingles (first-in, first-out), primero en entrar, primero en salir.

Page 83: 301305 Estructura de Datos

83

UNIVERSIDAD NACIONAL ABIERTA Y A DISTANCIA – UNAD ESCUELA DE CIENCIAS BÁSICAS TECNOLOGÍA E INGENIERÍA CONTENIDO DIDÁCTICO DEL CURSO: 301305 – ESTRUCTURA DE DATOS

Una muy buena representación gráfica de las estructuras de datos tipo cola puede visualizarse en la Figura 32, que se muestra a continuación. Figura 31 Representación gráfica de una cola de personas.

Fuente: http://www.utpl.edu.ec/ecc/wiki/index.php/Imagen:Cola.JPG

Aplicación de las estructuras Lineales tipo Colas En la vida real se tiene ejemplos numerosos de colas: la cola de un autobuses, cola para ingresar al cine, caravana de coches en una calle, etc. En todas ellas el primer elemento (pasajero, coche, etc) que llega es el primero que sale. “En informática existen numerosas aplicaciones de las colas. Por ejemplo, en un sistema de tiempo compartido suele haber un procesador central y una serie de periféricos compartidos: discos, impresoras, etc. Los recursos se comparten por los diferentes usuarios y se utiliza una cola para almacenar los programas o peticiones de los diferentes usuarios que esperan su turno de ejecución. Es así como en un sistema multiprocesos, el procesador central atiende normalmente en un riguroso orden de llamada de peticiones del usuario; por tanto todas las llamadas se almacenan en una cola. Existe otra aplicación muy utilizada que se denomina cola de prioridades; en ella el procesador central no atiende por riguroso orden de llamada, aquí el procesador atiende por prioridades asignadas por el sistema o bien por el usuario y sólo dentro de las peticiones de igual prioridad se producirá una cola”4.

4 Tomado de: http://www.uhu.es/17207-18209/Transparencias/Tema3.pdf

Page 84: 301305 Estructura de Datos

84

UNIVERSIDAD NACIONAL ABIERTA Y A DISTANCIA – UNAD ESCUELA DE CIENCIAS BÁSICAS TECNOLOGÍA E INGENIERÍA CONTENIDO DIDÁCTICO DEL CURSO: 301305 – ESTRUCTURA DE DATOS

Una muy buena implementación de las colas podría realizarse un programa para manejar un planificador de citas en un consultorio médico, de tal manera que cada solicitud de una cita se va almacenando en la cola el nombre del paciente y la hora de la cita, en el mismo orden de fecha y hora en que se solicitó será atendida. En general en una cola, de la vida diaria, el primero que llega será atendido primero, pasando a continuación el segundo de la cola al frente; y cada que llega un nuevo elemento este se colocará al final de la cola. De aquí que el extremo por donde se insertan los elementos se llamará "final" y por donde se retiran "frente". Debido a esto último las colas también son llamadas listas en las cuales el primer elemento en entrar es el primero en salir. Para las colas que se trabajarán se sobreentenderá, a menos de decir lo contrario, que la regla es que siempre el primero se atiende primero.

Figura 32 Representación gráfica de una cola

Lección 7: Operaciones básicas con colas Nuevamente se encuentra una situación particular ante una estructura de datos con muy pocas operaciones disponibles. Las colas sólo permiten añadir, visualizar y eliminar elementos. Añadir: Inserta un elemento al final de la cola. Extraer: elimina un elemento del principio de la cola. Visualizar: muestra los elementos insertados en la cola Las operaciones en detalle que se pueden realizar con una cola son: Acceder al primer elemento de la cola. Añadir un elemento al final de la cola. Eliminar el primer elemento de la cola. Vaciar la cola. Verificar el estado de la cola: vacía, llena.

Page 85: 301305 Estructura de Datos

85

UNIVERSIDAD NACIONAL ABIERTA Y A DISTANCIA – UNAD ESCUELA DE CIENCIAS BÁSICAS TECNOLOGÍA E INGENIERÍA CONTENIDO DIDÁCTICO DEL CURSO: 301305 – ESTRUCTURA DE DATOS

Implementación de las listas tipo cola Para la implementación de estructura de datos tipo cola utilizaremos las listas enlazadas con apuntadores al igual que el uso de arreglos unidimensionales. Las funciones que manejarán la cola serán: Insertar() y Atender(). Se Desarrollarán estas dos funciones de forma "simultánea";

Implementación de las colas por con arreglos En vista de que las estructuras de datos lineales pueden ser implementadas también por medio de arreglos unidimensionales se ha puesto a consideración para efectos de análisis el siguiente listado llamado Progra24.cpp. Progra24.cpp #include <iostream.h> #include <iomanip.h> #include <conio.h> const int MaxiCola = 5; const int nulo = 1; int frente = nulo; int final = nulo; int cola[MaxiCola]; void Insertar(){ if ( (final+1 == MaxiCola && frente == 0) || (final+1 == frente) ) { cout << "La cola está llena "; getch(); } else if (frente == nulo) { //la cola estaba vacía frente = final = 0; cout << "\n\n Ingrese el elemento a insertar: "; cin >> cola[frente]; } else { final++; if (final == MaxiCola) final = 0;

Page 86: 301305 Estructura de Datos

86

UNIVERSIDAD NACIONAL ABIERTA Y A DISTANCIA – UNAD ESCUELA DE CIENCIAS BÁSICAS TECNOLOGÍA E INGENIERÍA CONTENIDO DIDÁCTICO DEL CURSO: 301305 – ESTRUCTURA DE DATOS

cout << "\n\n Ingrese el Elemento a insertar: "; cin >> cola[final]; } } void Atender() { if (frente == nulo) cout << "\nCola vacia\a"; else { cout << "\nEliminando elemento: " << cola[frente]; if (frente == final) // cola quedó vacía frente = final = nulo; else{ frente++; if (frente == MaxiCola) frente = 0; } } } void Listar() { int i; if (frente==nulo) cout << "\nLa cola esta vacia \a\n"; else if (frente <= final) for (i=frente; i <= final; i++) cout <<setw(4) << cola[i]; else { for (i=frente; i < MaxiCola; i++) cout << setw(4) << cola[i]; for (i=0; i <= final; i++) cout << setw(4) << cola[i]; } } void main() { char opcion; do{

Page 87: 301305 Estructura de Datos

87

UNIVERSIDAD NACIONAL ABIERTA Y A DISTANCIA – UNAD ESCUELA DE CIENCIAS BÁSICAS TECNOLOGÍA E INGENIERÍA CONTENIDO DIDÁCTICO DEL CURSO: 301305 – ESTRUCTURA DE DATOS

clrscr(); Listar(); cout << "\nIMPLENTACION DE UNA COLA CON ARREGLOS \n"; cout << "\n\nInsertar Atender Salir \n"; switch (opcion=getch()){ case 'I':; case 'i': Insertar(); break; case 'A':; case 'a': Atender(); break; } } while (opcion != 'S' && opcion != 's'); } El resultado de la salida en pantalla del Listado Implementado con arreglos llamado progra24.cpp se puede visualizar en la siguiente figura 34.

Figura 33 Salida en pantalla de progra24

Lección 8: Implementación de las Colas por medio de Punteros Representación de las Colas

Las colas también se pueden representar como estructuras dinámicas, para ello se necesitan dos punteros que se llamarán: CAB, FIN y AUX. Las operaciones con colas son muy sencillas, prácticamente no hay casos especiales, salvo que la cola esté vacía. Añadir un elemento a una cola vacía Se parte del hecho de que ya se tiene el nodo a insertar y por supuesto un puntero que apunte a él, además los punteros que definen la cola, CABEZA, FINAL y AUXILIAR que se inicializan a cero es decir valdrán NULL. El proceso es muy simple, bastará con que:

Page 88: 301305 Estructura de Datos

88

UNIVERSIDAD NACIONAL ABIERTA Y A DISTANCIA – UNAD ESCUELA DE CIENCIAS BÁSICAS TECNOLOGÍA E INGENIERÍA CONTENIDO DIDÁCTICO DEL CURSO: 301305 – ESTRUCTURA DE DATOS

1. AUXILIAR->sig apunte a NULL. 2. Que los punteros CABEZA y FINAL apunten a AUXILIAR. Añadir elemento en una cola no vacía De igual manera que el caso anterior se parte de un nodo a insertar, con un puntero que apunte a él, y de una cola, en este caso, al no estar vacía, los punteros CABEZA y FINAL no serán nulos. El proceso sigue siendo muy sencillo: 1. Se Hace que AUXILIAR->siguiente apunte a NULL. 2. Después que FINAL->siguiente apunte a AUXILIAR. 3. Se actualiza FINAL, haciendo que apunte a AUXILIAR. La siguiente función resume el anterior análisis realizado para la inserción de nodos a la cola void insertar(void) { AUXILIAR=(struct cola *)malloc(sizeof(struct cola)); clrscr(); cout<<"Nombre: "; gets(AUXILIAR->nombre); AUXILIAR->sig=NULL; if (FINAL==NULL) FINAL=CABEZA=AUXILIAR; else { FINAL->sig=AUXILIAR; FINAL=AUXILIAR; } } Extraer un elemento de una cola Extraer un elemento de una cola, implica eliminarlo definitivamente de la lista Se usará un puntero a un nodo auxiliar llamado CABEZA que apunta a la cabeza de la cola. Si la cola está vacía si CABEZA==NULL retorna al programa principal, desplegando el mensaje que indica el estado de la cola. . 1. Se hace que AUXILIAR apunte al primer elemento de la cola, es decir a CABEZA. 2. Se asigna a CABEZA la dirección del segundo nodo de la pila: CABEZA=CABEZA->sig.

Page 89: 301305 Estructura de Datos

89

UNIVERSIDAD NACIONAL ABIERTA Y A DISTANCIA – UNAD ESCUELA DE CIENCIAS BÁSICAS TECNOLOGÍA E INGENIERÍA CONTENIDO DIDÁCTICO DEL CURSO: 301305 – ESTRUCTURA DE DATOS

3. Se guarda el contenido del nodo para devolverlo como retorno, hay que recordar que la operación de lectura en colas implican también borrar. 4. se libera la memoria asignada al primer nodo, el que se quiere eliminar. Free (AUXILIAR); La siguiente función resume el anterior análisis realizado para la eliminación de nodos a la cola void extraer(void) { if (CABEZA==NULL) { cout<<"No hay elementos en la cola"; getch(); } else { AUXILIAR=CABEZA; cout<<"El dato eliminado es: "<<AUXILIAR->nombre; getch(); CABEZA=CABEZA->sig; free(AUXILIAR); } } Visualizar los elementos de una cola Se hará uso del puntero llamado CABEZA que apunta a la cabeza de la cola. Si la cola está vacía si CABEZA==NULL retorna al programa principal desplegando el mensaje que indica el estado de la cola. En caso contrario, que la cola tenga elementos 1. Se hace que AUXILIAR apunte al primer elemento de la cola, es decir a la CABEZA. 2. inicia el recorrido por todos los elementos de la cola, por medio del apuntador AUXILIAR, AUXILIAR->nombre, posteriormente a AUXILIAR se le asigna el valor del siguiente nodo, AUXILIAR=AUXILIAR->sig el proceso se repite hasta que este sea igual a NULL. La siguiente función representa el código que permite la visualización de los datos de la cola. void visualizar(void) { if (CABEZA==NULL)

Page 90: 301305 Estructura de Datos

90

UNIVERSIDAD NACIONAL ABIERTA Y A DISTANCIA – UNAD ESCUELA DE CIENCIAS BÁSICAS TECNOLOGÍA E INGENIERÍA CONTENIDO DIDÁCTICO DEL CURSO: 301305 – ESTRUCTURA DE DATOS

{ cout<<"NO HAY ELEMENTOS EN LA COLA"; getch(); } else { clrscr(); AUXILIAR=CABEZA; while (AUXILIAR!=NULL) { cout<<"Nombre:" <<AUXILIAR->nombre <<"\n"; AUXILIAR=AUXILIAR->sig; } getch(); } Lección 9: Implementación del código completo de la cola El siguiente listado llamado Progra25.cpp muestra el código completo de la implementación de la cola objeto del análisis en la lección anterior. Progra25.cpp #include <stdio.h> #include <iostream.h> #include <conio.h> #include <stdlib.h> void insertar(void); void extraer(void); void visualizar(void); struct cola { char nombre[20]; struct cola *sig; }*CABEZA=NULL,*AUXILIAR=NULL,*FINAL=NULL; main() { char opc; do {

Page 91: 301305 Estructura de Datos

91

UNIVERSIDAD NACIONAL ABIERTA Y A DISTANCIA – UNAD ESCUELA DE CIENCIAS BÁSICAS TECNOLOGÍA E INGENIERÍA CONTENIDO DIDÁCTICO DEL CURSO: 301305 – ESTRUCTURA DE DATOS

clrscr(); gotoxy(30,8); cout<<"1.- Insertar"; gotoxy(30,10); cout<<"2.- Extraer"; gotoxy(30,12); cout<<"3.- Visualizar la cola"; gotoxy(30,14); cout<<"4.- Salir"; gotoxy(25,16); cout<<"Ingrese la opcion :"; opc=getch( ); switch(opc) { case '1': insertar( ); break; case '2': extraer( ); break; case '3': visualizar( ); } }while (opc!='4'); return 0; } void insertar(void) { AUXILIAR=(struct cola *)malloc(sizeof(struct cola)); clrscr(); cout<<"Nombre: "; gets(AUXILIAR->nombre); AUXILIAR->sig=NULL; if (FINAL==NULL) FINAL=CABEZA=AUXILIAR; else { FINAL->sig=AUXILIAR; FINAL=AUXILIAR; } }

Page 92: 301305 Estructura de Datos

92

UNIVERSIDAD NACIONAL ABIERTA Y A DISTANCIA – UNAD ESCUELA DE CIENCIAS BÁSICAS TECNOLOGÍA E INGENIERÍA CONTENIDO DIDÁCTICO DEL CURSO: 301305 – ESTRUCTURA DE DATOS

void extraer(void) { if (CABEZA==NULL) { cout<<"No hay elementos en la cola"; getch(); } else { AUXILIAR=CABEZA; cout<<"El dato eliminado es: "<<AUXILIAR->nombre; getch(); CABEZA=CABEZA->sig; free(AUXILIAR); } } void visualizar(void) { if (CABEZA==NULL) { cout<<"NO HAY ELEMENTOS EN LA COLA"; getch(); } else { clrscr(); cout<<"ELEMENTOS DE LA COLA \n\n"; AUXILIAR=CABEZA; while (AUXILIAR!=NULL) { cout<<"Nombre:" <<AUXILIAR->nombre <<"\n"; AUXILIAR=AUXILIAR->sig; } getch(); } } La salida en pantalla de Progra25.cpp se puede visualizar en la figura 35 que se muestra a continuación.

Page 93: 301305 Estructura de Datos

93

UNIVERSIDAD NACIONAL ABIERTA Y A DISTANCIA – UNAD ESCUELA DE CIENCIAS BÁSICAS TECNOLOGÍA E INGENIERÍA CONTENIDO DIDÁCTICO DEL CURSO: 301305 – ESTRUCTURA DE DATOS

Figura 34 Salida en pantalla de Progra25.cpp

Lección 10: Aplicación de una cola en un entorno real planificador de citas

Un Ejemplo real como aplicación de las colas es la de un consultorio médico donde el Doctor tiene una secretaria a su servicio para manejar su agenda de citas médicas, el teléfono y la correspondencia. La secretaria organiza la agenda de las citas médicas asignadas a los pacientes que atenderá el Doctor. Las llamadas solicitando una cita médica se atienden en el orden de llegada. El siguiente programa de aplicación de una cola implementa un planificador de citas con un menú de iteraciones para gestionar la cola. Progra26.cpp #include <string.h> #include <stdlib.h> #include <stdio.h> #include <ctype.h> #include <conio.h> #include <iostream.h> #define MAX 5 char *p[MAX], *crecup(void); int spos=0; int rpos=0; char *crecup(void); void intro(void), calmac(char *c), revisar(void), eliminar(void); int main() { clrscr(); char s[80];

Page 94: 301305 Estructura de Datos

94

UNIVERSIDAD NACIONAL ABIERTA Y A DISTANCIA – UNAD ESCUELA DE CIENCIAS BÁSICAS TECNOLOGÍA E INGENIERÍA CONTENIDO DIDÁCTICO DEL CURSO: 301305 – ESTRUCTURA DE DATOS

register int t; for(t=0;t<MAX; ++t) p[t] = NULL; //Inicializa el arreglo for(;;) { cout<<"\n\nOPCIONES DE ITERACION DE LA COLA\n\n"; cout<<"I. Introducir\n"; cout<<"R. Revisar\n"; cout<<"E. Eliminar\n"; cout<<"S. Salir\n\n"; cout<<"Seleccione la opci¢n : "; gets(s); *s = toupper(*s); switch(*s) { case 'I': intro(); break; case 'R': revisar(); break; case 'E': eliminar(); break; case 'S': exit(0); } } } //INTRODUCIR CITAS EN LA COLA void intro(void) { char s[256], *p; do { cout<<"Introduce la cita " <<spos+1 <<" : "; gets(s); if(*s==0) break; //no hay entradas p = (char *)malloc(strlen(s)+1);

Page 95: 301305 Estructura de Datos

95

UNIVERSIDAD NACIONAL ABIERTA Y A DISTANCIA – UNAD ESCUELA DE CIENCIAS BÁSICAS TECNOLOGÍA E INGENIERÍA CONTENIDO DIDÁCTICO DEL CURSO: 301305 – ESTRUCTURA DE DATOS

if(!p) { cout<<"No hay memoria \n"; return; } strcpy(p, s); if(*s)calmac(p); }while(*s); clrscr(); } //ver que hay en la cola void revisar(void) { clrscr(); register int t; cout<<endl <<endl <<" LISTADO DE CITAS" <<endl <<endl; for(t=rpos;t<spos;++t) cout<<t+1 <<p[t] <<endl; } //Eliminar una cita de la cola void eliminar(void) { clrscr(); char *p; if ((p=crecup())==NULL) return; cout<<endl <<"CITA ELIMINADA:" <<p; } //guardar una cita void calmac(char *c) { if(spos==MAX) { cout<<"\n La Cola esta llena. Presione Intro \n"; return; } p[spos] = c; spos++;

Page 96: 301305 Estructura de Datos

96

UNIVERSIDAD NACIONAL ABIERTA Y A DISTANCIA – UNAD ESCUELA DE CIENCIAS BÁSICAS TECNOLOGÍA E INGENIERÍA CONTENIDO DIDÁCTICO DEL CURSO: 301305 – ESTRUCTURA DE DATOS

} //Recuperar una cita char *crecup(void) { if(rpos==spos) { cout<<"No hay mas citas \n"; return NULL; } rpos++; return p[rpos-1]; } El resultado después de haber compilado, depurado y ejecutado el listado Progra26.cpp se puede visualizar en la figura 36, que se muestra a continuación.

Figura 35 Salida en pantalla de progra26.cpp

El Listado llamado Progra26.cpp, implementa un planificador de citas, sería importante que analice detenidamente cada una de las instrucciones del código y así establecer las diferencias del código con la implementación de una PILA, así mismo se pide que modifique el programa para que guarde además del nombre de la persona, la hora de la cita, de tal manera que al visualizar la cola se muestren los datos completos.

Page 97: 301305 Estructura de Datos

97

UNIVERSIDAD NACIONAL ABIERTA Y A DISTANCIA – UNAD ESCUELA DE CIENCIAS BÁSICAS TECNOLOGÍA E INGENIERÍA CONTENIDO DIDÁCTICO DEL CURSO: 301305 – ESTRUCTURA DE DATOS

CAPITULO 6: LISTAS

Introducción

Las listas al igual que las pilas y las colas, son una estructura de datos de tipo lineal diferenciándose de las anteriores en el hecho de que pueden las inserciones y eleminaciones se en cualquier parte de la lista. Esto hace que tengan mayor aplicabilidad en el entorno real. Se abordan los temas relacionados con los conceptos básicos de las listas, así como tipos de listas y las operaciones que se pueden realizar con las listas, todo conjugado en programas de aplicación, implementados con apuntadores. Se hace uso de un menú de opciones para cada programa y funciones para la inserción, visualización, eliminación y búsqueda de nodos en la lista. Al igual que en los anteriores capítulos, cada uno de los programas aquí presentados, están previamente compilados y depurados de tal manera que se mustra la salida en pantalla de cada uno. Lo anterior garantiza al estudiante que puede guiarse en el código fuente para hacerle modificaciones y proponer soluciones a entornos reales.

Lección 11: Concepto básicos de Listas

Una lista enlazada es una colección o secuencia de elementos del mismo tipo dispuestos uno detrás de otro, en el que cada elemento se liga al siguiente elemento por un enlace que no es más que un puntero previamente definido. Las listas según su estructura se han dividido en cuatro grandes categorías: 1.- Listas Simplemente enlazadas 2.- Listas Doblemente enlazadas 3.- Listas Circular simplemente enlazada 4.- Lista circular doblemente enlazada

Lista simplemente enlazada Entre las listas simplemente enlazadas se encuentra un tipo de lista llamada Lista contigua: La cual se compone de un conjunto de elementos de un tipo dado que

Page 98: 301305 Estructura de Datos

98

UNIVERSIDAD NACIONAL ABIERTA Y A DISTANCIA – UNAD ESCUELA DE CIENCIAS BÁSICAS TECNOLOGÍA E INGENIERÍA CONTENIDO DIDÁCTICO DEL CURSO: 301305 – ESTRUCTURA DE DATOS

se encuentran ordenados y pueden variar en número. Esta es una definición general, que incluye los ficheros y vectores. Las entradas de una guía o directorio telefónico, por ejemplo, están en líneas sucesivas, excepto en las partes superior e inferior de cada columna. Una lista lineal se almacena en la memoria principal de una computadora en posiciones sucesivas de memoria; cuando se almacenan en cinta magnética, los elementos sucesivos se presentan en sucesión en la cinta. Esta asignación de memoria se denomina almacenamiento secuencial. Posteriormente, se verá que existe otro tipo de almacenamiento denominado encadenado o enlazado. Una lista lineal se almacena en la memoria de la computadora en posiciones sucesivas o adyacentes y se procesa como un arreglo unidimensional. En este caso, el acceso a cualquier elemento de la lista es fácil; sin embargo, la inserción o borrado requiere un desplazamiento de lugar de los elementos que le siguen y en consecuencia el diseño de un algoritmo específico. Para permitir operaciones con las listas como arreglos se deben dimensionar éstos con tamaño suficiente para que contengan todos los posibles elementos de la lista. La inserción o eliminación de un elemento, excepto en la cabecera o final de la lista, necesita una traslación de un parte de los elementos de la misma: la que precede o sigue a la posición del elemento modificado. Las operaciones directas de añadir y eliminar se efectúan únicamente en los extremos de la lista. Esta limitación es una de las razones por las que esta estructura es poco utilizada.

Operaciones con listas lineales contiguas Las operaciones que se pueden realizar con listas lineales contiguas son:

Insertar, eliminar o localizar un elemento. Determinar el tamaño – número de elementos – de la lista. Recorrer la lista para localizar un determinado elemento. Clasificar los elementos de la lista en orden ascendente o descendente. Unir dos o más listas en una sola. Dividir una lista en varias sublistas. Copiar la lista. Borrar la lista.

Page 99: 301305 Estructura de Datos

99

UNIVERSIDAD NACIONAL ABIERTA Y A DISTANCIA – UNAD ESCUELA DE CIENCIAS BÁSICAS TECNOLOGÍA E INGENIERÍA CONTENIDO DIDÁCTICO DEL CURSO: 301305 – ESTRUCTURA DE DATOS

Representación gráfica de una lista contigua Figura 36 Representación gráfica de una lista contigua

Como se puede apreciar en la figura 36 se trata de una lista contigua de elementos de tipo entero representados en un arreglo unidimensional de 6 campos, de tal manera que no es posible insertar un nuevo elemento por que la lista está completa. Esta es una de las desventajas de este tipo de lista. Lección 12: Listas enlazadas

Las listas enlazadas o de almacenamiento enlazado son mucho más flexibles y potentes, su uso es mucho más amplio comparado con la lista contigua. Una lista enlazada o encadenada es un conjunto de elementos del mismo tipo en los que cada elemento contiene la posición o dirección del siguiente elemento de la lista. Cada elemento de la lista enlazada debe tener al menos dos campos: un campo que tiene el valor del elemento y un campo (enlace, link) que contiene la posición del siguiente elemento, es decir, su conexión, enlace o encadenamiento. Los elementos de una lista son enlazados por medio de los campos enlaces.

Una lista enlazada sin ningún elemento se llama lista vacía. Su puntero inicial o de cabecera tiene el valor nulo, es decir apunta a NULL. *puntero NULL; Una lista enlazada se define por: El tipo de sus elementos: el campo de información donde se almacenan los

datos y el campo de enlace apunta al siguiente elemento lo define un puntero. Un puntero de cabecera que permite acceder al primer elemento de la lista. Un medio para detectar el último elemento de la lista: puntero nulo (NULL).

Page 100: 301305 Estructura de Datos

100

UNIVERSIDAD NACIONAL ABIERTA Y A DISTANCIA – UNAD ESCUELA DE CIENCIAS BÁSICAS TECNOLOGÍA E INGENIERÍA CONTENIDO DIDÁCTICO DEL CURSO: 301305 – ESTRUCTURA DE DATOS

Figura 37 Representación gráfica de listas enlazadas

En la figura 37. Se puede observar las diferentes representaciones graficas del último nodo de una lista enlazada. Operaciones con las listas enlazadas

Generalmente las operaciones básicas que se pueden realizar en una lista enlazada son las siguientes:

Operación de Recorrido. Esta operación consiste en visitar cada uno de los elementos que forman la lista. Para ello se comienza con el primer elemento, se toma el valor del campo enlace para avanzar al segundo elemento, el campo enlace de este elemento dará la dirección del tercer elemento y así sucesivamente hasta que la información del campo enlace sea NULL, lo que indica que el recorrido llegó a su final.

Operación de Inserción. Esta operación consiste en agregar un nuevo elemento a la lista. Se pueden considerar tres casos especiales: Insertar un elemento al inicio de la lista. Insertar un elemento antes o después de un determinado elemento o nodo de

la lista. Insertar un elemento al final de la lista.

Operación de Búsqueda. Esta operación consiste en visitar cada uno de los elementos, tomando al campo enlace como puntero al siguiente elemento a visitar en la lista. Operación de Borrado. La operación de borrado consiste en eliminar un elemento de la lista, considerando que se debe redefinir los enlaces involucrados en la operación. Se pueden presentar cuatro casos básicos:

Page 101: 301305 Estructura de Datos

101

UNIVERSIDAD NACIONAL ABIERTA Y A DISTANCIA – UNAD ESCUELA DE CIENCIAS BÁSICAS TECNOLOGÍA E INGENIERÍA CONTENIDO DIDÁCTICO DEL CURSO: 301305 – ESTRUCTURA DE DATOS

Eliminar el primer elemento de la lista. Eliminar el último elemento de la lista. Eliminar de la lista un elemento específico, es decir, que tenga cierta

información. Eliminar de la lista el elemento anterior o posterior al elemento que tiene cierta

información.

Implementación de una lista enlazada con punteros El siguiente programa se plantea como ejemplo guía para implementar una lista simplemente enlazada con punteros, para gestionar números enteros, ingresados por teclado con funciones de crear, insertar, eliminar, recorrer y buscar. Las eliminaciones y la búsqueda, se realizan en cualquier lugar de la lista. Progra27.cpp #include <iostream.h> #include <stdlib.h> #include <stdio.h> #include <conio.h> struct lista { int dato; struct lista *sig; }; void crear(struct lista **); void insertar(struct lista **, int); void eliminar(struct lista **, int); void recorrer(struct lista **); int buscar(struct lista **, int); int main() { clrscr(); struct lista *entero; int dato; crear(&entero);

Page 102: 301305 Estructura de Datos

102

UNIVERSIDAD NACIONAL ABIERTA Y A DISTANCIA – UNAD ESCUELA DE CIENCIAS BÁSICAS TECNOLOGÍA E INGENIERÍA CONTENIDO DIDÁCTICO DEL CURSO: 301305 – ESTRUCTURA DE DATOS

cout<<"OPERACIONES CON LA LISTA ENLAZADA\n\n "; cout<<"Para finalizar la insercion Ingrese el cero\n\n "; cout<<"Ingrese un numero: "; cin>>dato; while(dato != 0) { insertar(&entero, dato); cout<<"Ingrese un numero: "; cin>>dato; } cout<<"\n \n ELEMENTOS DE LA LISTA \n\n"; recorrer(&entero); cout<<"\n \n Ingrese el numero a eliminar: "; cin>>dato; eliminar(&entero, dato); recorrer(&entero); cout<<"\n \n Ingrese el numero a buscar: "; cin>>dato; if(buscar(&entero,dato) == 1) cout<<"\n El numero "<<dato<<" fue encontrado\n"; else cout<<"Enl numero no existe "<<endl; getchar(); return 0; } // funciones de listas simplemente enlazadas void crear(struct lista **entero) { *entero = NULL; } void insertar(struct lista **entero, int dato) { struct lista *auxiliar, *puntero, *anterior; auxiliar = new lista; if(!auxiliar) { cout<<"error:memoria insuficiente"<<endl; exit(1); }

Page 103: 301305 Estructura de Datos

103

UNIVERSIDAD NACIONAL ABIERTA Y A DISTANCIA – UNAD ESCUELA DE CIENCIAS BÁSICAS TECNOLOGÍA E INGENIERÍA CONTENIDO DIDÁCTICO DEL CURSO: 301305 – ESTRUCTURA DE DATOS

auxiliar->dato = dato; anterior = NULL; puntero = *entero; //puntero es el puntero auxiliar que recorre la lista while((puntero != NULL) && (puntero->dato < dato)) { anterior = puntero; puntero = puntero->sig; } if(anterior == NULL) { auxiliar->sig = *entero; *entero = auxiliar; } else { anterior->sig = auxiliar; auxiliar->sig = puntero; } } void eliminar(struct lista **entero, int dato) { struct lista *puntero, *anterior; puntero = *entero; anterior = NULL; while((puntero != NULL) && (puntero->dato < dato)) { anterior = puntero; puntero = puntero->sig; } if(puntero->dato != dato) cout<<"El numero no existe "<<endl; else { if(anterior == NULL) //1er lista *entero = (*entero)->sig; else

Page 104: 301305 Estructura de Datos

104

UNIVERSIDAD NACIONAL ABIERTA Y A DISTANCIA – UNAD ESCUELA DE CIENCIAS BÁSICAS TECNOLOGÍA E INGENIERÍA CONTENIDO DIDÁCTICO DEL CURSO: 301305 – ESTRUCTURA DE DATOS

anterior->sig = puntero->sig; delete puntero; } } void recorrer(struct lista **entero) { struct lista *puntero; puntero = *entero; while(puntero != NULL) { cout<<puntero->dato<< " "; puntero = puntero->sig; } } int buscar(struct lista **entero, int dato) { struct lista *puntero; puntero = *entero; while((puntero != NULL) && (puntero->dato < dato)) puntero = puntero->sig; if(puntero->dato == dato) return 1; else return 0; } El resultado de la salida en pantalla del listado anterior se puede observar en la siguiente figura 38. Analice el código y plantee modificaciones al programa, en busca de mejoras.

Page 105: 301305 Estructura de Datos

105

UNIVERSIDAD NACIONAL ABIERTA Y A DISTANCIA – UNAD ESCUELA DE CIENCIAS BÁSICAS TECNOLOGÍA E INGENIERÍA CONTENIDO DIDÁCTICO DEL CURSO: 301305 – ESTRUCTURA DE DATOS

Figura 38 Salida en pantalla de Progra27.cpp

Lección 13: Más a cerca de listas enlazadas

En la implementación de las listas enlazadas se pueden encontrar muchas formas de representación, dependiendo de los recursos que se tengan relacionados con el dominio del lenguaje C++. Una forma más sencilla de representar una lista enlazada de números enteros se presenta en el listado llamado progra28.cpp en donde los datos ya están predefinidos.

Progra28.cpp #include <conio.h> #include <iostream.h> #include <stdlib.h> struct lista { int nuevo; struct lista *sig; }; int main() { clrscr(); struct lista *L;

Page 106: 301305 Estructura de Datos

106

UNIVERSIDAD NACIONAL ABIERTA Y A DISTANCIA – UNAD ESCUELA DE CIENCIAS BÁSICAS TECNOLOGÍA E INGENIERÍA CONTENIDO DIDÁCTICO DEL CURSO: 301305 – ESTRUCTURA DE DATOS

struct lista *P; int i; L=NULL; cout<<"RESULTADO DE LA LISTA\n\n"; for(i=1;i<=6;i++) { cout <<i <<"-"; P=(struct lista *)malloc(sizeof(struct lista)); //Reserva memoria para el nodo P-> nuevo=3; //Introduce la informaci¢n P->sig=L; //Reorganiza L=P; //los enlaces } cout <<P->nuevo <<"\n\n"; cout << "Donde " <<P->nuevo <<" es el Nuevo nodo insertado al final "; free (P); getch(); return 0; } El resultado de la salida en pantalla de progra28.cpp se visualiza en la figura 40, que se muestra continuación. Figura 39 Salida en pantalla de progra28.cpp

Análisis de Progra28.cpp

Al analizar un poco el código de progra28.cpp se tiene definida una estructura llamada lista, que tiene como miembros a un puntero llamado *nuevo y a *sig que es el enlace al siguiente elemento de la lista y es del tipo de la estructura, al igual que los punteros *L y *P, utilizados para gestionar la lista. Se define la variable i que es de tipo entero utilizada para el recorrido del ciclo for. El cual está predefinido para que repita el proceso de insertar elementos 5 veces al estar definido así: for(i=1;i<=6;i++).

Page 107: 301305 Estructura de Datos

107

UNIVERSIDAD NACIONAL ABIERTA Y A DISTANCIA – UNAD ESCUELA DE CIENCIAS BÁSICAS TECNOLOGÍA E INGENIERÍA CONTENIDO DIDÁCTICO DEL CURSO: 301305 – ESTRUCTURA DE DATOS

El puntero P es utilizado para la reserva de memoria que se hace por medio de Malloc(), lo que indica que P guardará los elementos que se inserten a la lista, pero se requiere otro puntero que recorra la lista y esa labor la hace L. Siguiendo algorítmicamente las instrucciones del programa se tiene que se almacena un nuevo dato que es el número 3 y que este se guarda en el apuntador P tal como lo indica la instrucción p->nuevo=3. Con la instrucción P->sig=L; se hace que p apunte al siguiente elemento de lista posteriormente se reorganizan los enlaces en la instrucción L=P. Finalmente se imprime los datos de ciclo for almacenados en la variable, es decir los números del 1 al 5, seguido del valor almacenado en P para el cual se reservó memoria que se libera antes de finalizar el programa. Continuando con la implementación de las listas enlazadas, vale la pena analizar el siguiente código de progra29.cpp, implementado con punteros que crea una lista enlazada de 6 números enteros ingresados por teclado en tiempo de ejecución, imprime todos sus elementos y adicionalmente arroja la sumatoria de los elementos de la lista. Progra29.cpp

#include <stdlib.h> #include <iostream.h> #include <conio.h> struct nodo { int dato; struct nodo *sig; }*l=NULL,*primero=NULL; int main() { clrscr(); int acumulador=0; int i=0, vector[6]; cout<<"IMPLEMENTACION DE UNA LISTA ENLAZADA\n\n"; cout<<"Ingrese 6 numeros\n"; for(i;i<6;i++) { cin>> vector[i]; acumulador = acumulador + vector[i];

Page 108: 301305 Estructura de Datos

108

UNIVERSIDAD NACIONAL ABIERTA Y A DISTANCIA – UNAD ESCUELA DE CIENCIAS BÁSICAS TECNOLOGÍA E INGENIERÍA CONTENIDO DIDÁCTICO DEL CURSO: 301305 – ESTRUCTURA DE DATOS

} for(i;i<6;i++) { primero=(struct nodo *)malloc(sizeof(struct nodo)); primero->dato=vector[i-1]; primero->sig = l; l = primero; } cout<<"\nLista creada. Preseione una tecla "; getch(); cout<<"\nLa sumatoria de la lista es : " <<acumulador; cout<<" \n"; while(l!=NULL) { cout<< l->dato; l=l->sig; } free(primero); getch(); return 0; } El resultado después de haber compilado y depurado el código es el que se visualiza en la figura 40,

Figura 40 Salida en pantalla de progra29.cpp

Page 109: 301305 Estructura de Datos

109

UNIVERSIDAD NACIONAL ABIERTA Y A DISTANCIA – UNAD ESCUELA DE CIENCIAS BÁSICAS TECNOLOGÍA E INGENIERÍA CONTENIDO DIDÁCTICO DEL CURSO: 301305 – ESTRUCTURA DE DATOS

Lección 14: Listas doblemente enlazadas Las listas doblemente enlazadas son un tipo de lista lineal en la que cada nodo tiene dos enlaces, uno que apunta al nodo siguiente, y el otro que apunta al nodo anterior. Las listas doblemente enlazadas no necesitan un nodo especifico para acceder a ellas, ya que presentan una gran ventaja comparada con las listas enlazadas y es que pueden recorrerse en ambos sentidos a partir de cualquier nodo de la lista, ya que siempre es posible desde cualquier nodo alcanzar cualquier otro nodo de la lista, hasta que se llega a uno de los extremos. La creación de las listas doblemente enlazadas se hace de igual manera que con las listas enlazadas, es decir a través de una estructura, la diferencia radica en que para esta tipo de lista doble se requiere otro enlace que apunte al nodo anterior. He aquí la definición de la estructura llamada ListaDoble.

struct ListaDoble { int dato; struct nodo *siguiente; struct nodo *anterior; }; Representación gráfica de una lista doblemente enlazada Una forma gráfica de representar una lista doblemente enlazada se puede visualizar en la figura 41, que se muestra a continuación.

Figura 41 Representación gráfica de una lista doblemente enlazada

El movimiento a través de listas doblemente enlazadas es más flexible, ya que como se verá en esta lección las operaciones de búsqueda, inserción y

Page 110: 301305 Estructura de Datos

110

UNIVERSIDAD NACIONAL ABIERTA Y A DISTANCIA – UNAD ESCUELA DE CIENCIAS BÁSICAS TECNOLOGÍA E INGENIERÍA CONTENIDO DIDÁCTICO DEL CURSO: 301305 – ESTRUCTURA DE DATOS

borrado, también tienen algunas ventajas significativas frente a las listas enlazada”.5

Operaciones básicas con listas doblemente enlazadas Nuevamente se tienen las mismas operaciones sobre este tipo listas:

Añadir o insertar elementos. Puede llevarse a cabo en cualquier lugar de la lista.

Buscar o localizar elementos. Dada una característica especial. Borrar elementos. Permite elegir el elemento a eliminar. Moverse a través de la lista, siguiente y anterior.

Se intentará analizar algunos casos posibles de inserción, eliminación y visualización de elementos en listas doblemente enlazadas. Para ampliar este tema puede consultar la siguiente dirección web: http://ldcastillo.wordpress.com/tema-2-listas-doblemente-enlazadas/ Implementación de una lista doblemente enlazada En el siguiente listado se presenta el código completo de progra30.cpp, el cual crea una lista doblemente enlazada con punteros donde se incluye un menú de opciones para su interacción, adicionalmente presenta funciones para crear la lista del registro de personas, visualiza la lista, elimina un registro y busca un registro dentro de la lista. Progra30.cpp #include <conio.h> #include <stdio.h> #include <stdlib.h> #include <string.h> #include <iostream.h> struct direc { char nombre[30]; char ciudad[20]; char codigo[10]; struct direc *sig; //PUNTERO A LA SIGUIENTE ENTRADA 5 Tomado de: http://ldcastillo.wordpress.com/tema-2-listas-doblemente-enlazadas/

Page 111: 301305 Estructura de Datos

111

UNIVERSIDAD NACIONAL ABIERTA Y A DISTANCIA – UNAD ESCUELA DE CIENCIAS BÁSICAS TECNOLOGÍA E INGENIERÍA CONTENIDO DIDÁCTICO DEL CURSO: 301305 – ESTRUCTURA DE DATOS

struct direc *ant; //PUNTERO AL REGISTRO ANTERIOR }; struct direc *ppio; //PUNTERO A LA PRIMERA ENTRADA ALA LISTA struct direc *final; //PUNTERO ALA ULTIMA ENTRADA struct direc *buscar(char *); void intro(void); void buscar(void); void listar(void); void eliminar(struct direc **, struct direc **); void dl_insert(struct direc *i, struct direc **ppio, struct direc **final); void leecad(char *, char *, int), mostrar(struct direc *); int menu(void); int main(void) { clrscr(); ppio = final = NULL; //INICIALIZA LOS PUNTEROS for(;;) { switch(menu()) { case 1: intro(); //INTRODUCIR UNA DIRECCION break; case 2: eliminar(&ppio, &final); //ELIMINA UNA DIRECCION break; case 3: listar();//MOSTRAR LA LISTA break; case 4: buscar();//ENCONTRAR UNA DIRECCION break; case 5: exit(0); } } } //selecionar una operacion int menu(void) {

Page 112: 301305 Estructura de Datos

112

UNIVERSIDAD NACIONAL ABIERTA Y A DISTANCIA – UNAD ESCUELA DE CIENCIAS BÁSICAS TECNOLOGÍA E INGENIERÍA CONTENIDO DIDÁCTICO DEL CURSO: 301305 – ESTRUCTURA DE DATOS

char s[80]; int c; cout<<"\nLISTA DOBLEMENTE ENLAZADA\n\n"; cout<<"1. Introducir una direccion" <<endl; cout<<"2. Eliminar una direcci¢n" <<endl; cout<<"3. Listar el archivo" <<endl; cout<<"4. Buscar" <<endl; cout<<"5. Salir" <<endl; do { cout<<"\nIntroduce una opcion: "; gets(s); c = atoi(s); }while(c<0 || c>5); clrscr(); return c; } //Introducir nombres y direcciones void intro(void) { struct direc *info; for(;;) { info = (struct direc *)malloc(sizeof(struct direc)); if(!info) { cout<<endl <<"no hay memoria"; return; } leecad("\nIntroduce el nombre: ", info->nombre, 30); if(!info->nombre[0]) break; //parar el proceso leecad("Introduce la ciudad: ", info->ciudad, 20); leecad("Introduce el codigo: ", info->codigo, 10); dl_insert(info, &ppio, &final); } clrscr(); }

Page 113: 301305 Estructura de Datos

113

UNIVERSIDAD NACIONAL ABIERTA Y A DISTANCIA – UNAD ESCUELA DE CIENCIAS BÁSICAS TECNOLOGÍA E INGENIERÍA CONTENIDO DIDÁCTICO DEL CURSO: 301305 – ESTRUCTURA DE DATOS

/* Esta funcion lee una cadena de longitud maxima cont y previene el desbordamiento de la cadena. tambien visualiza un mensaje indicativo */ void leecad(char *indic, char *s, int cont) { char p[255]; do { printf(indic); fgets(p, 254, stdin); }while(strlen(p) > cont); p[strlen(p)-1] = 0; //Eliminar el salto de linea strcpy(s, p); } // crear una lista doblemente enlazada void dl_insert( struct direc *i, //nuevo elemento struct direc **ppio, //primer elemento de la lista struct direc **final //ultimo elemento de la lista ) { struct direc *ant, *p; if(*final == NULL) //primer elemento de la lista { i->sig = NULL; i->ant = NULL; *final = i; *ppio = i; return; } p = *ppio; //principio de la lista ant = NULL; while(p) { if(strcmp(p->nombre, i->nombre) <0) {

Page 114: 301305 Estructura de Datos

114

UNIVERSIDAD NACIONAL ABIERTA Y A DISTANCIA – UNAD ESCUELA DE CIENCIAS BÁSICAS TECNOLOGÍA E INGENIERÍA CONTENIDO DIDÁCTICO DEL CURSO: 301305 – ESTRUCTURA DE DATOS

ant = p; p = p->sig; } else { if(p->ant) { p->ant->sig = i; i->sig = p; i->ant = p->ant; p->ant = i; *ppio = i; return; } i->sig = p; //nuevo primer elemento i->ant = NULL; p->ant = i; *ppio = i; return; } } ant->sig = i; //ponerlo en el final i->sig = NULL; i->ant = ant; *final = i; } //eliminar un elemento de la lista void eliminar(struct direc **ppio, struct direc **final) { struct direc *info; char s[80]; leecad("Introduce el nombre: ", s, 30); info = buscar(s); if(info) { if(*ppio==info) { *ppio=info->sig; if(*ppio) (*ppio)->ant =NULL; else *final = NULL; } else

Page 115: 301305 Estructura de Datos

115

UNIVERSIDAD NACIONAL ABIERTA Y A DISTANCIA – UNAD ESCUELA DE CIENCIAS BÁSICAS TECNOLOGÍA E INGENIERÍA CONTENIDO DIDÁCTICO DEL CURSO: 301305 – ESTRUCTURA DE DATOS

{ info->ant->sig = info->sig; if(info != *final) info->sig->ant = info->ant; else *final = info->ant; } free(info); //devolver la memoria al sistema } clrscr(); } //buscar una direccion struct direc *buscar(char *nombre) { struct direc *info; info = ppio; while(info) { if(!strcmp(nombre, info->nombre)) return info; info = info->sig; //obtener siguiente direccion } cout<<"nombre no encontrado" <<endl; return NULL; //no encontrado } //mostrar la lista entera void listar(void) { struct direc *info; info = ppio; while(info) { mostrar(info); info = info->sig; //obtener la siguiente direccion }

Page 116: 301305 Estructura de Datos

116

UNIVERSIDAD NACIONAL ABIERTA Y A DISTANCIA – UNAD ESCUELA DE CIENCIAS BÁSICAS TECNOLOGÍA E INGENIERÍA CONTENIDO DIDÁCTICO DEL CURSO: 301305 – ESTRUCTURA DE DATOS

cout<<endl <<endl; } // esta funcion imprime realmente los campos de cada direccion void mostrar(struct direc *info) { cout<<info->nombre<<"-"; cout<<info->ciudad<<"-"; cout<<info->codigo<<"-"; cout<<endl <<endl; } //buscar un nombre en la lista void buscar(void) { char nombre[40]; struct direc *info; cout<<"Introduce el nombre a encontrar: "; gets(nombre); info = buscar(nombre); if(!info) cout<<"no encontrado"; else mostrar(info); getch(); clrscr(); }

La salida en pantalla de progra30.cpp como implementación de una lista doblemente enlazada se puede visualizar en la figura 42 que se muestra a continuación.

Page 117: 301305 Estructura de Datos

117

UNIVERSIDAD NACIONAL ABIERTA Y A DISTANCIA – UNAD ESCUELA DE CIENCIAS BÁSICAS TECNOLOGÍA E INGENIERÍA CONTENIDO DIDÁCTICO DEL CURSO: 301305 – ESTRUCTURA DE DATOS

Figura 42 Salida en pantalla de progra30.cpp

Lección 15: Listas circulares Las listas enlazadas no permiten a partir de un elemento acceder directamente a cualquiera de los elementos que le preceden. En cambio la lista enlazada circular o lista circular (también llamada listas en anillo), en lugar de almacenar un punto NULO en el campo SIG del último elemento de la lista, se hace que el último elemento apunte al primero o principio de la lista. Las listas circulares presentan las siguientes ventajas respecto de las listas enlazadas simples: Cada nodo de una lista circular es accesible desde cualquier otro nodo de ella.

Es decir, dado un nodo se puede recorrer toda la lista completa. En una lista enlazada de forma simple sólo es posible recorrerla por completo si se parte de su primer nodo.

Las operaciones de concatenación o unión y división de listas son más eficaces con listas circulares.

Pero también se presentan algunos inconvenientes que vale la pena mencionar. Se pueden producir lazos o bucles infinitos. Una forma de evitar estos bucles

infinitos es disponer de un nodo especial que se encuentre permanentemente asociado a la existencia de la lista circular. Este nodo se denomina cabecera de la lista.

Page 118: 301305 Estructura de Datos

118

UNIVERSIDAD NACIONAL ABIERTA Y A DISTANCIA – UNAD ESCUELA DE CIENCIAS BÁSICAS TECNOLOGÍA E INGENIERÍA CONTENIDO DIDÁCTICO DEL CURSO: 301305 – ESTRUCTURA DE DATOS

Figura 43 Representación gráfica de una Lista Circular

El nodo cabecera puede diferenciarse de otros nodos en una de las dos formas siguientes: Puede tener un valor especial en su campo INFO que no es válido como datos

de otros elementos. Puede tener un indicador o bandera que señale cuándo es nodo cabecera. El campo de la información del nodo cabecera no se utiliza, lo que se señala con el sombreado de dicho campo.

En una lista circular se puede considerar las siguientes situaciones:

No existe elemento alguno que apunte a NULL es decir que el último elemento apunta a la cabeza o al inicio de la lista. De igual manera se integra como una estructura tipo anillo. Solo se evidencia un nodo cabecera, La cabecera siempre apuntará al siguiente enlace para algún nodo y es susceptible de crear ciclos o bucles infinitos.

En una estructura tipo Circular no existe algún elemento que apunte a NULL, se presenta entonces la dificultad para conocer el último elemento. Sin embargo podría considerarse que como el último nodo será aquel que en su parte siguiente apunta a la cabeza y precisamente en un método de búsqueda la comparación con el nodo cabeza será la que indique que no existen más elementos en la lista.

Se pueden identificar dos tipos de lista circulares:

Listas Circulares Simplemente Enlazadas Listas Circulares Doblemente Enlazadas

Una representación gráfica sería tal como se visualiza en la figura 44 y 45.

Page 119: 301305 Estructura de Datos

119

UNIVERSIDAD NACIONAL ABIERTA Y A DISTANCIA – UNAD ESCUELA DE CIENCIAS BÁSICAS TECNOLOGÍA E INGENIERÍA CONTENIDO DIDÁCTICO DEL CURSO: 301305 – ESTRUCTURA DE DATOS

Figura 44 Lista circular simplemente enlazada

Figura 45 Lista circular doblemente enlazada

Una lista enlazada circularmente vacía se representa como se muestra LISTA ---------- NULL

Añadir elemento en una lista circular vacía Partiremos de que ya tenemos el nodo A para insertar y por supuesto un puntero que apunte a él, además el puntero que define la lista, que valdrá NULL:

Page 120: 301305 Estructura de Datos

120

UNIVERSIDAD NACIONAL ABIERTA Y A DISTANCIA – UNAD ESCUELA DE CIENCIAS BÁSICAS TECNOLOGÍA E INGENIERÍA CONTENIDO DIDÁCTICO DEL CURSO: 301305 – ESTRUCTURA DE DATOS

Figura 46 Primer nodo de la lista circular

El proceso es muy simple, bastará con que: 1. lista apunta a nodo. 2. lista->siguiente apunte a nodo.

Añadir elemento en una lista circular no vacía De nuevo partiremos de un nodo a insertar, con un puntero que apunte a él, y de una lista, en este caso, el puntero no será nulo:

Figura 47 Inserción del segundo nodo

El proceso sigue siendo muy sencillo: 1. Hacemos que nodo->siguiente apunte a lista->siguiente. 2. Después que lista->siguiente apunte a nodo.

Page 121: 301305 Estructura de Datos

121

UNIVERSIDAD NACIONAL ABIERTA Y A DISTANCIA – UNAD ESCUELA DE CIENCIAS BÁSICAS TECNOLOGÍA E INGENIERÍA CONTENIDO DIDÁCTICO DEL CURSO: 301305 – ESTRUCTURA DE DATOS

Figura 48 Nuevo nodo insertado en la lista circular

Añadir elemento en una lista circular caso general Para generalizar los dos casos anteriores, sólo necesitamos añadir una operación: 1. Si lista está vacía hacemos que lista apunte a nodo. 2. Si lista no está vacía, hacemos que: nodo->siguiente apunte a lista->siguiente.

3. Después que lista->siguiente apunte a nodo.

“La implementación de las listas circulares se puede apreciar en el siguiente listado llamado progra31.cpp.

Progra31.cpp #include <stdio.h> #include <stdlib.h> typedef struct _nodo { int valor; struct _nodo *siguiente; } tipoNodo; typedef tipoNodo *pNodo; typedef tipoNodo *Lista; // Funciones con listas: void Insertar(Lista *l, int v); void Borrar(Lista *l, int v); void BorrarLista(Lista *); void MostrarLista(Lista l); int main() { Lista lista = NULL; pNodo p;

Page 122: 301305 Estructura de Datos

122

UNIVERSIDAD NACIONAL ABIERTA Y A DISTANCIA – UNAD ESCUELA DE CIENCIAS BÁSICAS TECNOLOGÍA E INGENIERÍA CONTENIDO DIDÁCTICO DEL CURSO: 301305 – ESTRUCTURA DE DATOS

Insertar(&lista, 10); Insertar(&lista, 40); Insertar(&lista, 30); Insertar(&lista, 20); Insertar(&lista, 50); MostrarLista(lista); Borrar(&lista, 30); Borrar(&lista, 50); MostrarLista(lista); BorrarLista(&lista); getchar(); return 0; } void Insertar(Lista *lista, int v) { pNodo nodo; // Creamos un nodo para el nuvo valor a insertar nodo = (pNodo)malloc(sizeof(tipoNodo)); nodo->valor = v; // Si la lista está vacía, la lista será el nuevo nodo // Si no lo está, insertamos el nuevo nodo a continuación del apuntado // por lista if(*lista == NULL) *lista = nodo; else nodo->siguiente = (*lista)->siguiente; // En cualquier caso, cerramos la lista circular (*lista)->siguiente = nodo; } void Borrar(Lista *lista, int v) { pNodo nodo; nodo = *lista; // Hacer que lista apunte al nodo anterior al de valor v do { if((*lista)->siguiente->valor != v) *lista = (*lista)->siguiente; } while((*lista)->siguiente->valor != v && *lista != nodo); // Si existe un nodo con el valor v: if((*lista)->siguiente->valor == v) {

Page 123: 301305 Estructura de Datos

123

UNIVERSIDAD NACIONAL ABIERTA Y A DISTANCIA – UNAD ESCUELA DE CIENCIAS BÁSICAS TECNOLOGÍA E INGENIERÍA CONTENIDO DIDÁCTICO DEL CURSO: 301305 – ESTRUCTURA DE DATOS

// Y si la lista sólo tiene un nodo if(*lista == (*lista)->siguiente) { // Borrar toda la lista free(*lista); *lista = NULL; } else { // Si la lista tiene más de un nodo, borrar el nodo de valor v nodo = (*lista)->siguiente; (*lista)->siguiente = nodo->siguiente; free(nodo); } } } void BorrarLista(Lista *lista) { pNodo nodo; // Mientras la lista tenga más de un nodo while((*lista)->siguiente != *lista) { // Borrar el nodo siguiente al apuntado por lista nodo = (*lista)->siguiente; (*lista)->siguiente = nodo->siguiente; free(nodo); } // Y borrar el último nodo free(*lista); *lista = NULL; } void MostrarLista(Lista lista) { pNodo nodo = lista; do { printf("%d -> ", nodo->valor); nodo = nodo->siguiente; } while(nodo != lista); printf("\n"); }

//Fin del programa”6

6 Tomado de: http://www.conclase.net/c/edd/index.php?cap=004c

Page 124: 301305 Estructura de Datos

124

UNIVERSIDAD NACIONAL ABIERTA Y A DISTANCIA – UNAD ESCUELA DE CIENCIAS BÁSICAS TECNOLOGÍA E INGENIERÍA CONTENIDO DIDÁCTICO DEL CURSO: 301305 – ESTRUCTURA DE DATOS

El resultado en pantalla se puede visualizar en la figura 49.

Figura 49 Salida en pantalla de progra31.cpp

Page 125: 301305 Estructura de Datos

125

UNIVERSIDAD NACIONAL ABIERTA Y A DISTANCIA – UNAD ESCUELA DE CIENCIAS BÁSICAS TECNOLOGÍA E INGENIERÍA CONTENIDO DIDÁCTICO DEL CURSO: 301305 – ESTRUCTURA DE DATOS

Actividades de Autoevaluación de la Unidad 2

Ejercicio1. Declarar funciones para realizar las siguientes operaciones desarrolladas con las estructuras de datos tipo pilas:

Una función que calcule el número de elementos de una pila p.

Una función que elimine los últimos n elementos apilados en una pila p si los hay.

Una función que imprima la inversa de una pila p, es decir que el último dato ingresado sea el primero en la lista de impresión.

Una función llamada fondo que calcule el elemento del fondo de una pila p. es decir el primer elemento insertado.

Ejercicio 2. Implemente una pila usando memoria dinámica con listas enlazadas. Para realizar operaciones de push y pop. Ejercicio 3. Implemente un programa para gestionar la entrega de regalos a los niños que fueron invitados a la fiesta. Los regalos se entregarán teniendo en cuenta el orden de llegada, el primero que llegue será el primero en recibir su regalo, es importante conocer el nombre y la edad de los niños que recibieron regalos.

Ejercicio 4. Implementar funciones para una estructura tipo colas así: Una función que calcule el último elemento de una cola. Una función que imprima la inversa de una cola es decir que visualice en

pantalla los datos en orden inverso en que fueron ingresados. Una Función que intercale los elementos de dos colas.

Ejercicio 5. Una cola medieval se comporta como una cola ordinaria, con la única diferencia de que los elementos almacenados en ella se dividen en dos estamentos: nobles y plebeyos. Dentro de cada estamento, los elementos deben ser atendidos en orden de llegada; pero siempre que haya nobles en la cola, éstos deben ser atendidos antes que los plebeyos. Se pide: Implementar las colas medievales utilizando memoria dinámica para. añadir un elemento nuevo a una cola consultar el primer elemento de una cola

Page 126: 301305 Estructura de Datos

126

UNIVERSIDAD NACIONAL ABIERTA Y A DISTANCIA – UNAD ESCUELA DE CIENCIAS BÁSICAS TECNOLOGÍA E INGENIERÍA CONTENIDO DIDÁCTICO DEL CURSO: 301305 – ESTRUCTURA DE DATOS

quitar el primer elemento de una cola consultar el número de nobles en una cola, consultar el número de plebeyos en una cola,

Ejercicio 6. Implemente una lista lineal de datos de tipo numérico, con opciones de ordenar la lista en los dos sentidos, ascendente y descendente, e imprima el resultado.

Ejercicio 7. Escribir un programa para el mantenimiento de notas de un grupo de alumnos usando listas. Se debe registrar el nombre del alumno y la respectiva nota y calcular el promedio del grupo, la estructura a implementar es la siguiente. struct nodo { int nota; char nombre[15]; struct nodo *siguiente; } cabeza;

Ejercicio 8. Desarrolle un programa para buscar un elemento en la lista (de números enteros) y borrar todas las ocurrencias de cada elemento encontrado use un menú de opciones.

Page 127: 301305 Estructura de Datos

127

UNIVERSIDAD NACIONAL ABIERTA Y A DISTANCIA – UNAD ESCUELA DE CIENCIAS BÁSICAS TECNOLOGÍA E INGENIERÍA CONTENIDO DIDÁCTICO DEL CURSO: 301305 – ESTRUCTURA DE DATOS

Fuentes Documentales de la Unidad 2 AGUILAR, Luis (2003). Fundamentos de programación, algoritmos, estructura de datos y Objetos, Tercera edición. España: McGRAW-HILL. AGUILAR, Luis (200). Programación en C++, Algoritmos, estructura de datos y Objetos. España: McGRAW-HILL. AGUILAR, Luis (2003). Fundamentos de programación, algoritmos, estructura de datos y Objetos Tercera edición. España: McGRAW-HILL. AGUILAR Luis, ZAHONERO Martínez (2004). Algoritmos y Estructuras de Datos. Una perspectiva en C. Madrid-España: McGraw-Hill. BROOKSHEAR, J. Glenn (1995). Introducción a las ciencias de la Computación. Cuarta Edicón. Edición Española: Addison-Wesley Iberoamericana. DEYTEL Y DEYTEL(1999). Como programa C++. Segunda Edición. Mexico D.F: Prentice Hall. McGRAW-HILL. FARREL, Joyce (2000). Introducción a la programación lógica y diseño. Mexico D.F: Thomson. KENNETH C, Louden (2004). Lenguajes de programación. Segunda edición. MexicoD.F: Thomson. Salvador, Pozo (2001). Estructuras dinámicas de datos- Listas circulares. Consultado en Octubre de 2008 en http://c.conclase.net/edd/index.php?cap=004. Salvador, Pozo (2001). Estructuras dinámicas de datos- Colas. Consultado en Octubre de 2008 en http://c.conclase.net/edd/index.php?cap=003. MENDEZ, Justo (2004). Las tendencias en los lenguajes de programación. Consultado en Noviembre de 2008 en http://www.ilustrados.com/publicaciones/EpZVVEZpyEdFpAKxjH.php. CACERES, Abdiel (2005). Estructuras de datos en C++. Consultado en Febrero 25 de 2009 en http://computacion.cs.cinvestav.mx/~acaceres/courses/estDatosCPP/

CASTILLO, Lenin (2007). Listas doblemente enlazadas. Consultado en Mayo 2 de 2009 en http://ldcastillo.wordpress.com/tema-2-listas-doblemente-enlazadas/.

Page 128: 301305 Estructura de Datos

128

UNIVERSIDAD NACIONAL ABIERTA Y A DISTANCIA – UNAD ESCUELA DE CIENCIAS BÁSICAS TECNOLOGÍA E INGENIERÍA CONTENIDO DIDÁCTICO DEL CURSO: 301305 – ESTRUCTURA DE DATOS

TEJADA, Hector (2005). Asignación dinámica de Memoria y estructuras dinámicas. Consultado en Octubre 23 de 2008 en http://www.fismat.umich.mx/mn1/manual/node10.html. RIOFRIO, Guido (2008). Estructura de datos y algoritmos. Consultado en Septiembre 10 de 2008 en http://www.youtube.com/watch?v=ohb9bjPX7Vw. SOTO, Lauro (2005). Manejo de Memoria. Consultado en Junio 23 de 2009 en http://www.programacionfacil.com/estructura_de_datos/start. Universidad de Huelva. Departamento de Tecnologías de la Información (DTI) (2008). TAD Lineales. Consultado en Junio 23 de 2009 en http://www.uhu.es/17207-18209/Transparencias/Tema3.pdf.

Page 129: 301305 Estructura de Datos

129

UNIVERSIDAD NACIONAL ABIERTA Y A DISTANCIA – UNAD ESCUELA DE CIENCIAS BÁSICAS TECNOLOGÍA E INGENIERÍA CONTENIDO DIDÁCTICO DEL CURSO: 301305 – ESTRUCTURA DE DATOS

UNIDAD 3

Nombre de la Unidad ESTRUCTURAS DE DATOS NO LINEALES

Introducción

Con el contenido de esta unidad se pretende dar un acercamiento a la programación orientada a objetos, considerando que en adelante será una constante para abordar el siguiente curso de programación orientada a objetos. Se profundiza en la aplicación que puede darse a la temática relacionada con los tres capítulos que integran la Unidad con la temática de la teoría general de árboles, árboles binarios y finalizar con la teoría de grafos, respectivamente. En el capítulo 7, de la Unidad se aborda el tema del modo gráfico de C++, en cuanto a la configuración del compilar y algunas pautas para el inicio. Es importante resaltar que en esta unidad se hace una recopilación de información desarrollada por varios autores que se relacionan en la bibliografía, con el propósito de ampliar la temática y brindar al estudiante mayor soporte conceptual. Al final de la unidad, se plantean una serie de actividades que buscan determinar el grado de apropiación del conocimiento, basados en los tres momentos: Reconocimiento, Profundización y transferencia, que en su conjunto garantizan el aprendizaje y por ende la adquisición de la competencia esperada en el curso.

Justificación

Los árboles son, sin duda, una de las estructuras de datos no lineales, empleadas en informática, tanto para resolver problemas de hardware como de software. Los árboles de directorios son organizaciones bastante empleadas por cualquier usuario o programador de una computadora. De igual manera cumplen un buen papel en la toma de decisiones, valido como árbol de decisiones. Los árboles genealógicos y los organigramas son

Page 130: 301305 Estructura de Datos

130

UNIVERSIDAD NACIONAL ABIERTA Y A DISTANCIA – UNAD ESCUELA DE CIENCIAS BÁSICAS TECNOLOGÍA E INGENIERÍA CONTENIDO DIDÁCTICO DEL CURSO: 301305 – ESTRUCTURA DE DATOS

ejemplos comunes. Entre otras aplicaciones, los árboles se emplean para analizar circuitos eléctricos y para representar la estructura de fórmulas matemáticas, así como para organizar la información de bases de datos, para representar la estructura sintáctica de un programa fuente en compiladores y para la toma de decisiones.

Intencionalidades Formativas

Profundizar en la conceptualización y la aplicabilidad de la teoría general de árboles, árboles binarios y gafos en la programación estructurada.

Inducir al estudiante los aspectos fundamentales y principios básicos necesarios para abordar la programación orientada a objetos iniciando con la programación en modo gráfico de C++. Identificar plenamente la forma de recorrer árboles binarios de búsqueda. Identificar las operaciones que se pueden realizar con árboles binarios. Conceptualizar en la forma de recorrer los grafos y su aplicabilidad en entornos reales.

Capítulo 1 ÁRBOLES Lección 1 Teoría general de árboles Lección 2 Otros conceptos de la teoría general de árboles Lección 3 Árbol completo Lección 4 Estructura para la creación de un árbol de orden tres Lección 5 Introducción al Modo Gráfico de C++ Capítulo 2 ÁRBOLES BINARIOS Lección 6 Conceptualización de árboles binarios Lección 7 Clasificación de los árboles binarios Lección 8 Formas de Recorrer un Árbol Binario Lección 9 Ábol binario de búsqueda (ABB) Lección 10 Operaciones en ABB Capítulo 3 GRAFOS Lección 11 Conceptos básicos de grafos Lección 12 Grafo no dirigido Lección 13 Representación de los grafos Lección 14 Representación mediante listas de Adyacencia Lección 15 Exploración de grafos

Page 131: 301305 Estructura de Datos

131

UNIVERSIDAD NACIONAL ABIERTA Y A DISTANCIA – UNAD ESCUELA DE CIENCIAS BÁSICAS TECNOLOGÍA E INGENIERÍA CONTENIDO DIDÁCTICO DEL CURSO: 301305 – ESTRUCTURA DE DATOS

CAPITULO 7: ÁRBOLES

Introducción

Los árboles a diferencia de las listas son una estructura de datos de no lineal, atendiendo más a una estructura de tipo jerárquico. Se abordan los temas relacionados con los conceptos básicos de árboles, incluyendo la teoría general de árboles e identificando los diferentes tipos de árboles. Se presenta un apartado ampliamente desarrollado a cerca del módo gráfico de C++, donde se ilustra a través de imágenes la configuración del editor, las librerías gráficas y el directorio donde se encuentra la interfaz grafica es decir BGI. Finalizando con un programa de aplicación del modo gráfico que muestra figuras geométricas y texto manejando colores y rellenos.

Lección 1: Teoría general de Árboles Los árboles son, sin duda, una de las estructuras de datos no lineales, empleadas en informática, tanto para resolver problemas de hardware como de software. Los árboles de directorios son organizaciones bastante empleadas por cualquier usuario o programador de una computadora. De igual manera cumplen un buen papel en la toma de decisiones, valido como árbol de decisiones. Los árboles genealógicos y los organigramas son ejemplos comunes. Entre otras aplicaciones, los árboles se emplean para analizar circuitos eléctricos y para representar la estructura de fórmulas matemáticas, así como para organizar la información de bases de datos, para representar la estructura sintáctica de un programa fuente en compiladores y para la toma de decisiones.

Después de haber conceptualizado la segunda unidad y haber realizado la implementación de los programas de aplicación con Arreglos y Apuntadores, se presenta otra alternativa para la aplicación y conceptualización de los árboles se recomienda que se realice por medio del entorno gráfico que hace parte del compilador de C++, de esta manera se logra un acercamiento a la programación orientada a objetos.

Page 132: 301305 Estructura de Datos

132

UNIVERSIDAD NACIONAL ABIERTA Y A DISTANCIA – UNAD ESCUELA DE CIENCIAS BÁSICAS TECNOLOGÍA E INGENIERÍA CONTENIDO DIDÁCTICO DEL CURSO: 301305 – ESTRUCTURA DE DATOS

Definición de árboles Los árboles son estructuras de datos muy similares a las listas doblemente enlazadas, en el sentido que tienen punteros que apuntan a otros elementos, pero no tienen una estructura lógica de tipo lineal o secuencial como aquellas, sino ramificada. Tienen aspecto de árbol, de ahí su nombre. Su estudio desde el punto de vista matemático pertenece a la teoría de grafos; desde el punto de vista informático son estructuras de datos, lo que significa que cada elemento, denominado nodo u hoja, contiene un valor. Su estudio corresponde a la teoría de bases de datos, y en esta terminología, los nodos que dependen de otros se denominan hijos. Cada hoja puede tener un máximo de hijos, si no tiene ninguno se dice que es un nodo terminal.

Un árbol es una estructura de datos 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 compuesta por un dato y varios árboles. Esto son definiciones simples. Una representación gráfica de los árboles se puede visualizar en la figura 50 presente a continuación. Figura 50 Representación gráfica de árboles

Fuente: http://www.conclase.net/c/edd/index.php?cap=006b

Lección 2: Otros conceptos de la teoría general de árboles

“Con relación al tipo de nodos que hacen parte de los árboles, se identifican algunos nodos:

Page 133: 301305 Estructura de Datos

133

UNIVERSIDAD NACIONAL ABIERTA Y A DISTANCIA – UNAD ESCUELA DE CIENCIAS BÁSICAS TECNOLOGÍA E INGENIERÍA CONTENIDO DIDÁCTICO DEL CURSO: 301305 – ESTRUCTURA DE DATOS

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'. Los árboles con los que trabajará tienen otra característica importante: cada nodo sólo puede ser apuntado por otro nodo, es decir, cada nodo sólo tendrá un padre. Esto hace que estos árboles estén fuertemente jerarquizados, y es lo que en realidad les da la apariencia de árboles. En cuanto a la posición dentro del árbol: 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'. Nodo hoja: nodo que no tiene hijos. En el ejemplo hay varios: 'F', 'H', 'I', 'K', 'L', 'M', 'N' y 'O'. 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'.

Lección 3: Árbol completo Un árbol completo es aquel en el que en cada nodo o bien todos o ninguno de los hijos existen. Los árboles se parecen al resto de las estructuras tratadas en la unidad dos; dado un nodo cualquiera de la estructura, se puede considerar como una estructura independiente. Es decir, un nodo cualquiera puede ser considerado como la raíz de un árbol completo. Existen otros conceptos que definen las características del árbol, en relación a su tamaño:

Orden: es el número potencial de hijos que puede tener cada elemento de árbol. De este modo, se dice que un árbol en el que cada nodo puede apuntar a otros dos es de orden dos, si puede apuntar a tres será de orden tres y así sucesivamente. Grado: el número de hijos que tiene el elemento con más hijos dentro del árbol. En el árbol del ejemplo en la figura 50, el grado es tres, ya que tanto 'A' como 'D' tienen tres hijos, y no existen elementos con más de tres hijos. Nivel: se define para cada elemento del árbol como la distancia a la raíz, medida en nodos. El nivel de la raíz siempre será cero y el de sus hijos uno. Así

Page 134: 301305 Estructura de Datos

134

UNIVERSIDAD NACIONAL ABIERTA Y A DISTANCIA – UNAD ESCUELA DE CIENCIAS BÁSICAS TECNOLOGÍA E INGENIERÍA CONTENIDO DIDÁCTICO DEL CURSO: 301305 – ESTRUCTURA DE DATOS

sucesivamente. En el ejemplo de la figura 50, el nodo 'D' tiene nivel 1, el nodo 'G' tiene nivel 2, y el nodo 'N', nivel 3. Altura: la altura de un árbol se define como el nivel del nodo de mayor nivel. Como cada nodo de un árbol puede considerarse a su vez como la raíz de un árbol, también se puede hablar de altura de ramas. El árbol del ejemplo de la figura 50, tiene altura 3, la rama 'B' tiene altura 2, la rama 'G' tiene altura 1, la 'H' cero. Los árboles de orden dos son bastante especiales, de hecho se ampliará un poco la información en el siguiente capítulo. Estos árboles se conocen también como árboles binarios.

Frecuentemente, aunque tampoco es estrictamente necesario, para hacer más fácil moverse a través del árbol, se añade un puntero a cada nodo que apunte al nodo padre. De este modo se podrá avanzar en dirección a la raíz, y no sólo hacia las hojas.

Es importante conservar siempre el nodo Raíz ya que es el nodo a partir del cual se desarrolla el árbol, si se pierde este nodo, se perderá el acceso a todo el árbol.

Lección 4: Estructura para la creación de un árbol de orden tres El nodo típico de un árbol difiere de los nodos que se vieron en la unidad dos para el manejo de las listas, aunque sólo en el número de nodos. A continuación se presenta un ejemplo de nodo para crear árboles de orden tres:

struct Arbol { int dato; struct Arbol *rama1; struct Arbol *rama2; struct Arbol *rama3; }; Generalizando más se puede declarar un a constantes llamada orden que se le asigna el valor de 5: #define ORDEN 5 struct Arbol { int dato; struct Arbol *rama[ORDEN]; };

Page 135: 301305 Estructura de Datos

135

UNIVERSIDAD NACIONAL ABIERTA Y A DISTANCIA – UNAD ESCUELA DE CIENCIAS BÁSICAS TECNOLOGÍA E INGENIERÍA CONTENIDO DIDÁCTICO DEL CURSO: 301305 – ESTRUCTURA DE DATOS

El movimiento a través de árboles, salvo que se implementen punteros al nodo padre, será siempre partiendo del nodo raíz hacia un nodo hoja. Cada vez que se llegue a un nuevo nodo se podrá optar por cualquiera de los nodos a los que apunta para avanzar al siguiente nodo.

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 fichero, se podría considerar que los nodos hoja son ficheros y los nodos rama son directorios.

Operaciones básicas con árboles

Salvo que se trabaje con algún tipo de árboles especiales, como los que se verán en el siguiente capítulo es decir el capítulo 8, las inserciones serán siempre en punteros de nodos hoja o en punteros libres de nodos rama. Ya que con estas estructuras no es tan fácil generalizar, existen muchas variedades de árboles.

Nuevamente se tiene casi el mismo concepto de operaciones de las que se disponía con las listas enlazadas: Añadir o insertar elementos a un árbol. Buscar o localizar elementos dentro del árbol. Borrar elementos creados en el árbol. Moverse a través del árbol por cada uno de sus ramas. Recorrer el árbol completo. Los algoritmos de inserción y borrado dependen en gran medida del tipo de árbol que se esté implementando, de modo que por ahora se dejarán a un lado y se centrará la atención en el modo de recorrer los árboles.

Árboles ordenados

Los árboles ordenados son los que tienen más interés desde el punto de vista de los tipos de datos abstractos (TAD), y los que tienen más aplicaciones genéricas.

Un árbol ordenado, en general, es aquel que a partir del cual se puede obtener una secuencia ordenada siguiendo uno de los recorridos posibles del árbol, es decir en inorden, preorden o posorden.

En estos árboles es importante que la secuencia se mantenga ordenada aunque se añadan o se eliminen nodos.

Page 136: 301305 Estructura de Datos

136

UNIVERSIDAD NACIONAL ABIERTA Y A DISTANCIA – UNAD ESCUELA DE CIENCIAS BÁSICAS TECNOLOGÍA E INGENIERÍA CONTENIDO DIDÁCTICO DEL CURSO: 301305 – ESTRUCTURA DE DATOS

Existen varios tipos de árboles ordenados, a continuación se presentan a nivel informativo: Árboles binarios de búsqueda (ABB): son árboles de orden 2 que mantienen

una secuencia ordenada si se recorren en inorden.

Árboles AVL: son árboles binarios de búsqueda balanceados, es decir, los niveles de cada rama para cualquier nodo no difieren en más de 1.

Árboles perfectamente equilibrados: son árboles binarios de búsqueda en los que el número de nodos de cada rama para cualquier nodo no difieren en más de 1. Son por lo tanto árboles AVL también.

Árboles 2-3: son árboles de orden 3, que contienen dos claves en cada nodo y que están también equilibrados. También generan secuencias ordenadas al recorrerlos en inorden.

Árboles-B: caso general de árboles 2-3, que para un orden M, contienen M-1 claves”7.

Para finalizar la temática propuesta en el presente capítulo, se presenta a continuación en la lección 5, una introducción a lo que es el modo gráfico de C++, que será el referente para los inicios de la programación orientada a objetos y la aplicación a la temática de los capítulos 8 y 9 del presente curso. Bienvenidos….

Lección 5. Introducción al Modo Gráfico de C++ Después de haber trabajado la segunda unidad con la implementación de estructuras dinámicas lineales con punteros, se recomienda que la tercera unidad se realice por medio del modo gráfico, teniendo en cuenta que en esta unidad se hará la representación gráfica de los árboles y los grafos. Configuración del modo grafico de C++

Tal como se propone en la introducción general del curso, para el desarrollo del lenguaje de programación se recomienda trabajar con el compilador de Borlan C++ 3.0, la razones obedecen a que es uno de los compiladores más completos de uso general para plataforma Linux y Windows XP en especial, ya que para Windows Vista y Windows 7 en el manejo de gráficos se requiere una versión de compilador superior es por ello que para este curso se propone Borland C++ 5.5 7 Tomado de: http://www.conclase.net/c/edd/index.php?cap=006b.

Page 137: 301305 Estructura de Datos

137

UNIVERSIDAD NACIONAL ABIERTA Y A DISTANCIA – UNAD ESCUELA DE CIENCIAS BÁSICAS TECNOLOGÍA E INGENIERÍA CONTENIDO DIDÁCTICO DEL CURSO: 301305 – ESTRUCTURA DE DATOS

entre tantas versiones que hay disponibles y son de fácil manejo y algo adicional que es de libre uso y ya viene configurado siempre y cuando la descarga la realice del sitio https://sites.google.com/site/hhmosquera/file-cabinet. A continuación se muestra la interfaz gráfica del compilador Borland C++ 5.5. el cual recomiendo su uso para plataforma Windows Vista y Windows 7 pues no requiere de ningún tipo de configuración adicional ya tiene las librerías gráficas. Figura 51. Interfaz gráfica del compilador Borland C++ 5.5.

Se presentan algunas ventajas significativas de este compilador Borland C++ 5.5 comparado con Turbo C++ 3.0. El editor es mucho más flexible ya que permite copiar y pegar el código como se hace con cualquier aplicación de windows, los caracteres especiales responden deacuerdo a la configuración del idioma de su teclado, basta con compilar el programa para que se genere el ejecutable con extensión .exe que es el archivo en modo gráfico a visualizar como salida en pantalla. Es importante saber que el ejecutable se crea en la misma ruta donde tiene guardado el código fuente, es decir, el archivo con extensión .cpp. Para compilar el programa solo tiene que ubicar en la barra de menú del compilador la opción Tools y dar clic en la opción Compile o presione las teclas Ctrl + F7. Para probar si quedó bien instalado el compilador solo tiene que copiar en el editor el siguiente código fuente: #include <graphics.h> #include <conio.h>

Page 138: 301305 Estructura de Datos

138

UNIVERSIDAD NACIONAL ABIERTA Y A DISTANCIA – UNAD ESCUELA DE CIENCIAS BÁSICAS TECNOLOGÍA E INGENIERÍA CONTENIDO DIDÁCTICO DEL CURSO: 301305 – ESTRUCTURA DE DATOS

#include <stdio.h> void main(void) { int monitor=DETECT, modo; initgraph(&monitor,&modo,""); setcolor(YELLOW); line(10,50,50,100); setcolor(WHITE); circle(100,200,30); //setfillstyle(LINE_FILL,RED); floodfill(100,200,WHITE); rectangle(200,100,300,200); setfillstyle(HATCH_FILL,BLUE); floodfill(250,150,WHITE); setcolor(GREEN); settextstyle(GOTHIC_FONT,HORIZ_DIR,3); outtextxy(20,10,"Modo Gráfico de C++"); outtextxy(20,250,"Hola Ingeniero esto es:"); setcolor(CYAN); outtextxy(20,300,"Estructura de datos"); getch(); closegraph(); return; } Otra alternativa para trabajar en modo gráfico es el compilador de Turbo C++ 3.0, el cual requiere una configuración básica que se describe a continuación. Para configurar la versión de Borland C++ 3.0 en plataforma Windows XP se procede de la siguiente manera. Se parte del hecho de que ya se tiene instalado el compilador en la ruta que se define por defecto, es decir C:\TC\BIN. Para iniciar la configuración se debe abrir el editor creando un nuevo programa, Se debe habilitar las librerías gráficas, tal como se visualiza en la figura 52. Presente a continuación.

Figura 52 Opción para Habilitar las librerías gráficas de C++.

Page 139: 301305 Estructura de Datos

139

UNIVERSIDAD NACIONAL ABIERTA Y A DISTANCIA – UNAD ESCUELA DE CIENCIAS BÁSICAS TECNOLOGÍA E INGENIERÍA CONTENIDO DIDÁCTICO DEL CURSO: 301305 – ESTRUCTURA DE DATOS

Una vez haya seleccionado la opción Libraries….. se muestra la siguiente interfaz, la cual debe señalar la opción Graphics Library, para que quede marcada con la X y solo resta dar clic en la opción OK y listo. Una vez habilitada las librerías gráficas, solo queda por incluir la ruta donde se encuentran los archivos de la interfaz gráfica binaria (BGI) que está ubicada en la ruta que trae por defecto al instalarse el programa; esa ruta es C:\TC\BGI; se procede a incluir esta ruta en la opción de directorios tal como se muestra en la figura siguiente, Figura 53.

Figura 53 Configuración de directorio para BGI

Al dar clic en Opcions, se despliega el menú que se visualiza en la imagen, seleccione Directories… y lo lleva a la siguiente pantalla:

Figura 54 Interfaz de directorios de C++.

En la primera línea solo tiene que incluir la siguiente ruta tal como se ve en la siguiente gráfica; C:\TC\BGI

Page 140: 301305 Estructura de Datos

140

UNIVERSIDAD NACIONAL ABIERTA Y A DISTANCIA – UNAD ESCUELA DE CIENCIAS BÁSICAS TECNOLOGÍA E INGENIERÍA CONTENIDO DIDÁCTICO DEL CURSO: 301305 – ESTRUCTURA DE DATOS

Figura 55 Inclusión de la ruta C:\TC\BGI

Así se verá una vez haya incluido la ruta C:\TC\BGI solo debe presionar OK y listo ya tiene configurado el compilador para trabajar en modo gráfico sin problemas. Solo resta probar la configuración del editor para modo gráfico con un Hola mundo sencillo, que Grafica Figuras Geométricas, líneas, texto, colores y rellenos. El programa incluye comentarios explicativos en cada línea de código, se sugiere que estos comentarios los elimine para evitar que pueda generarle algún tipo de error de compilación. Progra32.cpp #include <graphics.h> // Encabezado con declaraciones de graficos #include <conio.h> #include <stdio.h> void main(void) { int monitor=DETECT, modo; // Declaracion de tipo de monitor y modo initgraph(&monitor,&modo,"C:\\tc\\bgi"); // Inicializa el modo grafico indicando el monitor y modo utilizado // El subdirectorio C:\\tc\\bgi indica la ruta de localizacion de los // archivos *.BGI (monitores) y *.CHR (tipos de letras) gotoxy(1,23);printf("getmaxx()=%d",getmaxx()); gotoxy(1,24);printf("getmaxy()=%d",getmaxy()); setcolor(YELLOW); // Establece el color amarillo para los trazos line(0,0,50,50); // Dibuja una linea desde 0,0 hasta 50,50 setcolor(WHITE); //Establece el color blanco circle(100,200,30); // Dibuja un circulo el centro está en 100,200 y de // radio=30 pixeles

Page 141: 301305 Estructura de Datos

141

UNIVERSIDAD NACIONAL ABIERTA Y A DISTANCIA – UNAD ESCUELA DE CIENCIAS BÁSICAS TECNOLOGÍA E INGENIERÍA CONTENIDO DIDÁCTICO DEL CURSO: 301305 – ESTRUCTURA DE DATOS

setfillstyle(LINE_FILL,RED); // Establece el relleno de lineas rojas floodfill(100,200,WHITE); // Rellena el contorno desde 100,200 hasta // encontrar un trazo blanco rectangle(200,100,300,200); // Dibuja un rectangulo desde 200,100 hasta // 300,200 setfillstyle(HATCH_FILL,BLUE); // Establece el relleno como cuadricula floodfill(250,150,WHITE); // Rellena el contorno desde 100,200 hasta // encontrar un trazo blanco setcolor(GREEN); //Establece el color verde settextstyle(GOTHIC_FONT,HORIZ_DIR,5); // Establece el font como Gotico // en posicion Horizontal de tamano 5 outtextxy(320,100,"Ingenieros Gothic "); // Despliega el mensaje "Gothic" en 330,100 setcolor(CYAN); //Establece el color celeste //settextstyle(SANS_SERIF_FONT,VERT_DIR,2);// Establece el font como // Sanserif en posicion Vertical de tamano 7 outtextxy(300,200,"Ingenieros Sanserif");// Despliega el mensaje "Sanserif" en 330,200 getch(); closegraph(); // Termina el modo grafico (vuelve a su modo normal) return; } La salida en pantalla de progra32.cpp lo visualiza en la siguiente figura 56.

Figura 56 Salida en pantalla de progra32 Modo grafico de C++.

Un ejemplo más completo con la temática de árboles binarios se realizará haciendo uso del modo gráfico en el capítulo siguiente y en los anexos 2 del módulo.

Page 142: 301305 Estructura de Datos

142

UNIVERSIDAD NACIONAL ABIERTA Y A DISTANCIA – UNAD ESCUELA DE CIENCIAS BÁSICAS TECNOLOGÍA E INGENIERÍA CONTENIDO DIDÁCTICO DEL CURSO: 301305 – ESTRUCTURA DE DATOS

CAPITULO 8: ÁRBOLES BINARIOS

Introducción

Los árboles binarios son estructuras de datos de no lineales, atendiendo más a una estructura de tipo jerárquico. En el presente capítulo se abordan los temas relacionados con los conceptos básicos de árboles binarios, incluyendo la teoría general de árboles binarios e identificando la forma de recorrerlos. Así como también la documentación de los árboles binarios de búsqueda y la forma de ir insertando los datos en el árbol. Se presenta un apartado amplio con el desarrollo de programas como aplicación en módo gráfico de C++. Finalizando con un programa de aplicación del modo gráfico que muestra la creación del árbol y la visualización de los recorridos.

Lección 6: Conceptualización de Arboles Binarios Este tipo de árbol se caracteriza porque tienen un vértice principal y de él se desprende dos ramas. La rama izquierda y la rama derecha a las que también se les conoce como subárboles. Figura 57 Estructura de un árbol binario

La rama izquierda y la derecha, también son dos árboles binarios. El Vértice principal se denomina raíz y cada una de las ramas se puede denominar como subárbol izquierdo y subárbol derecho.

Page 143: 301305 Estructura de Datos

143

UNIVERSIDAD NACIONAL ABIERTA Y A DISTANCIA – UNAD ESCUELA DE CIENCIAS BÁSICAS TECNOLOGÍA E INGENIERÍA CONTENIDO DIDÁCTICO DEL CURSO: 301305 – ESTRUCTURA DE DATOS

Representación gráfica de un árbol binario Figura 58 Representación gráfica de un árbol binario

La raíz de este árbol es A y el árbol izquierdo está conformado por dos árboles. Uno de raíz B tal como se muestra en la figura 59. Y el otro de raíz I tal como se muestra en la figura 60.

Figura 59 Representación gráfica del subárbol izquierdo

Los dos subárboles tienen a su vez dos subárboles cada uno, donde C y F son la raíces de los arboles del sub árbol izquierdo. Mientras que las raíces de los subárboles del subárbol derecho son J y M respectivamente, tal como se visualiza en la figura 60.

Page 144: 301305 Estructura de Datos

144

UNIVERSIDAD NACIONAL ABIERTA Y A DISTANCIA – UNAD ESCUELA DE CIENCIAS BÁSICAS TECNOLOGÍA E INGENIERÍA CONTENIDO DIDÁCTICO DEL CURSO: 301305 – ESTRUCTURA DE DATOS

Figura 60 Representación gráfica del subárbol derecho

Nodo: Un árbol binario es un conjunto de elementos cada uno de los cuales se denomina nodo. Un árbol Binario puede tener cero nodos y este caso se dice que está vacío. Puede tener un sólo nodo, y en este caso solamente existe la raíz del árbol o puede tener un número finito de nodos. Cada nodo puede estar ramificado por la izquierda o por la derecha o puede no tener ninguna ramificación. Padre: Un Padre es un nodo que puede o no tener ramificaciones. Un ejemplo se puede visualizar en la figura 61.

Figura 61 Representación gráfica de un nodo padre

En los tres casos el nodo A es un padre. En el caso 1 es un padre que no tiene hijos. En el caso 2, el nodo A es el padre del nodo B. En el caso 3 el nodo A es padre de los nodos B y C pero no es padre del nodo D.

Hijo: En el ejemplo anterior. El caso 1 el nodo A no tiene hijos. En el caso 2,B es un hijo del nodo A y en caso 3, D es hijo de B y el Padre de B es el nodo A.

Hermano: Nos referimos al caso 3 del ejemplo anterior. Los hermanos son los hijos de un mismo padre. Los nodos B y C son hermanos. El nodo D no tiene Hermanos.

Page 145: 301305 Estructura de Datos

145

UNIVERSIDAD NACIONAL ABIERTA Y A DISTANCIA – UNAD ESCUELA DE CIENCIAS BÁSICAS TECNOLOGÍA E INGENIERÍA CONTENIDO DIDÁCTICO DEL CURSO: 301305 – ESTRUCTURA DE DATOS

Hoja: Una hoja es un nodo que no tiene ramificaciones. Por ejemplo

Figura 62 Representación gráfica de un nodo hoja

El nodo C es una hoja mientras que el nodo B no se puede considerar como hoja porque tiene una ramificación por la derecha. El nodo D también es una hoja.

Nodo no terminal: Un nodo no terminal es aquel que posee por lo menos una ramificación. En el ejemplo anterior, el nodo A o el nodo B son nodos no terminales, mientras el nodo D o el nodo C son nodos terminales.

Camino: Un árbol siempre se examina de arriba hacia abajo. Por Ejemplo: Figura 63 Camino del árbol

Al nodo C se puede llegar desde el nodo B. Nunca se puede examinar el nodo B a partir del nodo C. Los apuntadores derecho o izquierdo de cualquier nodo apuntan al árbol derecho o izquierdo que siguen a ese nodo. Nunca apuntan a los nodos precedentes. Un Camino, es el conjunto de nodos que tenemos que visitar con el propósito de llegar a un nodo específico. Por ejemplo para llegar al nodo F, es necesario recorrer el camino: A ------- D ------ F

Page 146: 301305 Estructura de Datos

146

UNIVERSIDAD NACIONAL ABIERTA Y A DISTANCIA – UNAD ESCUELA DE CIENCIAS BÁSICAS TECNOLOGÍA E INGENIERÍA CONTENIDO DIDÁCTICO DEL CURSO: 301305 – ESTRUCTURA DE DATOS

Del mismo nodo, para llegar al nodo G debemos recorrer el camino: A ----- D ------- E ------- G Obsérvese que los Caminos se configuran siempre hacia abajo. Longitud: Longitud es el número de nodos que se deben recorrer para pasar de un nodo a otro. Por ejemplo: Figura 64 Longitud del árbol binario

De acuerdo a la figura 64. La longitud entre A y E es 3. La longitud entre G y G es 0. La longitud entre A y B es 1. Obsérvese que no se puede calcular la longitud entre B y G ya que el camino B ---- A ---- G no existe. Descendiente: El nodo C es descendiente del nodo A si a partir de A se puede llegar a C a través de un camino según la figura 64, El nodo C es descendiente de A ya que a C podemos llegar por el camino A -----B ------ C En el Ejemplo anterior, el nodo E es descendiente de D pero el nodo D no es descendiente de G. Ancestro: El nodo A es un ancestro del nodo C si existe un camino entre A y C. Basándonos en el ejemplo anterior, A es un ancestro de C ya que existe un Nivel: Cada nodo tiene un nivel dentro de un árbol binario. Por definición el nodo raíz tiene un nivel 0 y los demás nodos tienen el nivel de su padre más 1. Por esto los nodos que son hijos del nodo raíz tienen un nivel 1.

Page 147: 301305 Estructura de Datos

147

UNIVERSIDAD NACIONAL ABIERTA Y A DISTANCIA – UNAD ESCUELA DE CIENCIAS BÁSICAS TECNOLOGÍA E INGENIERÍA CONTENIDO DIDÁCTICO DEL CURSO: 301305 – ESTRUCTURA DE DATOS

Figura 65 Nivel del árbol

El nodo A, tienen un nivel 0 en tanto que los nodos R y F tienen un nivel 1 Obsérvese que el nivel del nodo G es la longitud del camino desde la raíz hasta el nodo y tiene nivel 3.

Grado de un Nodo. El grado de un nodo es el número de hijos. Por ejemplo el grado del nodo A es 2, el grado del nodo T es 1. El grado de un nodo terminal siempre es 0. En los árboles binarios, el grado de un nodo fluctúa entre 0 y 2. Altura: La altura de un árbol binario es el nivel de la hoja o de las hojas que están más distantes de la raíz. Basándose en la figura 65 de la gráfica anterior, la altura del árbol cuya raíz es A, corresponde a la longitud del camino para llegar a la hoja G que es más distante de la raíz, En este caso será 3.

Lección 7: Clasificación de los árboles binarios Árbol Binario completo: Un árbol binario completo es aquel en el que todo nodo no terminal tiene sus dos hijos. El siguiente es un árbol binario completo de nivel 3 Figura 66 Representación gráfica de un árbol binario completo.

Page 148: 301305 Estructura de Datos

148

UNIVERSIDAD NACIONAL ABIERTA Y A DISTANCIA – UNAD ESCUELA DE CIENCIAS BÁSICAS TECNOLOGÍA E INGENIERÍA CONTENIDO DIDÁCTICO DEL CURSO: 301305 – ESTRUCTURA DE DATOS

Obsérvese que todos los nodos no terminales tienen sus dos hijos. El máximo número de nodos que puede tener un árbol de nivel n puede representarse con la siguiente ecuación matemática: 2°+2¹+2²+2³...+2n

Si n es 3 entonces: 2°+2¹+2²+2³ = 15 El árbol de la figura 66, es un árbol binario completo de nivel 3, donde el número máximo de nodos es 15 tal como lo indica la fórmula matemática. Árbol binario Igual: Dos árboles son iguales si los dos son vacíos. Existe otro caso en el cual dos árboles son iguales:

Figura 67 Representación gráfica de Árbol binario igual

Estos árboles son iguales porque sus raíces son iguales y también lo son su respectivo árbol izquierdo y derecho. Para que un árbol sea igual a otro, es necesario que el contenido de cada uno de sus respectivos nodos sea el mismo y que tengan las mismas relaciones de parentesco. Árbol Binario Semejante: Dos árboles binarios son semejantes si tienen el mismo número de nodos y los valores de los nodos del primer árbol son los mismos que los valores de los nodos del segundo, sin importar la relación de parentesco entre ellos. Por ejemplo:

Page 149: 301305 Estructura de Datos

149

UNIVERSIDAD NACIONAL ABIERTA Y A DISTANCIA – UNAD ESCUELA DE CIENCIAS BÁSICAS TECNOLOGÍA E INGENIERÍA CONTENIDO DIDÁCTICO DEL CURSO: 301305 – ESTRUCTURA DE DATOS

Figura 68 Representación gráfica de árboles semejantes

Estos árboles son semejantes. Contienen los mismos valores en cada uno de sus nodos. Árbol Binario Isomorfo: Dos árboles binarios son isomorfos si tienen la misma estructura aunque el contenido de cada uno de sus nodos sea diferente. Por ejemplo los siguientes árboles son isomorfos. Figura 69 Representación gráfica de árboles isomorfos

Peso: El peso de un árbol en un nodo dado es el número de nodos en el árbol sin contarse el mismo. Por ejemplo teniendo como referente los árboles de la figura 69, se tiene que el peso de cualquiera de los dos árboles cuya raíz es A, corresponde al número de nodos para cada árbol es 6. Mientras que cualquiera de los nodos B y C tienen un peso de 2. Lección 8: Formas de Recorrer un Árbol Binario Los árboles binarios, son estructuras de datos no lineales, son considerados como estructuras jerárquicas y como tal su forma de recorrerlos difiere sustancialmente en comparación con las listas enlazadas que son estructuras de datos de tipo

Page 150: 301305 Estructura de Datos

150

UNIVERSIDAD NACIONAL ABIERTA Y A DISTANCIA – UNAD ESCUELA DE CIENCIAS BÁSICAS TECNOLOGÍA E INGENIERÍA CONTENIDO DIDÁCTICO DEL CURSO: 301305 – ESTRUCTURA DE DATOS

lineal. En ese orden de ideas, el recorrido de un árbol binario se lleva a cabo en tres sentidos: Preorden, Inorden y Postorden. A continuación se detalla cada caso. Recorrido en Preorden Recorrer un árbol en preorden consiste en primer lugar, examinar el dato del nodo raíz, posteriormente se recorrer el subárbol izquierdo en preorden y finalmente se recorre el subárbol derecho en preorden. Esto significa que para cada subárbol se debe conservar el recorrido en preorden, primero la raíz, luego la parte izquierda y posteriormente la parte derecha. En la figura 70, se visualiza un árbol binario, perfectamente equilibrado, en el que sus nodos son de tipo carácter. De acuerdo con la definición del recorrido en preorden el resultado sería: Figura 70 Recorrido del árbol binario en preorden

Otro ejemplo de recorrido en preorden, donde sus nodos son de tipo numérico para el siguiente árbol binario de la figura 71. Figura 71 Resultado del recorrido en preorden del árbol

Page 151: 301305 Estructura de Datos

151

UNIVERSIDAD NACIONAL ABIERTA Y A DISTANCIA – UNAD ESCUELA DE CIENCIAS BÁSICAS TECNOLOGÍA E INGENIERÍA CONTENIDO DIDÁCTICO DEL CURSO: 301305 – ESTRUCTURA DE DATOS

Una forma de implementar los recorridos de un árbol binario es a través de funciones específicas para dicha tarea. void preorden(tarbol *a) { if (a != NULL) { visitar(a); preorden(a->izq); preorden(a->der); } } Recorrido en Inorden Recorrer un árbol en Inorden consiste en primer lugar en recorrer el subárbol izquierdo en Inorden, luego se examina el dato del nodo raíz, y finalmente se recorre el subárbol derecho en Inorden. Esto significa que para cada subárbol se debe conservar el recorrido en Inorden, es decir, primero se visita la parte izquierda, luego la raíz y posteriormente la parte derecha. He aquí una aplicación un ejemplo: Manos a la obra… Se tiene el árbol binario de la figura 72, con datos de tipo numérico. El recorrido inicia con el subárbol izquierdo, el primer nodo a visitar es el 3 luego se visita el 5 y posteriormente el 7, con esto se garantiza que el recorrido del subárbol izquierdo se hizo en Inorden. Finalizado el recorrido del subárbol izquierdo se visita el nodo de la raíz, que para este caso es el numero 10. Solo queda recorrer el subárbol derecho en Inorden, es decir se visita el 11 luego el 12 y se finaliza con la visita del nodo 15 El resultado completo del recorrido en Inorden para el árbol de la figura 72 es: 3 - 5 - 7 - 10 - 11 - 12 – 15 Tal como se muestra en la figura.

Page 152: 301305 Estructura de Datos

152

UNIVERSIDAD NACIONAL ABIERTA Y A DISTANCIA – UNAD ESCUELA DE CIENCIAS BÁSICAS TECNOLOGÍA E INGENIERÍA CONTENIDO DIDÁCTICO DEL CURSO: 301305 – ESTRUCTURA DE DATOS

Figura 72 Representación gráfica del recorrido en Inorden

Se puede implementar el recorrido en Inorden de un árbol binario es a través de una función específicas para dicha tarea. void inorden(tarbol *a) { if (a != NULL) { inorden(a->izq); visitar(a); inorden(a->der); } } Por último solo queda describir la tercera forma de recorrer un árbol binario.

Recorrido en Postorden Recorrer un árbol en Postorden consiste en primer lugar en recorrer el subárbol izquierdo en Postorden, luego se recorre el subárbol derecho en Postorden y finalmente se visita el nodo raíz. Esto significa que para cada subárbol se debe conservar el recorrido en Postorden, es decir, primero se visita la parte izquierda, luego la parte derecha y por último la raíz. He aquí la aplicación con un ejemplo basado en el árbol de la figura 72: Manos a la obra… El recorrido inicia con el subárbol izquierdo, el primer nodo a visitar es el 3 luego se visita el 7 y posteriormente el 5 que es la raíz, con esto se garantiza que el recorrido del subárbol izquierdo se hizo en Postorden.

Page 153: 301305 Estructura de Datos

153

UNIVERSIDAD NACIONAL ABIERTA Y A DISTANCIA – UNAD ESCUELA DE CIENCIAS BÁSICAS TECNOLOGÍA E INGENIERÍA CONTENIDO DIDÁCTICO DEL CURSO: 301305 – ESTRUCTURA DE DATOS

Finalizado el recorrido del subárbol izquierdo se inicia la visita al subárbol derecho en Postorden, es decir, se visita el 11 luego el 15 y se finaliza con la visita del nodo 12 que sería la raíz de este subárbol. Solo queda recorrer la raíz del árbol que para este caso es el número 10. El resultado completo del recorrido en Postorden para el árbol de la figura 72 es: 3 - 7 - 5 - 11 - 15 – 12 - 10 Tal como se muestra en la siguiente figura 73. Figura 73 Recorrido en Postorden del árbol binario.

Se puede implementar el recorrido en Postorden de un árbol binario es a través de una función específicas para dicha tarea. void postorden(arbol *a) { if (a != NULL) { postorden(a->izq); postorden(a->der); visitar(a); } } Como aplicación a los tres recorridos de un árbol binario se presenta el siguiente árbol binario de la figura 74, con datos de tipo carácter con el propósito de identificar los recorridos es Preorden, Inorden, Postorden.

Page 154: 301305 Estructura de Datos

154

UNIVERSIDAD NACIONAL ABIERTA Y A DISTANCIA – UNAD ESCUELA DE CIENCIAS BÁSICAS TECNOLOGÍA E INGENIERÍA CONTENIDO DIDÁCTICO DEL CURSO: 301305 – ESTRUCTURA DE DATOS

Figura 74 Árbol binario como aplicación a los tres recorridos

El resultado que arroja al realizar los tres recorridos es el siguiente: Preorden: P Q S T R U W X V Y Z Inorden: S Q T P W U X R Y V Z Postorden: S T Q P W X U Y Z V R P Lección 9: Ábol binario de búsqueda (ABB)

Los árboles binarios de búsqueda, son un tipo especial de árbol binario cuya característica radica en la forma ordenada de insertar sus elementos, facilitando así la búsqueda de un nodo en particular. Para puntualizar aun más, se tratarán los árboles binarios de búsqueda, en los que se tiene preestablecido un cierto orden, que seguramente ayudará a encontrar un cierto dato dentro de un árbol con mucha rapidez. La pregunta sería; ¿cómo es este orden prefijado o preestablecido? La respuesta es sencilla y entenderlo es aun más, Solo se debe cumplir la condición que para cada nodo se tiene que:

la rama de la izquierda contendrá elementos menores. la rama de la derecha contendrá elementos mayores.

Tal como se ha mantenido la metodología a lo largo del curso, un ejemplo sería la forma de explicarlo. Manos a la obra… Se tienen los siguientes datos de tipo numérico para crear con ellos un árbol binario de búsqueda.

Page 155: 301305 Estructura de Datos

155

UNIVERSIDAD NACIONAL ABIERTA Y A DISTANCIA – UNAD ESCUELA DE CIENCIAS BÁSICAS TECNOLOGÍA E INGENIERÍA CONTENIDO DIDÁCTICO DEL CURSO: 301305 – ESTRUCTURA DE DATOS

Los datos son: 5 – 3 – 7 – 2 – 4 – 8 - 9 El primer nodo siempre será asignado a la raíz del árbol binario de búsqueda, así que para este caso el 5 es la raíz del árbol. 5 Primer número: 5 (directo) Segundo número: 3 se interroga (3 es menor que 5) la respuesta es sí, entonces va al lado izquierdo de 5. 5 / 3 Tercer número: 7 (7 es mayor que 5) se inserta al lado derecho de 5, con ello se va construyendo el árbol. 5 / \ 3 7 Cuarto número: 2 (2 es menor que 5, y menor que 3) entonces va al lado izquierdo del 3. 5 / \ 3 7 / 2 Quinto número: 4 (4 es menor que 5 pero es mayor que 3) entonces va al lado derecho del 3. Nada complicado. 5 / \ 3 7 / \ 2 4 Sexto número: 8 (8 es mayor que 5 y mayor que 7) en este caso se ingresa al lado derecho de 7.

Page 156: 301305 Estructura de Datos

156

UNIVERSIDAD NACIONAL ABIERTA Y A DISTANCIA – UNAD ESCUELA DE CIENCIAS BÁSICAS TECNOLOGÍA E INGENIERÍA CONTENIDO DIDÁCTICO DEL CURSO: 301305 – ESTRUCTURA DE DATOS

5 / \ 3 7 / \ \ 2 4 8 Séptimo número: 9 (9 es mayor que 5 , es mayor que 7 y es mayor que 8) en este caso se ingresa al lado derecho del número 8 formando de esta manera el árbol binario de búsqueda. 5 / \ 3 7 / \ \ 2 4 8 \ 9 Ventajas de los árboles binarios de búsqueda Para este tipo de árbol es muy evidente la rapidez con que se podría encontrar un el valor de un nodo; para este caso se tienen 7 elementos de tipo numérico no ordenados, lo que en una lista supone que si se busca un dato que casualmente está al final, se harían 7 comparaciones; en este árbol, dado que este árbol es de altura 4, se tienen que realizar 4 comparaciones como máximo. Y si además se hubiera equilibrado el árbol, es decir, irlo reacomodando de modo que siempre tenga la menor altura posible, habría quedado con una altura igual 3. Esto es lo que se hace en la práctica cuando en el árbol se va a hacer muchas más lecturas que escrituras: se reordena internamente después de añadir cada nuevo dato, de modo que la altura sea mínima en cada caso. De este modo, el número máximo de comparaciones que se tendrían que hacer sería representado por la expresión matemática log2(n), lo que supone que si se tienen 500 datos, en una lista se podría llegar a tener que hacer 500 comparaciones, y en un árbol binario de búsqueda, log2(1000) = 10 comparaciones como máximo. La ganancia en velocidad de búsqueda es clara. Habiendo conceptualizado la teoría de un árbol binario de búsqueda, la tarea sería desarrollar un programa en modo gráfico de C++ para que al insertar los datos ingresados por teclado en tiempo de ejecución, se imprima en pantalla la gráfica del árbol binario de búsqueda.

Page 157: 301305 Estructura de Datos

157

UNIVERSIDAD NACIONAL ABIERTA Y A DISTANCIA – UNAD ESCUELA DE CIENCIAS BÁSICAS TECNOLOGÍA E INGENIERÍA CONTENIDO DIDÁCTICO DEL CURSO: 301305 – ESTRUCTURA DE DATOS

Lección 10: Operaciones en ABB “Las operaciones que se pueden realizar sobre un árbol binario de búsqueda ABB es parecido al que se realizan sobre otras estructuras de datos lineales, más alguna otra propia de árboles entre ellas están: Buscar un elemento en cualquier posición del árbol Insertar un elemento en cualquier lugar del árbol Borrar un elemento ubicado en cualquier lugar del árbol. Movimientos a través del árbol:

Izquierda. Derecha. Raíz.

Borrar un nodo rama con intercambio de un nodo hoja En el árbol de ejemplo, representado en la figura 74, borrar el nodo 4.

1. Se localiza el nodo a borrar ('raíz'). 2. Se busca el nodo más a la derecha del árbol izquierdo de 'raíz', en este

caso el 3, al tiempo que se mantiene un puntero a 'Padre' a 'nodo'. 3. Se Intercambian los elementos 3 y 4. 4. Se hace que el puntero de 'Padre' que apuntaba a 'nodo', ahora apunte

a NULL. 5. Se borra el 'nodo'.

Figura 75 Borrado de un nodo rama con intercambio de nodo hoja

Fuente: http://www.conclase.net/c/edd/index.php?cap=007 Borrar un nodo rama con intercambio de un nodo rama Para este ejemplo se tiene otro árbol. En éste se borrará el elemento 6.

Page 158: 301305 Estructura de Datos

158

UNIVERSIDAD NACIONAL ABIERTA Y A DISTANCIA – UNAD ESCUELA DE CIENCIAS BÁSICAS TECNOLOGÍA E INGENIERÍA CONTENIDO DIDÁCTICO DEL CURSO: 301305 – ESTRUCTURA DE DATOS

Figura 76 Representación gráfica de un árbol binario de búsqueda

Fuente: http://www.conclase.net/c/edd/index.php?cap=007

1. Se localiza el nodo a borrar ('raíz'). 2. Se busca el nodo más a la izquierda del árbol derecho de 'raíz', en este

caso el 12, ya que el árbol derecho no tiene nodos a su izquierda, si se opta por la rama izquierda, se estará en un caso análogo. Al mismo tiempo que se mantiene un puntero a 'Padre' a 'nodo'.

3. Se intercambia los elementos 6 y 12. 4. Ahora se tiene que repetir el bucle para el nodo 6 de nuevo, ya que no

es posible eliminarlo. Figura 77 Borrado de un nodo rama con intercambio de nodo rama

Fuente: http://www.conclase.net/c/edd/index.php?cap=007

5. Se localiza de nuevo el nodo a borrar ('raíz'). 6. Se busca el nodo más a la izquierda del árbol derecho de 'raíz', en este

caso el 16, al mismo tiempo que se mantiene un puntero a 'Padre' a 'nodo'.

7. Se hace el intercambio de los elementos 6 y 16.

Page 159: 301305 Estructura de Datos

159

UNIVERSIDAD NACIONAL ABIERTA Y A DISTANCIA – UNAD ESCUELA DE CIENCIAS BÁSICAS TECNOLOGÍA E INGENIERÍA CONTENIDO DIDÁCTICO DEL CURSO: 301305 – ESTRUCTURA DE DATOS

8. Se hace que el puntero de 'Padre' que apuntaba a 'nodo', ahora apunte a NULL.

9. Se procede a borrar el 'nodo'. Figura 78 Intercambio de un nodo rama con intercambio de nodo rama

Fuente: http://www.conclase.net/c/edd/index.php?cap=007 Este modo de actuar asegura que el árbol sigue siendo ABB”8. Implementación de un árbol binario con Punteros Progra34.cpp #include <stdio.h> #include <conio.h> #include <stdlib.h> #include <ctype.h> #include <iostream.h> struct arbol { int dato; struct arbol *izq; struct arbol *der; }*raiz; enum{ FALSO=0, VERDADERO }; /*PROTOTIPOS*/ 8 Tomado de: http://ldcastillo.wordpress.com/tema-4-arboles-binarios/

Page 160: 301305 Estructura de Datos

160

UNIVERSIDAD NACIONAL ABIERTA Y A DISTANCIA – UNAD ESCUELA DE CIENCIAS BÁSICAS TECNOLOGÍA E INGENIERÍA CONTENIDO DIDÁCTICO DEL CURSO: 301305 – ESTRUCTURA DE DATOS

void inicializar( void ); int vacio( struct arbol *hoja ); int eshoja( struct arbol *hoja ); struct arbol *insertar( struct arbol *raiz, struct arbol *hoja, int num ); int busqueda( struct arbol *hoja, int num ); int nodos( struct arbol *hoja ); void auxnodos( struct arbol *hoja, int *cont ); struct arbol *borrarx( struct arbol *hoja, int num ); struct arbol *podar( struct arbol *hoja ); void preorden( struct arbol *hoja ); void inorden( struct arbol *hoja ); void posorden( struct arbol *hoja ); void menu_recorridos( void ); void menu_busquedas( void ); void menu_nodos( void ); void menu_podar( void ); void inicializar( void ) { raiz= NULL; } int vacio( struct arbol *hoja ) { if( !hoja ) return VERDADERO; return FALSO; } int eshoja( struct arbol *hoja ) { if( hoja->izq==NULL && hoja->der==NULL ) return VERDADERO; return FALSO; } struct arbol *insertar( struct arbol *raiz, struct arbol *hoja, int num ) { if( !hoja ) { hoja= (struct arbol *) malloc( sizeof (struct arbol) ); hoja->dato= num; hoja->izq= NULL; hoja->der= NULL; if( !raiz ) return hoja; else if( num<raiz->dato ) raiz->izq= hoja;

Page 161: 301305 Estructura de Datos

161

UNIVERSIDAD NACIONAL ABIERTA Y A DISTANCIA – UNAD ESCUELA DE CIENCIAS BÁSICAS TECNOLOGÍA E INGENIERÍA CONTENIDO DIDÁCTICO DEL CURSO: 301305 – ESTRUCTURA DE DATOS

else raiz->der= hoja; return hoja; } else if( num<hoja->dato ) insertar( hoja, hoja->izq, num ); else insertar( hoja, hoja->der, num ); return raiz; } int busqueda( struct arbol *hoja, int num ) { while( hoja ) { if( num==hoja->dato ) return VERDADERO; else { if( num<hoja->dato ) hoja= hoja->izq; else hoja= hoja->der; } } return FALSO; } int nodos( struct arbol *hoja ) { int nodos=0; auxnodos( hoja, &nodos ); return nodos; } void auxnodos( struct arbol *hoja, int *cont ) { if( !hoja ) return; (*cont)++; auxnodos( hoja->izq, cont ); auxnodos( hoja->der, cont ); } struct arbol *borrarx( struct arbol *hoja, int num ) { if( hoja->dato==num ) { struct arbol *p, *p2;

Page 162: 301305 Estructura de Datos

162

UNIVERSIDAD NACIONAL ABIERTA Y A DISTANCIA – UNAD ESCUELA DE CIENCIAS BÁSICAS TECNOLOGÍA E INGENIERÍA CONTENIDO DIDÁCTICO DEL CURSO: 301305 – ESTRUCTURA DE DATOS

if( vacio( hoja ) ) { free( hoja ); hoja= NULL; return hoja; } else if( hoja->izq==NULL ) { p= hoja->der; free( hoja ); return p; } else if( hoja->der==NULL ) { p= hoja->izq; free( hoja ); return p; } else { p= hoja->der; p2= hoja->der; while( p->izq ) p= p->izq; p->izq= hoja->izq; free( hoja ); return p2; } } else if( num<hoja->dato ) hoja->izq= borrarx( hoja->izq, num ); else hoja->der= borrarx( hoja->der, num ); return hoja; } struct arbol *podar( struct arbol *hoja ) { if( !hoja ) return hoja; podar( hoja->izq ); podar( hoja->der ); free( hoja ); hoja= NULL; return hoja; }

Page 163: 301305 Estructura de Datos

163

UNIVERSIDAD NACIONAL ABIERTA Y A DISTANCIA – UNAD ESCUELA DE CIENCIAS BÁSICAS TECNOLOGÍA E INGENIERÍA CONTENIDO DIDÁCTICO DEL CURSO: 301305 – ESTRUCTURA DE DATOS

/*Recorridos*/ void preorden( struct arbol *hoja ) { if( !hoja ) return; cout << hoja->dato ; preorden( hoja->izq ); preorden( hoja->der ); } void inorden( struct arbol *hoja ) { if( !hoja ) return; inorden( hoja->izq ); cout <<hoja->dato ; inorden( hoja->der ); } void posorden( struct arbol *hoja ) { if( !hoja ) return; posorden( hoja->izq ); posorden( hoja->der ); cout <<hoja->dato ; } /*Menus del Arbol*/ void menu_recorridos( void ) { char _op='S'; while( _op!='4' ) { clrscr(); cout << "1. PreOrden." ; cout << "\n2. InOrden." ; cout << "\n3. PosOrden." ; cout << "\n4. Salir." ; cout << "\n\n:: " ; _op= getch(); switch( _op ) { case '1':

Page 164: 301305 Estructura de Datos

164

UNIVERSIDAD NACIONAL ABIERTA Y A DISTANCIA – UNAD ESCUELA DE CIENCIAS BÁSICAS TECNOLOGÍA E INGENIERÍA CONTENIDO DIDÁCTICO DEL CURSO: 301305 – ESTRUCTURA DE DATOS

preorden( raiz ); getch(); break; case '2': inorden( raiz ); getch(); break; case '3': posorden( raiz ); getch(); break; } } return; } void menu_busquedas( void ) { int val; cout << "\n\nNumero: " ; cin>> val ; if( busqueda( raiz, val ) ) cout << "\n\nEncontrado.." ; else cout << "\n\nError, No se encuentra." ; getch(); } void menu_nodos( void ) { cout << "\n\nEl Numero de Nodos es " << nodos( raiz ) ; getch(); } void menu_podar( void ) { char _op='A'; int val; while( _op!='3' ) { clrscr(); cout << "1. Podar Un Nodos del Arbol." ; cout << "\n2. Podar Todo el Arbol." ;

Page 165: 301305 Estructura de Datos

165

UNIVERSIDAD NACIONAL ABIERTA Y A DISTANCIA – UNAD ESCUELA DE CIENCIAS BÁSICAS TECNOLOGÍA E INGENIERÍA CONTENIDO DIDÁCTICO DEL CURSO: 301305 – ESTRUCTURA DE DATOS

cout << "\n3. Salir." ; _op= getch(); switch( _op ) { case '1': cout << "\n\nNumero: " ; cin>> val ; raiz= borrarx( raiz, val ); cout << "\n\n.... Borrado ...." ; break; case '2': raiz= podar( raiz ); cout << "\n\nArbol Borrado por Completo." ; getch(); break; } } return; } int main() { char _op='A'; int val; inicializar(); while( _op!='S' ) { clrscr(); cout << "IMPLEMENTACION DE UN ARBOL BINARIO \n\n"; cout << "Insertar" ; cout << "\nRecorridos" ; cout << "\nBusquedas" ; cout << "\nNodos" ; cout << "\nPodar" ; cout << "\nSalir" ; cout << "\n\n Ingrese la Opcion : " ; _op= toupper( getch() ); switch( _op ) { case 'I': cout << "\n\nNumero: " ; cin>> val ; if( busqueda( raiz, val ) )

Page 166: 301305 Estructura de Datos

166

UNIVERSIDAD NACIONAL ABIERTA Y A DISTANCIA – UNAD ESCUELA DE CIENCIAS BÁSICAS TECNOLOGÍA E INGENIERÍA CONTENIDO DIDÁCTICO DEL CURSO: 301305 – ESTRUCTURA DE DATOS

{ cout << "\n\nEste numero ya ha sido insertado." ; getch(); break; } raiz= insertar( raiz, raiz, val ); break; case 'R': if( vacio( raiz ) ) { cout << "\n\nEl Arbol Aun esta Vacio." ; getch(); break; } menu_recorridos(); break; case 'B': if( vacio( raiz ) ) { cout << "\n\nEl Arbol Aun esta Vacio." ; getch(); break; } menu_busquedas(); break; case 'A': if( vacio( raiz ) ) { cout << "\n\nEl Arbol Aun esta Vacio." ; getch(); break; } case 'N': if( vacio( raiz ) ) { cout << "\n\nEl Arbol Aun esta Vacio." ; getch(); break; } menu_nodos(); break; case 'P': if( vacio( raiz ) ) { cout << "\n\nEl Arbol Aun esta Vacio." ;

Page 167: 301305 Estructura de Datos

167

UNIVERSIDAD NACIONAL ABIERTA Y A DISTANCIA – UNAD ESCUELA DE CIENCIAS BÁSICAS TECNOLOGÍA E INGENIERÍA CONTENIDO DIDÁCTICO DEL CURSO: 301305 – ESTRUCTURA DE DATOS

getch(); break; } menu_podar(); break; } } cout << "\n\nPulsa para salir..." ; getchar(); return 0; } El resultado después de la compilación y ejecución del listado, se puede visualizar en la figura 79 que se muestra a continuación. Figura 79 Salida en pantalla de progra34

Despues de haber profundizado en la temática de la unida tres relacionada con la teoría de árboles, árboles binarios y haber hecho una introducción al entorno gráfico de C++, solo resta presentar un programa completo funcional donde se de aplicabilidad a la teoría de árboles haciendo buen uso del modo gráfico. Implementación de los árboles binarios en modo gráfico El siguiente programa llamado progra35, fue realizado por Carlos Javier Guzmán, estudiante del programa de Ingeniería de Sistemas de la UNAD en el CEAD de Popayán Progra35.cpp //Autor: Carlos Javier Guzmán //Estudiante de Ingeniería de Sistemas del CEAD de Popayán #include <graphics.h> #include <iostream.h> #include <string.h>

Page 168: 301305 Estructura de Datos

168

UNIVERSIDAD NACIONAL ABIERTA Y A DISTANCIA – UNAD ESCUELA DE CIENCIAS BÁSICAS TECNOLOGÍA E INGENIERÍA CONTENIDO DIDÁCTICO DEL CURSO: 301305 – ESTRUCTURA DE DATOS

#include <dos.h> #include <conio.h> #include <stdlib.h> void cajadetexto_a(int x,int y,int ancho,int altura); int iniciagrafica(); int linea_iz(int tx, int px1, int py1, int ty, int px2, int py2); int linea_der(int tx, int px1, int py1, int ty, int px2, int py2); int presentacion(); int ordenar(); int texto(); //para textos int verificar(int z); //analiza cuando hijos pueden haber main() { // int z; iniciagrafica(); setbkcolor(DARKGRAY); //color de fondo de pantalla setfillstyle(SOLID_FILL,LIGHTGRAY); //fondo de la ventana grande bar3d(620,470,5,20,10,30);//x/y/px1/py1/an //ventana grande presentacion(); cajadetexto_a(280,30,30,30);//px,py,largo,ancho A outtextxy(292,42,"A"); ordenar(); getch(); } int iniciagrafica() { int gdriver = DETECT, gmode, errorcode; initgraph(&gdriver, &gmode, "c:\\tc\\bgi"); } int ordenar() { int A,B,D,G,C,M,P,x; texto(); //llama la caja de texto outtextxy(55,388,"Cuandos hijos tiene A "); gotoxy(31,25);

Page 169: 301305 Estructura de Datos

169

UNIVERSIDAD NACIONAL ABIERTA Y A DISTANCIA – UNAD ESCUELA DE CIENCIAS BÁSICAS TECNOLOGÍA E INGENIERÍA CONTENIDO DIDÁCTICO DEL CURSO: 301305 – ESTRUCTURA DE DATOS

cin>>x; texto();// llama caja de texto para no spbrescribir A=verificar(x); if(A==1 || A==2) //B { //comienza lado izquierdo setcolor(5); linea_iz(125,276,40, 55,150,39);//izquierdo entre b y a cajadetexto_a(137,100,30,30);//px,py,largo,ancho isz 5.1 B outtextxy(150,110,"B"); //b if(A==2) { setcolor(13); linea_der(145,307,40, 55,452,39);//izquierdo entre c y a cajadetexto_a(439,100,30,30);//px,py,largo,ancho derecha 5.3 C outtextxy(452,110,"C"); } outtextxy(55,388,"Cuandos hijos tiene B "); gotoxy(31,25); cin>>x; texto();// llama caja de texto para no spbrescribir B=verificar(x); if(B==1); { setcolor(5); linea_iz(60,133,110, 75,72,109); //izquierda entre d y b cajadetexto_a(60,190,30,30);//px,py,largo,ancho iszquierda 1 D outtextxy(73,200,"D"); //D } if(B==2) //D y G { setcolor(5); linea_iz(60,133,110, 75,72,109); //izquierda entre d y b cajadetexto_a(60,190,30,30);//px,py,largo,ancho iszquierda 1 D outtextxy(73,200,"D"); // D setcolor(5); linea_der(57,164,110, 75,220,109);//izquierdo entre g y b cajadetexto_a(207,190,30,30);//px,py,largo,ancho iszquierda 2 G

Page 170: 301305 Estructura de Datos

170

UNIVERSIDAD NACIONAL ABIERTA Y A DISTANCIA – UNAD ESCUELA DE CIENCIAS BÁSICAS TECNOLOGÍA E INGENIERÍA CONTENIDO DIDÁCTICO DEL CURSO: 301305 – ESTRUCTURA DE DATOS

outtextxy(220,200,"G"); //G } outtextxy(55,388,"Cuandos hijos tiene D "); gotoxy(31,25); cin>>x; texto();// llama caja de texto para no sobrescribir D=verificar(x); if(D==1)//D { setcolor(5); linea_iz(34,55,198, 55,22,198); //izquierda entre e y d cajadetexto_a(10,250,30,30);//px,py,largo,ancho iszquierda 1.1 E outtextxy(23,263,"E"); } if(D==2) //E Y F { setcolor(5); linea_iz(34,55,198, 55,22,198); //izquierda entre e y d cajadetexto_a(10,250,30,30);//px,py,largo,ancho iszquierda 1.1 E outtextxy(23,263,"E"); setcolor(5); linea_der(28,87,198, 55,114,197);//izquierdo entre f y d cajadetexto_a(100,250,30,30);//px,py,largo,ancho iszquierda 1.2 F outtextxy(113,263,"F"); } if(B==2) { outtextxy(55,388,"Cuandos hijos tiene G "); gotoxy(31,25); cin>>x; texto();// llama caja de texto para no sobrescribir G=verificar(x); if(G==1) //H { setcolor(5); linea_iz(30,203,199, 45,173,199); //izquierda entre h y g cajadetexto_a(160,250,30,30);//px,py,largo,ancho iszquierda 2.1 H outtextxy(173,263,"H"); setcolor(5);

Page 171: 301305 Estructura de Datos

171

UNIVERSIDAD NACIONAL ABIERTA Y A DISTANCIA – UNAD ESCUELA DE CIENCIAS BÁSICAS TECNOLOGÍA E INGENIERÍA CONTENIDO DIDÁCTICO DEL CURSO: 301305 – ESTRUCTURA DE DATOS

} if(G==2) // H y I { setcolor(5); linea_iz(30,203,199, 45,173,199); //izquierda entre h y g cajadetexto_a(160,250,30,30);//px,py,largo,ancho iszquierda 2.1 H outtextxy(173,263,"H"); setcolor(5); linea_der(28,234,199, 47,261,198);//izquierdo entre i y g cajadetexto_a(250,250,30,30);//px,py,largo,ancho iszquierda 2.2 I outtextxy(263,263,"I"); } } } //termina lado izquierdo if(A==2) { outtextxy(55,388,"Cuandos hijos tiene C "); gotoxy(31,25); cin>>x; texto();// llama caja de texto para no sobrescribir C=verificar(x); if(C==1) { setcolor(13); linea_der(55,466,110, 75,520,109);//izquierdo entre c y p setcolor(13); cajadetexto_a(510,190,30,30);//px,py,largo,ancho derecha 4 P outtextxy(522,200,"P"); } if(C==2) { setcolor(13); linea_iz(57,435,110, 75,378,109); //izquierda entre m y c setcolor(13); cajadetexto_a(367,190,30,30);//px,py,largo,ancho dercha 3 M outtextxy(379,200,"M"); setcolor(13); linea_der(55,466,110, 75,520,109);//izquierdo entre c y p

Page 172: 301305 Estructura de Datos

172

UNIVERSIDAD NACIONAL ABIERTA Y A DISTANCIA – UNAD ESCUELA DE CIENCIAS BÁSICAS TECNOLOGÍA E INGENIERÍA CONTENIDO DIDÁCTICO DEL CURSO: 301305 – ESTRUCTURA DE DATOS

setcolor(13); cajadetexto_a(510,190,30,30);//px,py,largo,ancho derecha 4 P outtextxy(522,200,"P"); } outtextxy(55,388,"Cuandos hijos tiene P "); gotoxy(31,25); cin>>x; texto();// llama caja de texto para no sobrescribir P=verificar(x); if(P==1) { setcolor(13); linea_der(28,537,199, 47,564,198);//izquierdo entre z y p cajadetexto_a(550,250,30,30);//px,py,largo,ancho derecha 4.2 Z outtextxy(563,263,"Z"); } if(P==2) { setcolor(13); linea_iz(25,506,199, 45,482,199); //izquierda entre q y p cajadetexto_a(470,250,30,30);//px,py,largo,ancho derecha 4.1 Q outtextxy(482,263,"Q"); setcolor(13); linea_der(28,537,199, 47,564,198);//izquierdo entre z y p cajadetexto_a(550,250,30,30);//px,py,largo,ancho derecha 4.2 Z outtextxy(563,263,"Z"); } if(C==2) { outtextxy(55,388,"Cuandos hijos tiene M "); gotoxy(31,25); cin>>x; texto();// llama caja de texto para no sobrescribir M=verificar(x); if(M==1) { setcolor(13); linea_iz(33,364,199, 45,332,199); //izquierda entre n y m cajadetexto_a(320,250,30,30);//px,py,largo,ancho derecha 3.1 N

Page 173: 301305 Estructura de Datos

173

UNIVERSIDAD NACIONAL ABIERTA Y A DISTANCIA – UNAD ESCUELA DE CIENCIAS BÁSICAS TECNOLOGÍA E INGENIERÍA CONTENIDO DIDÁCTICO DEL CURSO: 301305 – ESTRUCTURA DE DATOS

outtextxy(332,263,"N"); } if(M==2) { setcolor(13); linea_iz(33,364,199, 45,332,199); //izquierda entre n y m cajadetexto_a(320,250,30,30);//px,py,largo,ancho derecha 3.1 N outtextxy(332,263,"N"); setcolor(13); linea_der(28,394,199, 47,422,198);//izquierdo entre o y m cajadetexto_a(410,250,30,30);//px,py,largo,ancho derecha 3.2 O outtextxy(422,263,"O"); } } } //termina A=2 }//termina funcion ordenar void cajadetexto_a(int x,int y,int ancho,int altura) { setcolor(DARKGRAY); line(x,y,x+ancho-1,y); //linea superior gris oscuro line(x,y,x,y+altura-1);//linea inferior derecha gris oscuro setcolor(LIGHTGRAY); line(x+1,y+altura-1,x+ancho-1,y+altura-1); //linea inferior gris line(x+ancho-1,y+1,x+ancho-1,y+altura-1); //linea derecha gris setcolor(WHITE); line(x,y+altura,x+ancho,y+altura); //linea inferior blanco externo line(x+ancho,y,x+ancho,y+altura); //linea derescha blanco externo setfillstyle(SOLID_FILL,9); bar(x+1,y+1,x+ancho-2,y+altura-2); //pinta el cuadro de blanco } int linea_iz(int tx, int px1, int py1, int ty, int px2, int py2) { for(int i=1; i<tx; i++) { outtextxy(px1-i,py1,"."); delay(15); }

Page 174: 301305 Estructura de Datos

174

UNIVERSIDAD NACIONAL ABIERTA Y A DISTANCIA – UNAD ESCUELA DE CIENCIAS BÁSICAS TECNOLOGÍA E INGENIERÍA CONTENIDO DIDÁCTICO DEL CURSO: 301305 – ESTRUCTURA DE DATOS

for(i=1; i<ty; i++) { outtextxy(px2,i+py2,"."); delay(15); } } int linea_der(int tx, int px1, int py1, int ty, int px2, int py2) { for(int i=1; i<tx; i++) { outtextxy(px1+i,py1,"."); delay(15); } for(i=1; i<ty; i++) { outtextxy(px2,i+py2,"."); delay(15); } } int presentacion() { cajadetexto_a(12,25,130,30);//px,py,largo,ancho A cuadro de mensaje arbo cajadetexto_a(482,25,130,30);//px,py,largo,ancho A cuadro de mensaje carlos sleep(1); setcolor(11); outtextxy(15,32,"Arboles"); sleep(1); outtextxy(68,44,"Binarios"); sleep(1); setcolor(11); outtextxy(495,32,"Carlos Javier"); sleep(1); outtextxy(524,44,"Guzman"); } int texto() {

Page 175: 301305 Estructura de Datos

175

UNIVERSIDAD NACIONAL ABIERTA Y A DISTANCIA – UNAD ESCUELA DE CIENCIAS BÁSICAS TECNOLOGÍA E INGENIERÍA CONTENIDO DIDÁCTICO DEL CURSO: 301305 – ESTRUCTURA DE DATOS

cajadetexto_a(50,375,180,30);//px,py,largo,ancho A cajadetexto_a(230,375,30,30);//px,py,largo,ancho A } int verificar(int z) { int n,d; n=z; while(n<=0 || n>=3) { outtextxy(60,386,"Dato errado, ingrese "); outtextxy(64,393,"otro dato "); gotoxy(31,25); cin>>n; texto();// llama caja de texto para no sobrescribir } if(n==1 || n==2) { return n; } return n; } Actividad de verificación Como actividad de verificación, se propone que cada estudiante de forma individual, analice el código que se presenta en el anterior programa en el listado llamado progra35, con el fin de que lo edite y lo lleve al compilador para ver la salida en pantalla, el cual pone en práctica los conocimientos adquiridos en la temática de árboles binarios, en la ejecución del programa.

Page 176: 301305 Estructura de Datos

176

UNIVERSIDAD NACIONAL ABIERTA Y A DISTANCIA – UNAD ESCUELA DE CIENCIAS BÁSICAS TECNOLOGÍA E INGENIERÍA CONTENIDO DIDÁCTICO DEL CURSO: 301305 – ESTRUCTURA DE DATOS

CAPITULO 3: GRAFOS

Introducción

Los grafos al igual que los árboles son estructuras de datos de no lineales, semejada a una estructura de tipo jerárquico. En el presente capítulo se abordan los temas relacionados con los conceptos básicos de grafos, incluyendo la teoría general de grafos e identificando la forma de recorrerlos. Así como también la documentación de los tipos de grafos y la representación a través de matriz de adyacencia y de listas de adyacencia especialmente. Al final del capítulo se propone como actividad de veririficación un programa de aplicación al modo gráfico de C++. Donde se evidencie la creación del grafo, la interacción de los recorridos y la visualización del árbol en pantalla.

Lección 11: Conceptos básicos de grafos Los grafos son una de las herramientas más empleadas en matemáticas, estadística, investigación operativa y en numerosos campos científicos. El estudio de la teoría de grafos se realiza fundamentalmente como elemento de Matemática discreta o Matemática aplicada. El conocimiento profundo de la teoría de grafos junto con los algoritmos de implementación es fundamental para conseguir el mayor rendimiento de las operaciones con datos, sobre todo si éstos son complejos en su organización. Un programador de alto nivel no puede dejar de conocer en toda su profundidad la teoría de grafos y sus operaciones, que además le servirá de báse para enfrentase a los cursos de investigación de operaciones, donde se conceptualizará de una manera matematica lo referente e este tema

La teoría de grafos es una rama de la matemática combinatoria muy útil en la solución de muchos problemas prácticos que se formulan de manera natural por medio de objetos y sus conexiones entre ellos (determinar el camino más corto entre dos ciudades, análisis de circuitos eléctricos, ordenación de tareas). En este capítulo se hace la implementación de los grafos como representación gráfica como aplicación a la fundamentación teórica. Se recomienda que se realice por medio del entorno gráfico que nos presenta el compilador de C++, de esta manera se hace un acercamiento a la programación orientada a objetos.

Page 177: 301305 Estructura de Datos

177

UNIVERSIDAD NACIONAL ABIERTA Y A DISTANCIA – UNAD ESCUELA DE CIENCIAS BÁSICAS TECNOLOGÍA E INGENIERÍA CONTENIDO DIDÁCTICO DEL CURSO: 301305 – ESTRUCTURA DE DATOS

Definición grafos

Un grafo es un objeto matemático conformado por una colección de vértices (o nodos) y aristas que se encargan de conectar o unir los. Los vértices son objetos simples que pueden tener un nombre y otras propiedades es decir información y una arista que es la conexión entre dos vértices. Representación grafica de los Grafos Los grafos pueden ser representados en situaciones de la vida práctica, para el caso de la figura 80, representa una red de aeropuertos entre algunas ciudades de colombia.

Figura 80 Representación gráfica de los grafos

A continuación se presentan algunas definiciones básicas de la teoría de grafos. Vértices: un vértice también llamado nodo es la unidad fundamental de la conformación de los grafos, en la figura 80, los vértices representan las ciudades. Aristas: son consideradas las uniones entre los nodos o vértices, véase la primera figura 80, donde las aristas representan la unión entre ciudades. Generalmente las aristas denotan relaciones entre los vértices. Las aristas, junto con los vértices forman los elementos principales de un grafo. Grafo dirigido (Red): Un grafo dirigido G consiste de un conjunto V de vértices y un conjunto E de aristas del grafo un no dirigido está formado por un conjunto de vértices y un conjunto de aristas (pares no ordenados de vértices), mientras que un grafo dirigido está compuesto por un conjunto de vértices y un conjunto de arcos. Un ejemplo práctico de grafo dirigido lo constituye la red del acueducto de una ciudad, ya que cada tubería sólo admite que el agua la recorra en un único sentido. Mientras que un ejemplo práctico para un grafo no dirigido lo representa

Page 178: 301305 Estructura de Datos

178

UNIVERSIDAD NACIONAL ABIERTA Y A DISTANCIA – UNAD ESCUELA DE CIENCIAS BÁSICAS TECNOLOGÍA E INGENIERÍA CONTENIDO DIDÁCTICO DEL CURSO: 301305 – ESTRUCTURA DE DATOS

la red de carreteras de un país, puesto que una misma carretera puede ser recorrida en ambos sentidos.

Representación gráfica de un grafo dirigido La siguiente figura 81, muestra la representación de un grafo dirigido. Figura 81 Representación gráfica de un gráfo dirigido

Fuente: http://www.slideshare.net/pilypardo/grafos-1407276

Lección 12: Grafo no dirigido Sea G un grafo no dirigido donde G =(V,E) donde V corresponde al conjunto de vértices y E el conjunto de aristas del grafo, un grafo no dirigido se diferencia de un grafo dirigido porque cada arista en E es un par no ordenado de vértices. Cuando no importa la dirección de una arista, el grafo se denomina no dirigido lo muestra la figura 82. Una aplicación de los grafos no dirigidos, es la red de computadoras de una empresa, en donde los vértices están representados en las terminales de los computadores y las ariatasn son el cabeado o en su defecto la conección inhalambrica. En ese sentido la información de la red se da en ambos sentidos al enviar y recibir información de cada terminal.

Figura 82 Representación gráfica de un grafo no dirigido

Fuente: http://www.slideshare.net/pilypardo/grafos-1407276

Page 179: 301305 Estructura de Datos

179

UNIVERSIDAD NACIONAL ABIERTA Y A DISTANCIA – UNAD ESCUELA DE CIENCIAS BÁSICAS TECNOLOGÍA E INGENIERÍA CONTENIDO DIDÁCTICO DEL CURSO: 301305 – ESTRUCTURA DE DATOS

Costos: Los enlaces tanto para los grafos dirigidos como para los grafos no dirigidos tienen un peso, costo o valor, por lo que se conocen como grafos etiquetados. Para ampliar este concepto se puede visualizar la figura 83. Que se muestra a continuación. Figura 83 Representación gráfica de grafos etiquetados

Fuente: http://www.slideshare.net/pilypardo/grafos-1407276 En general el término grafo hace referencia a un grafo no dirigido, a menos que se especifique lo contrario. Camino: Es la secuencia o ruta de un vértice inicial a un vértice final. El número de aristas de un camino (ciclo) se denomina longitud de camino (ciclo). Un camino es simple si sólo pasa una sola vez por cada nodo. La longitud del camino: es el número de arcos que comprende y en el caso en el que el grafo sea ponderado se calculará como la suma de los pesos de las aristas que lo constituyen. Figura 84 Representación gráfica de la longitud del camino de un grafo

Con base en la figura 84 que representa un grafo no dirigido se puede extrapolar la siguiente información relacionada con el camino.

Page 180: 301305 Estructura de Datos

180

UNIVERSIDAD NACIONAL ABIERTA Y A DISTANCIA – UNAD ESCUELA DE CIENCIAS BÁSICAS TECNOLOGÍA E INGENIERÍA CONTENIDO DIDÁCTICO DEL CURSO: 301305 – ESTRUCTURA DE DATOS

Un camino simple de “a” a “f” = {a,b}, {b,c}, {c,f} Un camino simple de “a” a “f” = {a,b}, {b,c}, {c,e}, {e,d}, {d,c}, {c,f} Un ciclo simple: {a,b}, {b,d}, {d,a}

Un ciclo no simple: {a,b}, {b,d}, {d,c}, {c,e}, {e,d}, {d,a}

Grafo Conexo: Sea G = (V, E) un grafo no dirigido, entonces G es conexo si existe un camino entre cada par de vértices de G. Por otra parte, sea G un grafo dirigido, y sea G’ su grafo no dirigido asociado, entonces si G’ es conexo, G se considera conexo.

Grafos Completos: es aquel con una arista entre cada par de vértices, es decir un grafo con todas las aristas posibles. Por otra parte, se denominan grafos densos aquellos que tienen muchas aristas.

Grafos Ponderados: Se le asignan pesos a las aristas para representar la distancia o el costo asociado a pasar por dicha arista. Grafo nulo: Se dice que un grafo es nulo cuando los vértices que lo componen no están conectados, esto es, que son vértices aislados. Grafos Isomorfos: Dos grafos son isomorfos cuando existe una correspondencia biunívoca (uno a uno), entre sus vértices de tal forma que dos de estos quedan unidos por una arista en común. Lección 13: Representación de los grafos Los grafos independientemente de que sean Dirigidos o no dirigidos, pueden ser representados mediante tres formas: Matriz de adyacencia Lista de adyacencia Arreglos para listas de adyacencias Se tiene el siguiente grafo dirigido, representado por el conjunto V, integrado por los elemento 1,2,3,4. Matemáticamente representado por: V = {1,2,3,4} E = {(1,2),(2,3),(3,1), ((4,2),(3,4)}

Page 181: 301305 Estructura de Datos

181

UNIVERSIDAD NACIONAL ABIERTA Y A DISTANCIA – UNAD ESCUELA DE CIENCIAS BÁSICAS TECNOLOGÍA E INGENIERÍA CONTENIDO DIDÁCTICO DEL CURSO: 301305 – ESTRUCTURA DE DATOS

Figura 85 Grafo dirigido

http://www.slideshare.net/pilypardo/grafos-1407276 Representación por Matriz de Adyacencia La forma más fácil de guardar la información de los nodos es mediante la utilización de un vector que indexe los nodos, de manera que los arcos entre los nodos se pueden ver como relaciones entre los índices. Esta relación entre índices se puede guardar en una matriz, que llamaremos de adyacencia. La matriz de adyacencia A de un grafo G=(V,E) tiene V*V elementos la cual se define matemáticamente como : A[ i , j ] = {1 si (i , j) € E y 0 en cualquier otro caso} Figura 86 Representación gráfica de la matriz de adyacencia

Fuente: http://www.slideshare.net/pilypardo/grafos-1407276 “Cuando se trata de grafos ponderados en lugar de 1 el valor que tomará será el peso de la arista. Si el grafo es no dirigido hay que asegurarse de que se marca con un 1 (o con el

Page 182: 301305 Estructura de Datos

182

UNIVERSIDAD NACIONAL ABIERTA Y A DISTANCIA – UNAD ESCUELA DE CIENCIAS BÁSICAS TECNOLOGÍA E INGENIERÍA CONTENIDO DIDÁCTICO DEL CURSO: 301305 – ESTRUCTURA DE DATOS

peso) tanto la entrada a[i][j] como la entrada a[j][i], puesto que se puede recorrer en ambos sentidos. int V,A; int a[maxV][maxV]; void inicializar() { int i,x,y,p; char v1,v2; // Leer V y A memset(a,0,sizeof(a)); for (i=1; i<=A; i++) { Cout <<"\n" <<v1 <<v2 <<p; x=v1-'A'; y=v2-'A'; a[x][y]=p; a[y][x]=p; } } En esta implementación se ha supuesto que los vértices se nombran con una letra mayúscula y no hay errores en la entrada. Evidentemente, cada problema tendrá una forma de entrada distinta y la inicialización será conveniente adaptarla a cada situación. En todo caso, esta operación es sencilla si el número de nodos es pequeño. Si, por el contrario, la entrada fuese muy grande se pueden almacenar los nombres de nodos en un árbol binario de búsqueda o utilizar una tabla de dispersión, asignando un entero a cada nodo, que será el utilizado en la matriz de adyacencia. Como se puede apreciar, la matriz de adyacencia siempre ocupa un espacio de V*V, es decir, depende solamente del número de nodos y no del de aristas, por lo que será útil para representar grafos densos”9. A la matriz de adyacencia se le pueden considerar algunas ventajas y desventajas. Ventajas de la matriz de adyacencia Se puede determinar en un tiempo fijo si y constante, si un enlace (arco) pertenece o no al grafo. Es fácil determinar si existe o no un arco o enlace, solo se debe posicionar en la matriz. 9Tomado de: http://www.algoritmia.net/articles.php?id=18

Page 183: 301305 Estructura de Datos

183

UNIVERSIDAD NACIONAL ABIERTA Y A DISTANCIA – UNAD ESCUELA DE CIENCIAS BÁSICAS TECNOLOGÍA E INGENIERÍA CONTENIDO DIDÁCTICO DEL CURSO: 301305 – ESTRUCTURA DE DATOS

Es fácil determinar si existe un ciclo en el grafo, solo basta con multiplicar la matriz por ella mismo n veces hasta obtener la matriz nula (no hat ciclos) o bien una sucesión periodica de matrices (hay ciclo). Desventajas de la matriz de adyacencia Se requiere un almacenamiento |v|*|v|. Es decir O(n2). Solo al leer o examinar la matriz puede llevar un tiempo de O(n2). Lección 14: Representación mediante listas de Adyacencia En las listas de adyacencia para un vértice v es unas listas enlazadas de todos los vértices w adyacentes a v. Un grafo puede estar representado por un |v|, listas de adyacencia, una para cada vértice. Figura 87 Representación gráfica de un grafo por lista de adyacencia

Fuente: http://www.slideshare.net/pilypardo/grafos-1407276 “En las listas de adyacencia lo que se haga será guardado por cada nodo, además de la información que pueda contener el propio nodo, una lista dinámica con los nodos a los que se puede acceder desde él. La información de los nodos se puede guardar en un vector, al igual que antes, o en otra lista dinámica. Las listas de adyacencia serán estructuras que contendrán un valor entero (el número que identifica al nodo destino), así como otro entero que indica el coste en el caso de que el grafo sea ponderado. En el ejemplo siguiente se ha utilizado una estructura con un nodo z ficticio en la cola. struct nodo { int v;

Page 184: 301305 Estructura de Datos

184

UNIVERSIDAD NACIONAL ABIERTA Y A DISTANCIA – UNAD ESCUELA DE CIENCIAS BÁSICAS TECNOLOGÍA E INGENIERÍA CONTENIDO DIDÁCTICO DEL CURSO: 301305 – ESTRUCTURA DE DATOS

int p; nodo *sig; }; int V,A; // vértices y aristas del grafo struct nodo *a[maxV], *z; void inicializar() { int i,x,y,peso; char v1,v2; struct nodo *t; z=(struct nodo *)malloc(sizeof(struct nodo)); z->sig=z; for (i=0; i<V; i++) a[i]=z; for (i=0; i<A; i++) { cout <<”\n" <<v1<<v2<<peso; x=v1-'A'; y=v2-'A'; t=(struct nodo *)malloc(sizeof(struct nodo)); t->v=y; t->p=peso; t->sig=a[x]; a[x]=t; t=(struct nodo *)malloc(sizeof(struct nodo)); t->v=x; t->p=peso; t->sig=a[y]; a[y]=t; } } En este caso el espacio ocupado es O(V + A), muy distinto del necesario en la matriz de adyacencia, que era de O(V2). La representación por listas de adyacencia, por tanto, será más adecuada para grafos dispersos. Hay que tener en cuenta un aspecto importante y es que la implementación con listas enlazadas determina fuertemente el tratamiento del grafo posterior. Como se puede ver en el código, los nodos se van añadiendo a las listas según se leen las aristas, por lo que nos encontramos que un mismo grafo con un orden distinto de las aristas en la entrada producirá listas de adyacencia diferentes y por ello el orden en que los nodos se procesen variará. Una consecuencia de esto es que si un problema tiene varias soluciones la primera que se encuentre dependerá de la entrada dada. Podría presentarse el caso de tener varias soluciones y tener que mostrarlas siguiendo un determinado orden. Ante una situación así podría ser muy conveniente modificar la forma de meter los nodos en la lista (por ejemplo, hacerlo al final y no al principio, o incluso

Page 185: 301305 Estructura de Datos

185

UNIVERSIDAD NACIONAL ABIERTA Y A DISTANCIA – UNAD ESCUELA DE CIENCIAS BÁSICAS TECNOLOGÍA E INGENIERÍA CONTENIDO DIDÁCTICO DEL CURSO: 301305 – ESTRUCTURA DE DATOS

insertarlo en una posición adecuada), de manera que el algoritmo mismo diera las soluciones ya ordenadas”10. Al igual que la matriz de adyacencia, las listas de adyacencias también presentan algunas ventajas y desventajas. Ventajas de las listas de adyacencia La lista de adyacencia requiere un espacio proporcional a la suma del número de vértices, más el número de enlaces (arcos). Por otro lado hace buen uso de la memoria. Se utiliza bastante cuando el número de enlaces es mucho menor que O(n2). Desventaja de las listas de adyacencia La representación con listas de adyacencia es que pueden llevar un tiempo O(n) determinar si existe un arco del vértice i al vértice j, ya que pueden haber O(n) vértices en la lista de adyacencia. Para el vértice i.

Lección 15: Exploración de grafos A la hora de explorar un grafo, nos encontramos con dos métodos distintos. Ambos conducen al mismo destino (la exploración de todos los vértices o hasta que se encuentra uno determinado), si bien el orden en que éstos son "visitados" decide radicalmente el tiempo de ejecución de un algoritmo, como se verá posteriormente. En primer lugar, una forma sencilla de recorrer los vértices es mediante una función recursiva, lo que se denomina búsqueda en profundidad. La sustitución de la recursión (cuya base es la estructura de datos pila) mientras que el segundo método de búsqueda o recorrido, la búsqueda en amplitud o anchura lo proporciona una cola.

10 Tomado de: http://www.algoritmia.net/articles.php?id=18

Page 186: 301305 Estructura de Datos

186

UNIVERSIDAD NACIONAL ABIERTA Y A DISTANCIA – UNAD ESCUELA DE CIENCIAS BÁSICAS TECNOLOGÍA E INGENIERÍA CONTENIDO DIDÁCTICO DEL CURSO: 301305 – ESTRUCTURA DE DATOS

Figura 88 Representación grafica de un grafo

Fuente: http://www.algoritmia.net/articles.php?id=18 Suponiendo que el orden en que están almacenados los nodos en la estructura de datos correspondiente es A-B-C-D-E-F... (el orden alfabético), se tiene que el orden que seguiría el es destacable que el nodo D es el último en explorarse en la búsqueda en profundidad pese a ser adyacente al nodo de origen, es decir el nodo A. Esto es debido a que primero se explora la rama del nodo C, que también conduce al nodo D. En este ejemplo hay que tener en cuenta que es fundamental el orden en que los nodos están almacenados en las estructuras de datos. Si, por ejemplo, el nodo D estuviera antes que el C, en la búsqueda en profundidad se tomaría primero la rama del D (con lo que el último en visitarse sería el C), y en la búsqueda en anchura se exploraría antes el H que el G. El recorrido en profundidad sería el siguiente: A-B-E-I-F-C-G-J-K-H-D En un recorrido en anchura el orden sería, por contra: A-B-C-D-E-G-H-I-J-K-F

Búsqueda en profundidad Se implementa de forma recursiva, aunque también puede realizarse con una pila. Se utiliza un array val para almacenar el orden en que fueron explorados los vértices. Para ello se incrementa una variable global id (inicializada a 0) cada vez que se visita un nuevo vértice y se almacena id en la entrada del array val correspondiente al vértice que se está explorando. La siguiente función realiza un máximo de V (el número total de vértices) llamadas a la función visitar, que implementamos aquí en sus dos variantes: representación por matriz de adyacencia y por listas de adyacencia.

Page 187: 301305 Estructura de Datos

187

UNIVERSIDAD NACIONAL ABIERTA Y A DISTANCIA – UNAD ESCUELA DE CIENCIAS BÁSICAS TECNOLOGÍA E INGENIERÍA CONTENIDO DIDÁCTICO DEL CURSO: 301305 – ESTRUCTURA DE DATOS

int id=0; int val[V]; void buscar() { int k; for (k=1; k<=V; k++) val[k]=0; for (k=1; k<=V; k++) if (val[k]==0) visitar(k); } void visitar(int k) // matriz de adyacencia { int t; val[k]=++id; for (t=1; t<=V; t++) if (a[k][t] && val[t]==0) visitar(t); } void visitar(int k) // listas de adyacencia { struct nodo *t; val[k]=++id; for (t=a[k]; t!=z; t=t->sig) if (val[t->v]==0) visitar(t->v); } El resultado es que el array val contendrá en su i-ésima entrada el orden en el que el vértice i-ésimo fue explorado. Es decir, si tenemos un grafo con cuatro nodos y fueron explorados en el orden 3-1-2-4, el array val quedará como sigue: val[1]=2; // el primer nodo fue visto en segundo lugar val[2]=3; // el segundo nodo fue visto en tercer lugar val[3]=1; // etc. val[4]=4; Una modificación que puede resultar especialmente útil es la creación de un array "inverso" al array val que contenga los datos anteriores "al revés". Esto es, un array en el que la entrada i-ésima contiene el vértice que se exploró en iésimo lugar. Basta modificar la línea val[k]=++id; // sustituyéndola por val[++id]=k; Para el orden de exploración de ejemplo anterior los valores serían los siguientes: val[1]=3; val[2]=1;

Page 188: 301305 Estructura de Datos

188

UNIVERSIDAD NACIONAL ABIERTA Y A DISTANCIA – UNAD ESCUELA DE CIENCIAS BÁSICAS TECNOLOGÍA E INGENIERÍA CONTENIDO DIDÁCTICO DEL CURSO: 301305 – ESTRUCTURA DE DATOS

val[3]=2; val[4]=4;

Búsqueda en amplitud o anchura La diferencia fundamental respecto a la búsqueda en profundidad es el cambio de estructura de datos: una cola en lugar de una pila. En esta implementación, la función del array val y la variable id es la misma que en el método anterior. struct tcola *cola; void visitar(int k) // listas de adyacencia { struct nodo *t; encolar(&cola,k); while (!vacia(cola)) { desencolar(&cola,&k); val[k]=++id; for (t=a[k]; t!=z; t=t->sig) { if (val[t->v]==0) { encolar(&cola,t->v); val[t->v]=-1; } } } } Fin del programa”11

Aunque las estructuras de datos no lineales también se pueden implementar por medio de apuntadores, el código que se presenta corresponde a la implementación por medi de arreglos.

11 Tomado de: http://www.algoritmia.net/articles.php?id=18 consultado en Junio 10 de 2009

Page 189: 301305 Estructura de Datos

189

UNIVERSIDAD NACIONAL ABIERTA Y A DISTANCIA – UNAD ESCUELA DE CIENCIAS BÁSICAS TECNOLOGÍA E INGENIERÍA CONTENIDO DIDÁCTICO DEL CURSO: 301305 – ESTRUCTURA DE DATOS

Actividades de Autoevaluación de la Unidad 3

Ejercicio 1. Especificar una función que calcule la frontera de un árbol general, donde por frontera se entiende la lista formada por los elementos almacenados en las hojas del árbol tomados de izquierda a derecha. Ejercicio 2. Implementar un programa para la especificación de árboles con las operaciones siguientes: • Calcular la talla del árbol, es decir, el número de nodos de la rama más larga. • Calcular el número de nodos. • Calcular el número de hojas. • calcular el grado del árbol. Ejercicio 3. Implementar un árbol binario de nivel 3 que permita ingresar números en tiempo de ejecición, por medio de un menú de opciones que visualice en cada recorrido (Inorden, preorden y posorden). Ejercicio 4. Implemente el funcionamiento de un árbol binario haciendo uso del modo grafico de C, donde se gestionen los tres recorridos y se muestre la grafica. Ejercicio 5. Desarrollar un programa que reconstruya un árbol binario a partir de las dos listas que son sus árboles izquierdo y derecho respectivamente, se debe ingresar la raíz y con estos datos imprimir los tres recorridos en Preorden e Inorden y Postorden. Ejercicio 6. Escribir un programa que ordene una lista de elementos distintos utilizando como estructura auxiliar un árbol binario de búsqueda. Ejercicio 7. Implemente un árbol binario por medio del entorno gráfico de C++, de tal manera que se pueda gestionar la teoría de un árbol binario (Creación y visualización del árbol, al igual que los tres recorridos Inorden, Preorden, Posorden, altura del árbol, el grado). Ejercicio 8. Implemente un grafo por medio del entorno gráfico de C++, de tal manera que se pueda gestionar la teoría de grafos (Creación y visualización del grafo, al igual que imprima los dos recorridos en profundidad y en amplitud).

Page 190: 301305 Estructura de Datos

190

UNIVERSIDAD NACIONAL ABIERTA Y A DISTANCIA – UNAD ESCUELA DE CIENCIAS BÁSICAS TECNOLOGÍA E INGENIERÍA CONTENIDO DIDÁCTICO DEL CURSO: 301305 – ESTRUCTURA DE DATOS

Fuentes Documentales de la Unidad 3 AGUILAR, Luis (2003). Fundamentos de programación, algoritmos, estructura de datos y Objetos, Tercera edición. España: McGRAW-HILL. AGUILAR, Luis (200). Programación en C++, Algoritmos, estructura de datos y Objetos. España: McGRAW-HILL. AGUILAR, Luis (2003). Fundamentos de programación, algoritmos, estructura de datos y Objetos Tercera edición. España: McGRAW-HILL. AGUILAR Luis, ZAHONERO Martínez (2004). Algoritmos y Estructuras de Datos. Una perspectiva en C. Madrid-España: McGraw-Hill. ARCEO B, Frida y Otro (1999). Estrategias Decentes Para un Aprendizaje Significativo. Mexico D,F: McGRAW-HILL. BROOKSHEAR, J. Glenn (1995). Introducción a las ciencias de la Computación (Cuarta Edicón). Edición Española: Addison-Wesley Iberoamericana. DEYTEL Y DEYTEL(1999). Como programa C++. Segunda Edición. Mexico D.F: Prentice Hall. McGRAW-HILL. FARREL, Joyce (2000). Introducción a la programación lógica y diseño. Mexico D.F: Thomson. KENNETH C, Louden (2004). Lenguajes de programación. Segunda edición. MexicoD.F: Thomson. Salvador, Pozo (2002). Estructuras Dinámicas de datos- Árboles. Consultado en Octubre de 2008 en http://c.conclase.net/edd/index.php?cap=006. ESPINOZA, David (2004). Curso básico de Algoritmia. Consultado en Octubre, 24 de 2008 en http://www.geocities.com/david_ees/Algoritmia/curso.htm. CACERES, Abdiel (2005). Estructuras de datos en C++. Consultado en Febrero 25 de 2009 en http://computacion.cs.cinvestav.mx/~acaceres/courses/estDatosCPP/

ALGORITMIA.NET (2003). Grafos. Consultado en Noviembre de 2008 en http://www.algoritmia.net/articles.php?id=18.

Page 191: 301305 Estructura de Datos

191

UNIVERSIDAD NACIONAL ABIERTA Y A DISTANCIA – UNAD ESCUELA DE CIENCIAS BÁSICAS TECNOLOGÍA E INGENIERÍA CONTENIDO DIDÁCTICO DEL CURSO: 301305 – ESTRUCTURA DE DATOS

CASTILLO, Lenin (2008). Árboles binarios de búsqueda (ABB). Consultado en Mayo 2 de 2009 en http://ldcastillo.wordpress.com/tema-5-arboles-binarios-de-busqueda-abb/. PARDO, Pilar (2008). Teoría de Grafos.Consultado en Julio 10 de 2009 en http://www.slideshare.net/pilypardo/grafos-1407276.