19189723 estructura-de-datos-programacion-facil

210
1 Estructura de Datos UNIDAD 1: Análisis de Algoritmos Concepto Complejidad Algoritmos La resolución práctica de un problema exige por una parte un algoritmo o método de resolución y por otra un programa o codificación de aquel en un ordenador real. Ambos componentes tienen su importancia, pero la del algoritmo es absolutamente esencial, mientras que la codificación puede muchas veces pasar a nivel de anécdota. A efectos prácticos o ingenieriles, nos deben preocupar los recursos físicos necesarios para que un programa se ejecute. Aunque puede haber muchos parámetros, los mas usuales son el tiempo de ejecución y la cantidad de memoria (espacio). Ocurre con frecuencia que ambos parametros están resolver en T segundos y/o con M bytes de memoria? En lo que sigue nos centramos casi siempre en el parametro tiempo de ejecución, si bien las ideas desarrolladas son fácilmente aplicables a otro tipo de recursos. Para cada problema determinaremos un medida N de su tamaño (por fijados por otras razones y se plantea la pregunta inversa: ¿cual es el tamano del mayor problema que puedo número de datos) e intentaremos hallar respuestas en función de dicho N. El concepto exacto que mide N depende de la naturaleza del problema. Así, para un vector se suele utizar como N su longitud; para una matriz, el número de elementos que la componen; para un grafo, puede ser el número de nodos (a veces es mas importante considerar el número de arcos, dependiendo del tipo de problema a resolver), en un archivo se suele usar el número de registros, etc. Es imposible dar una regla general, pues cada problema tiene su propia lógica de costo. Tiempo de Ejecución Una medida que suele ser útil conocer es el tiempo de ejecución de un programa en función de N, lo que denominaremos T(N). Esta función se puede medir físicamente (ejecutando el programa, reloj en mano), o calcularse sobre el código contando instrucciones a ejecutar y multiplicando por el tiempo requerido por cada instrucción. Así, un trozo sencillo de programa como:

Upload: dariana-acuariogv

Post on 13-Jun-2015

340 views

Category:

Documents


0 download

TRANSCRIPT

Page 1: 19189723 estructura-de-datos-programacion-facil

1

Estructura de Datos

UNIDAD 1: Análisis de Algoritmos Concepto Complejidad Algoritmos La resolución práctica de un problema exige por una parte un algoritmo o método de resolución y por otra un programa o codificación de aquel en un ordenador real. Ambos componentes tienen su importancia, pero la del algoritmo es absolutamente esencial, mientras que la codificación puede muchas veces pasar a nivel de anécdota. A efectos prácticos o ingenieriles, nos deben preocupar los recursos físicos necesarios para que un programa se ejecute. Aunque puede haber muchos parámetros, los mas usuales son el tiempo de ejecución y la cantidad de memoria (espacio). Ocurre con frecuencia que ambos parametros están resolver en T segundos y/o con M bytes de memoria? En lo que sigue nos centramos casi siempre en el parametro tiempo de ejecución, si bien las ideas desarrolladas son fácilmente aplicables a otro tipo de recursos. Para cada problema determinaremos un medida N de su tamaño (por fijados por otras razones y se plantea la pregunta inversa: ¿cual es el tamano del mayor problema que puedo número de datos) e intentaremos hallar respuestas en función de dicho N. El concepto exacto que mide N depende de la naturaleza del problema. Así, para un vector se suele utizar como N su longitud; para una matriz, el número de elementos que la componen; para un grafo, puede ser el número de nodos (a veces es mas importante considerar el número de arcos, dependiendo del tipo de problema a resolver), en un archivo se suele usar el número de registros, etc. Es imposible dar una regla general, pues cada problema tiene su propia lógica de costo. Tiempo de Ejecución Una medida que suele ser útil conocer es el tiempo de ejecución de un programa en función de N, lo que denominaremos T(N). Esta función se puede medir físicamente (ejecutando el programa, reloj en mano), o calcularse sobre el código contando instrucciones a ejecutar y multiplicando por el tiempo requerido por cada instrucción. Así, un trozo sencillo de programa como:

Page 2: 19189723 estructura-de-datos-programacion-facil

2

S1; for (int i= 0; i < N; i++) S2; Requiere T(N)= t1 + t2*N Siendo t1 el tiempo que lleve ejecutar la serie “S1” de sentencias, y t2 el que lleve la serie “S2”. Prácticamente todos los programas reales incluyen alguna sentencia condicional, haciendo que las sentencias efectivamente ejecutadas dependan de los datos concretos que se le presenten. Esto hace que más que un valor T (N) debamos hablar de un rango de valores

Tmin (N) ⇐ T(N) ⇐ Tmax(N) Los extremos son habitualmente conocidos como: “caso peor” y “caso mejor”. Entre ambos se hallara algun “caso promedio” o más frecuente. Cualquier fórmula T(N) incluye referencias al parámetro N y a una serie de constantes “Ti” que dependen de factores externos al algoritmo como pueden ser la calidad del código generado por el compilador y la velocidad de ejecución de instrucciones del ordenador que lo ejecuta. Dado que es fácil cambiar de compilador y que la potencia de los ordenadores crece a un ritmo vertiginoso (en la actualidad, se duplica anualmente), intentaremos analizar los algoritmos con algun nivel de independencia de estos factores; es decir, buscaremos estimaciones generales ampliamente válidas. UNIDAD 2: Manejo de Memoria Memoria Estática

La forma más fácil de almacenar el contenido de una variable en memoria en tiempo de ejecución es en memoria estática o permanente a lo largo de toda la ejecución del programa.

No todos los objetos (variables) pueden ser almacenados estáticamente.

Para que un objeto pueda ser almacenado en memoria estática su tamaño (número de bytes necesarios para su almacenamiento) ha de ser conocido en tiempo de compilación, como consecuencia de esta condición no podrán almacenarse en memoria estática:

Los objetos correspondientes a procedimientos o funciones recursivas, ya que en tiempo de compilación no se sabe el número de variables que serán necesarias.

Las estructuras dinámicas de datos tales como listas, árboles, etc. ya que el número de elementos que las forman no es conocido hasta que el programa se ejecuta.

Las técnicas de asignación de memoria estática son sencillas.

Page 3: 19189723 estructura-de-datos-programacion-facil

3

A partir de una posición señalada por un puntero de referencia se aloja el objeto X, y se avanza el puntero tantos bytes como sean necesarios para almacenar el objeto X.

La asignación de memoria puede hacerse en tiempo de compilación y los objetos están vigentes desde que comienza la ejecución del programa hasta que termina.

En los lenguajes que permiten la existencia de subprogramas, y siempre que todos los objetos de estos subprogramas puedan almacenarse estáticamente se aloja en la memoria estática un registro de activación correspondiente a cada uno de los subprogramas.

Estos registros de activación contendrán las variables locales, parámetros formales y valor devuelto por la función.

Dentro de cada registro de activación las variables locales se organizan secuencialmente. Existe un solo registro de activación para cada procedimiento y por tanto no están permitidas las llamadas recursivas. El proceso que se sigue cuando un procedimiento p llama a otro q es el siguiente:

1. p evalúa los parámetros de llamada, en caso de que se trate de expresiones complejas,

usando para ello una zona de memoria temporal para el almacenamiento intermedio. Por ejemplos, sí la llamada a q es q((3*5)+(2*2),7) las operaciones previas a la llamada propiamente dicha en código máquina han de realizarse sobre alguna zona de memoria temporal. (En algún momento debe haber una zona de memoria que contenga el valor intermedio 15, y el valor intermedio 4 para sumarlos a continuación). En caso de utilización de memoria estática ésta zona de temporales puede ser común a todo el programa, ya que su tamaño puede deducirse en tiempo de compilación.

2. q inicializa sus variables y comienza su ejecución.

Dado que las variables están permanentemente en memoria es fácil implementar la propiedad de que conserven o no su contenido para cada nueva llamada Memoria Dinámica

¿Qué es la memoria dinámica?

Supongamos que nuestro programa debe manipular estructuras de datos de longitud desconocida. Un ejemplo simple podría ser el de un programa que lee las líneas de un archivo y las ordena. Por tanto, deberemos leer un número indeterminado de líneas, y tras leer la última, ordenarlas. Una manera de manejar ese ``número indeterminado'', sería declarar una constante MAX_LINEAS, darle un valor vergonzosamente grande, y declarar un array de tamaño MAX_LINEAS. Esto, obviamente, es muy ineficiente (y feo). Nuestro programa no sólo quedaría limitado por ese valor máximo, sino que además gastaría esa enorme cantidad de memoria para procesar hasta el más pequeño de los ficheros.

La solución consiste en utilizar memoria dinámica. La memoria dinámica es un espacio de almacenamiento que se solicita en tiempo de ejecución. De esa manera, a medida que el proceso va necesitando espacio para más líneas, va solicitando más memoria al sistema operativo para guardarlas. El medio para manejar la memoria que otorga el sistema operativo, es el puntero, puesto que no

Page 4: 19189723 estructura-de-datos-programacion-facil

4

podemos saber en tiempo de compilación dónde nos dará huecos el sistema operativo (en la memoria de nuestro PC). Memoria Dinámica.

Sobre el tratamiento de memoria, GLib dispone de una serie de instrucciones que sustituyen a las ya conocidas por todos malloc, free, etc. y, siguiendo con el modo de llamar a las funciones en GLib, las funciones que sustituyen a las ya mencionadas son g_malloc y g_free. Reserva de memoria.

La función g_malloc posibilita la reserva de una zona de memoria, con un número de bytes que le pasemos como parámetro. Además, también existe una función similar llamada g_malloc0 que, no sólo reserva una zona de memoria, sino que, además, llena esa zona de memoria con ceros, lo cual nos puede beneficiar si se necesita un zona de memoria totalmente limpia.

gpointer g_malloc (gulong numero_de_bytes ); gpointer g_malloc0 (gulong numero_de_bytes );

Existe otro conjunto de funciones que nos permiten reservar memoria de una forma parecida a

cómo se hace en los lenguajes orientados a objetos. Liberación de memoria.

Cuando se hace una reserva de memoria con g_malloc y, en un momento dado, el uso de esa memoria no tiene sentido, es el momento de liberar esa memoria. Y el sustituto de free es g_free que, básicamente, funciona igual que la anteriormente mencionada.

void g_free (gpointer memoria_reservada ); Realojamiento de memoria

En determinadas ocasiones, sobre todo cuando se utilizan estructuras de datos dinámicas, es necesario ajustar el tamaño de una zona de memoria (ya sea para hacerla más grande o más pequeña). Para eso, GLib ofrece la función g_realloc, que recibe un puntero a memoria que apunta a una región que es la que será acomodada al nuevo tamaño y devuelve el puntero a la nueva zona de memoria. El anterior puntero es liberado y no se debería utilizar más:

gpointer g_realloc (gpointer memoria_reservada , gulong numero_de_bytes ); Asignación dinámica

El proceso de compactación del punto anterior es una instancia particular del problema de asignación de memoria dinámica, el cual es el cómo satisfacer una necesidad de tamaño n con una lista de huecos libres. Existen muchas soluciones para el problema. El conjunto de huecos es analizado para determinar cuál hueco es el más indicado para asignarse. Las estrategias más comunes para asignar algún hueco de la tabla son:

Page 5: 19189723 estructura-de-datos-programacion-facil

5

Primer ajuste: Consiste en asignar el primer hueco con capacidad suficiente. La búsqueda puede iniciar ya sea al inicio o al final del conjunto de huecos o en donde terminó la última búsqueda. La búsqueda termina al encontrar un hueco lo suficientemente grande.

Mejor ajuste: Busca asignar el espacio más pequeño de los espacios con capacidad suficiente. La búsqueda se debe de realizar en toda la tabla, a menos que la tabla esté ordenada por tamaño. Esta estrategia produce el menor desperdicio de memoria posible.

Peor ajuste: Asigna el hueco más grande. Una vez más, se debe de buscar en toda la tabla de huecos a menos que esté organizada por tamaño. Esta estrategia produce los huecos de sobra más grandes, los cuales pudieran ser de más uso si llegan procesos de tamaño mediano que quepan en ellos.

Se ha demostrado mediante simulacros que tanto el primer y el mejor ajuste son mejores que el peor ajuste en cuanto a minimizar tanto el tiempo del almacenamiento. Ni el primer o el mejor ajuste es claramente el mejor en términos de uso de espacio, pero por lo general el primer ajuste es más rápido. Unidad 3: Estructura datos pilas lifo Definición:

Son aquellas que solo tiene 2 operaciones, Push(Inserción) y Pop(Eliminación) la cual solo se puede efectuar por un extremo llamado Top. Sin Embargo se le pueden aplicar todas las operaciónes al igual que a las listas. 1.- Recorrido Definición: Ya que las pilas son LIFO(Last in - First Out) el Recorrido se hace sacando el ultimo dato que se inserto hasta que no encuentre ningún otro. Detalle: Apuntador toma el Top, después ve si la condición cumple para efectuar un Ciclo mientras Apuntador sea diferente de Nulo, si cumple lo que hace es que despliega el contenido de la Pila(Pila[Apuntador]), después Apuntador se le resta 1. Este proceso se repite hasta que Apuntador sea igual Nulo(Cuando llega a este punto la Pila ya fue Recorrida). Algoritmo:

Recorrido(Pila, Top) Apuntador ←- Top Repetir mientras Apuntador &ne; Nulo Imprimir Pila[Apuntador] Apuntador ←- Apuntador - 1 Fin del ciclo Salir

Diagrama:

Page 6: 19189723 estructura-de-datos-programacion-facil

6

Corrida:

Push Definición: Push es simplemente el método por el cual va agregando un Dato nuevo a la Pila tomando en cuenta la Capacidad Máxima (Max) de almacenar un dato. Detalle: Compara en un principio el Top con Max, si la condición no cumple es imposible insertar mas datos a la Pila, de otra forma lo que hace es Incrementar el valor de Top, y copia el valor de Elemento en Pila[Top]. De esta forma el dato ya esta insertado. Algoritmo:

Push(Pila, Top, Max, Elemento) Si Top &ne; Max Top ←- Top + 1 Pila[Top] ←- Elemento Si no: Imprimir “Pila Llena” Salir

Diagrama:

Page 7: 19189723 estructura-de-datos-programacion-facil

7

Corrida:

Pop Definición: Pop es simplemente el método por el cual va sacando el ultimo Dato de la Pila, basándose únicamente en el Top. Detalle: Compara para determinar si la pila esta vacio, de otra forma lo que hace es Imprimir el valor de Pila[Top] (Que es el dato que esta apunto de Eliminar) y enseguida a Top le resta 1, de esta forma el dato ya no existe. Algoritmo:

Pop(Pila, Top) Si Top &ne; Nulo Imprimir Pila[Top] Top ←- Top - 1 Si no: Imprimir “Pila Vacía” Salir

Diagrama:

Page 8: 19189723 estructura-de-datos-programacion-facil

8

Corrida:

Búsqueda Definición: Este método usa el recorrido para encontrar Elemento y desplegar un mensaje si la búsqueda es exitosa. Detalle: El algoritmo compara para determinar si la Pila tiene algún dato, si no simplemente desplegara Lista Vacía y saldrá. De otra manera hará un Recorrido y comparara con cada uno de los Datos de la Pila hasta encontrar el dato que desea buscar. Si lo encuentra desplegara “El Dato fue encontrado” de otra manera “El Dato no se encontró”. Algoritmo:

Busqueda(Pila, Top, Elemento) Si Top &ne; Nulo Apuntador ←- Top Repetir mientras Apuntador &ne; Nulo Si Pila[Apuntador] = Elemento Imprimir “El Dato fue encontrado” y Salir Apuntador ←- Apuntador - 1 Fin del ciclo

Page 9: 19189723 estructura-de-datos-programacion-facil

9

Imprimir “El Dato no se encontró” Si no: Imprimir “Pila Vacía” Salir

Diagrama:

Corrida:

Eliminacion Definición: Este método busca un Dato dentro de la pila y lo elimina. Detalle: El algoritmo compara para determinar si la Pila tiene algún dato, si no simplemente desplegara Pila Vacía y saldrá. De otra manera hará un Recorrido y comparara con cada uno de los Datos de la Pila hasta encontrar el dato que desea eliminar, mientras hace esto copia cada uno de los datos a un arreglo Temp para cuando encuentre el Dato regresar esos valores a la Pila. Si lo encuentra desplegara “Eliminado el Dato” y le restara 1 a Top, de otra manera “El Dato no encontrado”. Algoritmo:

Borrar(Pila, Temp, Top, Elemento) Si Top &ne; Nulo

Page 10: 19189723 estructura-de-datos-programacion-facil

10

Apuntador1 ←- Top Repetir mientras Apuntador1 &ne; Nulo Si Pila[Apuntador1] = Elemento Imprimir “Eliminando el Dato…” Repetir mientras Apuntador2 &ne; Nulo Pila[Apuntador1]=Temp[Apuntador2] Fin del ciclo Top ←- Top - 1 y Salir Si No: Temp[Apuntador2+ ←- Pila[Apuntador1] Apuntador1 ←- Apuntador1 - 1 Apuntador2 ←- Apuntador2 + 1 Fin del ciclo Imprimir “Dato no encontrado” Si no: Imprimir “Pila Vacía” Salir

Diagrama:

Corrida:

Page 11: 19189723 estructura-de-datos-programacion-facil

11

Programa click here PROGRAMACION PILAS ESTRUCTURAS DE DATOS **#include <stdio.h>** #include <conio.h> #include <string.h> #include <iomanip.h> #include <iostream.h> class Alumno { private: int Pila[10],Top,Max; char Pila1[10][10]; public: Alumno() { int i,j; char Nulo[2]=" "; Max=9; Top=-1; for(i=1;i<9;i++) { Pila[i]=0; strcpy(Pila1[i],Nulo); }

Page 12: 19189723 estructura-de-datos-programacion-facil

12

} void Push(char Elem[10]) { if(Top!=Max) { Top++; strcpy(Pila1[Top],Elem); } else cout<<"Pila Llena"<<endl; } void Push(int Elem) { if(Top!=Max) { Top++; Pila[Top]=Elem; } else cout<<"Pila Llena"<<endl; } void Push(float Elem) { if(Top!=Max)

Page 13: 19189723 estructura-de-datos-programacion-facil

13

{ Top++; Pila[Top]=Elem; } else cout<<"Pila Llena"<<endl; } void Push(double Elem) { if(Top!=Max) { Top++; Pila[Top]=Elem; } else cout<<"Pila Llena"<<endl; } void Pop(void) { if(Top!=-1) { cout<<"Sacando el Dato: "<<Pila[Top]; Top--;

Page 14: 19189723 estructura-de-datos-programacion-facil

14

} else cout<<"Pila Vacia... Imposible Eliminar"<<endl; } void Recorrido(void) { if(Top!=-1) for(int i=Top;i!=-1;i--) cout<<Pila[i]<<endl; else cout<<"Pila Vacia..."; } void Busqueda(char Elem[10]) { for(int i=Top;i!=-1;i--) if((strcmp(Elem,Pila1[i]))==0) { cout<<"Dato "<<Pila1[i]<<" encontrado..."<<endl; return; } cout<<"Dato no encontrado..."<<endl; } void Busqueda(int Elem) {

Page 15: 19189723 estructura-de-datos-programacion-facil

15

for(int i=Top;i!=-1;i--) if(Elem==Pila[i]) { cout<<"Dato "<<Pila[i]<<" encontrado..."<<endl; return; } cout<<"Dato no encontrado..."<<endl; } void Busqueda(float Elem) { for(int i=Top;i!=-1;i--) if(Elem==Pila[i]) { cout<<"Dato "<<Pila[i]<<" encontrado..."<<endl; return; } cout<<"Dato no encontrado..."<<endl; } void Busqueda(double Elem) { for(int i=Top;i!=-1;i--) if(Elem==Pila[i]) {

Page 16: 19189723 estructura-de-datos-programacion-facil

16

cout<<"Dato "<<Pila[i]<<" encontrado..."<<endl; return; } cout<<"Dato no encontrado..."<<endl; } void Borrar(char Elem[10]) { char Temp[10][10]; int i=0,j=Top; if(Top==-1) { cout<<"Pila Vacia... Imposible Eliminar..."; return; } while(j!=-1) { if((strcmp(Elem,Pila1[j]))==0) { cout<<"Dato Eliminado..."; for(i--;i!=-1;j++,i--) strcpy(Pila1[j],Temp[i]); Top--; return; }

Page 17: 19189723 estructura-de-datos-programacion-facil

17

else { strcpy(Temp[i],Pila1[j]); i++; j--; } } cout<<"Dato no encontrado... Imposible Eliminar..."; return; } void Borrar(int Elem) { int Temp[10],i=0,j=Top; if(Top==-1) { cout<<"Pila Vacia... Imposible Eliminar..."; return; } while(j!=-1) { if(Elem==Pila[j]) { cout<<"Dato Eliminado...";

Page 18: 19189723 estructura-de-datos-programacion-facil

18

for(i--;i!=-1;j++,i--) Pila[j]=Temp[i]; Top--; return; } else { Temp[i]=Pila[j]; i++; j--; } } cout<<"Dato no encontrado... Imposible Eliminar..."; return; } void Borrar(float Elem) { int Temp[10],i=0,j=Top; if(Top==-1) { cout<<"Pila Vacia... Imposible Eliminar..."; return; } while(j!=-1)

Page 19: 19189723 estructura-de-datos-programacion-facil

19

{ if(Elem==Pila[j]) { cout<<"Dato Eliminado..."; for(i--;i!=-1;j++,i--) Pila[j]=Temp[i]; Top--; return; } else { Temp[i]=Pila[j]; i++; j--; } } cout<<"Dato no encontrado... Imposible Eliminar..."; return; } void Borrar(double Elem) { int Temp[10],i=0,j=Top; if(Top==-1)

Page 20: 19189723 estructura-de-datos-programacion-facil

20

{ cout<<"Pila Vacia... Imposible Eliminar..."; return; } while(j!=-1) { if(Elem==Pila[j]) { cout<<"Dato Eliminado..."; for(i--;i!=-1;j++,i--) Pila[j]=Temp[i]; Top--; return; } else { Temp[i]=Pila[j]; i++; j--; } } cout<<"Dato no encontrado... Imposible Eliminar..."; return; }

Page 21: 19189723 estructura-de-datos-programacion-facil

21

}tec; main() { int res,op=0; while(op!=6) { clrscr(); cout<<"\n1) Recorrido\n2) Busqueda\n3) Push\n4) Pop\n5) Eliminar un Dato\n6) Salir"<<endl; gotoxy(1,1); cout<<"Que deseas hacer?: "; cin>>op; gotoxy(1,10); switch (op) { case 1: tec.Recorrido(); break; case 2: cout<<"Que Numero deseas buscar?"<<endl; cin>>res; tec.Busqueda(res); break; case 3:

Page 22: 19189723 estructura-de-datos-programacion-facil

22

cout<<"Que Numero quieres Insertar?"<<endl; cin>>res; tec.Push(res); break; case 4: tec.Pop(); break; case 5: cout<<"Que Numero deseas eliminar?"<<endl; cin>>res; tec.Borrar(res); break; case 6: cout<<"Salida..."; break; default: cout<<"Opcion Erronea"<<endl; break; } getch(); } } UNIDAD 3: Colas FIFO Definición:

Page 23: 19189723 estructura-de-datos-programacion-facil

23

Son aquellas que solo tiene 2 operaciones, Push(Inserción) y Pop(Eliminación). Push solo se puede efectuar por un extremo llamado Frente y Pop por el extremo Llamado Final. Sin Embargo se le pueden aplicar todas las operación al igual que a las listas. Recorrido Definición: Ya que las colas son FIFO(First in - First Out) el Recorrido se hace sacando el primer dato que se inserto hasta que llegue al extremo llamado Final. Detalle: En un principio se compara para saber si tiene algún dato en la Cola, si no es así desplegara “Cola Vacía…”. De otra forma compara si Frente es mayor o igual a Final, de esta forma simplemente hace un Recorrido lineal como los anteriores. De otra forma usar Max como bandera para saber cuando empezar a contar de 0 a Final (Ya que sabemos que el Frente después del nodo Final). Algoritmo: Recorrido(Cola, Frente, Final, Max) Si Frente ≠ Nulo Si Frente ≤ Final, entonces: Apuntador <-- Frente Repetir mientras Apuntador ≤ Final Imprimir Cola[Apuntador] Apuntador <-- Apuntador + 1 Fin del ciclo Si no, si Frente > Final, entonces: Apuntador <-- Frente Repetir mientras Apuntador ≠ Final Si Apuntador > Max, entonces: Apuntador <-- 0 Imprimir Cola[Apuntador] Apuntador <-- Apuntador + 1 Fin del ciclo Si no:

Page 24: 19189723 estructura-de-datos-programacion-facil

24

Imprimir "Cola Vacía" Salir Diagrama:

Corrida:

Push Definición: Push es simplemente el método por el cual va agregando un Dato nuevo a la Cola tomando en cuenta el Tamaño Máximo de Capacidad (Max), el Frente y el Final de la Cola. Detalle: Primer nos aseguramos que la Cola no este Llena, para que de esta manera sea capaz de insertar un Elemento nuevo. Si no desplegara Cola Llena. Después compara para determinar las posiciones de Frente y Final y de esta manera poder moverlo con libertad. Ya que determina los valores de Frente y Final, nos Indica que Cola[Final] tomara el valor de Elemento. Algoritmo: Push(Cola, Frente, Final, Max, Elemento)

Page 25: 19189723 estructura-de-datos-programacion-facil

25

Si Frente = 0 y Final =9, o si Frente = (Final + 1) Imprimir "Cola Llena" y Salir Si Frente = Nulo Frente <-- 0 Final <-- 0 Si no, si Final = Max Final <-- 0 Si no: Final <-- Final + 1 Cola[Final] = Elemento Salir Diagrama:

Corrida:

Page 26: 19189723 estructura-de-datos-programacion-facil

26

Pop Definición: Pop es simplemente el método por el cual va sacando el primer Dato de la Cola (esto se comprueba ya que las Colas son FIFO), para esto toma en cuenta el Frente. Detalle: Compara para determinar si la cola esta vacía, de otra forma lo que hace es Imprimir “Eliminando el Dato…”. Después se hacen una series de comparaciones para determinar la nueva posición de Frente, de esa forma el Dato que existía en Frente es Eliminado. Algoritmo: Pop(Cola, Frente, Final, Max) Si Frente ≠ Nulo Imprimir "Eliminado el Dato..." Si Frente = Final Frente = Nulo Final = Nulo Si no, si Frente = Max Frente = 0 Si no: Frente <-- Frente + 1 Si no: Imprimir "Cola Vacía" Salir

Page 27: 19189723 estructura-de-datos-programacion-facil

27

Diagrama:

Corrida:

Búsqueda Definición: Este método usa el recorrido para encontrar Elemento y desplegar un mensaje si la búsqueda es exitosa. Detalle: El algoritmo usa básicamente la misma estructura del Recorrido, la única diferencia es que compara cada uno de los Datos con Elemento, de esta forma se da cuenta si este Dato existe en la Cola. Algoritmo: Busqueda(Cola, Frente, Fin, Max, Elemento) Si Frente ≠ Nulo Si Frente ≤ Final, entonces: Apuntador <-- Frente Repetir mientras Apuntador ≤ Final

Page 28: 19189723 estructura-de-datos-programacion-facil

28

Si Elemento = Cola[Apuntador] Imprimir "Dato encontrado..." y Salir Apuntador <-- Apuntador + 1 Fin del ciclo Si no, si Frente > Final, entonces: Apuntador <-- Frente Repetir mientras Apuntador ≠ Final Si Apuntador > Max, entonces: Apuntador <-- 0 Si Elemento = Cola[Apuntador] Imprimir "Dato encontrado..." y Salir Apuntador <-- Apuntador + 1 Fin del ciclo Imprimir "Dato no encontrado..." Si no: Imprimir "Cola Vacía" Salir Diagrama:

Page 29: 19189723 estructura-de-datos-programacion-facil

29

Corrida:

Eliminacion Definición: Este método busca un Dato dentro de la cola y lo elimina. Detalle: Este Método es la mezcla de todos en uno, Recorrido, Búsqueda, Pop y Push. Debido que a busca el Dato haciendo un Recorrido, y en el proceso copia todos los Datos que no son en un Arreglo Temp, para después meterlos a la Cola original, esto lo hace hasta encontrar el dato deseado que posteriormente lo Elimina. Diagrama:

Page 30: 19189723 estructura-de-datos-programacion-facil

30

Corrida:

Programa click here PROGRAMACION COLAS ESTRUCTURA DE DATOS #include <stdio.h> #include <conio.h> #include <string.h> #include <iomanip.h> #include <iostream.h> class Alumno { private:

Page 31: 19189723 estructura-de-datos-programacion-facil

31

int Cola[10],Frente,Final,Max; char Cola1[10][10]; public: Alumno() { int i,j; char Nulo[2]=" "; Frente=-1; Final=-1; Max=9; for(i=1;i<9;i++) { Cola[i]=0; strcpy(Cola1[i],Nulo); } } void Push(char Elem[10]) { if((Frente==0&&Final==9)||(Frente==(Final+1))) { cout<<"Cola Llena"<<endl; return; } if(Frente==-1)

Page 32: 19189723 estructura-de-datos-programacion-facil

32

{ Frente=0; Final=0; } else if(Final==Max) Final=0; else Final++; strcpy(Cola1[Final],Elem); } void Push(int Elem) { if((Frente==0&&Final==9)||(Frente==(Final+1))) { cout<<"Cola Llena"<<endl; return; } if(Frente==-1) { Frente=0; Final=0; } else if(Final==Max)

Page 33: 19189723 estructura-de-datos-programacion-facil

33

Final=0; else Final++; Cola[Final]=Elem; } void Push(float Elem) { if((Frente==0&&Final==9)||(Frente==(Final+1))) { cout<<"Cola Llena"<<endl; return; } if(Frente==-1) { Frente=0; Final=0; } else if(Final==Max) Final=0; else Final++; Cola[Final]=Elem; } void Push(double Elem)

Page 34: 19189723 estructura-de-datos-programacion-facil

34

{ if((Frente==0&&Final==9)||(Frente==(Final+1))) { cout<<"Cola Llena"<<endl; return; } if(Frente==-1) { Frente=0; Final=0; } else if(Final==Max) Final=0; else Final++; Cola[Final]=Elem; } void Pop(void) { if(Frente!=-1) { cout<<"Elmininado el Dato: "<<Cola[Frente]; if(Frente==Final)

Page 35: 19189723 estructura-de-datos-programacion-facil

35

{ Frente=-1; Final=-1; } else if(Frente==Max) Frente=0; else Frente++; } else cout<<"Cola Vacia... Imposible Eliminar"<<endl; } void Recorrido(void) { int i; if(Frente!=-1) { if(Frente<=Final) for(i=Frente;i<=Final;i++) cout<<Cola[i]<<endl; else if(Frente>Final) for(i=Frente;i!=Final;i++) { if(i>Max)

Page 36: 19189723 estructura-de-datos-programacion-facil

36

i=0; cout<<Cola[i]<<endl; } } else cout<<"Cola Vacia..."; } void Busqueda(char Elem[10]) { int i; if(Frente!=-1) { if(Frente<=Final) for(i=Frente;i<=Final;i++) if((strcmp(Elem,Cola1[i]))==0) { cout<<"Dato "<<Cola1[i]<<" encontrado..."<<endl; return; } else if(Frente>Final) for(i=Frente;i!=Final;i++) { if(i>Max)

Page 37: 19189723 estructura-de-datos-programacion-facil

37

i=0; if((strcmp(Elem,Cola1[i]))==0) { cout<<"Dato "<<Cola1[i]<<" encontrado..."<<endl; return; } } } else cout<<"Dato no encontrado..."; } void Busqueda(int Elem) { int i; if(Frente!=-1) { if(Frente<=Final) for(i=Frente;i<=Final;i++) if(Elem==Cola[i]) { cout<<"Dato "<<Cola[i]<<" encontrado..."<<endl; return; } else if(Frente>Final)

Page 38: 19189723 estructura-de-datos-programacion-facil

38

for(i=Frente;i!=Final;i++) { if(i>Max) i=0; if(Elem==Cola[i]) { cout<<"Dato "<<Cola[i]<<" encontrado..."<<endl; return; } } } else cout<<"Dato no encontrado..."; } void Busqueda(float Elem) { int i; if(Frente!=-1) { if(Frente<=Final) for(i=Frente;i<=Final;i++) if(Elem==Cola[i]) {

Page 39: 19189723 estructura-de-datos-programacion-facil

39

cout<<"Dato "<<Cola[i]<<" encontrado..."<<endl; return; } else if(Frente>Final) for(i=Frente;i!=Final;i++) { if(i>Max) i=0; if(Elem==Cola[i]) { cout<<"Dato "<<Cola[i]<<" encontrado..."<<endl; return; } } } else cout<<"Dato no encontrado..."; } void Busqueda(double Elem) { int i; if(Frente!=-1) { if(Frente<=Final)

Page 40: 19189723 estructura-de-datos-programacion-facil

40

for(i=Frente;i<=Final;i++) if(Elem==Cola[i]) { cout<<"Dato "<<Cola[i]<<" encontrado..."<<endl; return; } else if(Frente>Final) for(i=Frente;i!=Final;i++) { if(i>Max) i=0; if(Elem==Cola[i]) { cout<<"Dato "<<Cola[i]<<" encontrado..."<<endl; return; } } } else cout<<"Dato no encontrado..."; } void Borrar(char Elem[10]) {

Page 41: 19189723 estructura-de-datos-programacion-facil

41

char Temp[10][10]; int i,j; if(Frente!=-1) { if(Frente<=Final) for(j=0,i=Frente;i<=Final;i++,j++) { if((strcmp(Elem,Cola1[i]))==0) { cout<<"Eliminado el Dato "<<Cola1[i]<<endl; if(Frente==Final) { Frente=-1; Final=-1; return; } else if(Frente==Max) Frente=0; else Frente++; for(j--,i=Frente;j!=-1;i++,j--) strcpy(Cola1[i],Temp[j]); return; }

Page 42: 19189723 estructura-de-datos-programacion-facil

42

strcpy(Temp[j],Cola1[i]); } else if(Frente>Final) for(j=0,i=Frente;i!=Final;i++,j++) { if(i>Max) i=0; if((strcmp(Elem,Cola1[i]))==0) { cout<<"Eliminado el Dato "<<Cola1[i]<<endl; if(Frente==Max) Frente=0; else Frente++; for(j--,i=Frente;j!=-1;i++,j--) { if(i>Max) i=0; strcpy(Cola1[i],Temp[j]); } return; } strcpy(Temp[j],Cola1[i]);

Page 43: 19189723 estructura-de-datos-programacion-facil

43

} cout<<"Dato no Encontrado..."; } else cout<<"Cola Vacia... Imposible Eliminar..."; } void Borrar(int Elem) { int Temp[10],i,j; if(Frente!=-1) { if(Frente<=Final) for(j=0,i=Frente;i<=Final;i++,j++) { if(Elem==Cola[i]) { cout<<"Eliminado el Dato "<<Cola[i]<<endl; if(Frente==Final) { Frente=-1; Final=-1; return; } else if(Frente==Max)

Page 44: 19189723 estructura-de-datos-programacion-facil

44

Frente=0; else Frente++; for(j--,i=Frente;j!=-1;i++,j--) Cola[i]=Temp[j]; return; } Temp[j]=Cola[i]; } else if(Frente>Final) for(j=0,i=Frente;i!=Final;i++,j++) { if(i>Max) i=0; if(Elem==Cola[i]) { cout<<"Eliminado el Dato "<<Cola[i]<<endl; if(Frente==Max) Frente=0; else Frente++; for(j--,i=Frente;j!=-1;i++,j--) {

Page 45: 19189723 estructura-de-datos-programacion-facil

45

if(i>Max) i=0; Cola[i]=Temp[j]; } return; } Temp[j]=Cola[i]; } cout<<"Dato no Encontrado..."; } else cout<<"Cola Vacia... Imposible Eliminar..."; } void Borrar(float Elem) { int Temp[10],i,j; if(Frente!=-1) { if(Frente<=Final) for(j=0,i=Frente;i<=Final;i++,j++) { if(Elem==Cola[i]) { cout<<"Eliminado el Dato "<<Cola[i]<<endl;

Page 46: 19189723 estructura-de-datos-programacion-facil

46

if(Frente==Final) { Frente=-1; Final=-1; return; } else if(Frente==Max) Frente=0; else Frente++; for(j--,i=Frente;j!=-1;i++,j--) Cola[i]=Temp[j]; return; } Temp[j]=Cola[i]; } else if(Frente>Final) for(j=0,i=Frente;i!=Final;i++,j++) { if(i>Max) i=0; if(Elem==Cola[i]) {

Page 47: 19189723 estructura-de-datos-programacion-facil

47

cout<<"Eliminado el Dato "<<Cola[i]<<endl; if(Frente==Max) Frente=0; else Frente++; for(j--,i=Frente;j!=-1;i++,j--) { if(i>Max) i=0; Cola[i]=Temp[j]; } return; } Temp[j]=Cola[i]; } cout<<"Dato no Encontrado..."; } else cout<<"Cola Vacia... Imposible Eliminar..."; } void Borrar(double Elem) { int Temp[10],i,j; if(Frente!=-1)

Page 48: 19189723 estructura-de-datos-programacion-facil

48

{ if(Frente<=Final) for(j=0,i=Frente;i<=Final;i++,j++) { if(Elem==Cola[i]) { cout<<"Eliminado el Dato "<<Cola[i]<<endl; if(Frente==Final) { Frente=-1; Final=-1; return; } else if(Frente==Max) Frente=0; else Frente++; for(j--,i=Frente;j!=-1;i++,j--) Cola[i]=Temp[j]; return; } Temp[j]=Cola[i]; }

Page 49: 19189723 estructura-de-datos-programacion-facil

49

else if(Frente>Final) for(j=0,i=Frente;i!=Final;i++,j++) { if(i>Max) i=0; if(Elem==Cola[i]) { cout<<"Eliminado el Dato "<<Cola[i]<<endl; if(Frente==Max) Frente=0; else Frente++; for(j--,i=Frente;j!=-1;i++,j--) { if(i>Max) i=0; Cola[i]=Temp[j]; } return; } Temp[j]=Cola[i]; } cout<<"Dato no Encontrado..."; }

Page 50: 19189723 estructura-de-datos-programacion-facil

50

else cout<<"Cola Vacia... Imposible Eliminar..."; } }tec; main() { int res,op=0; while(op!=6) { clrscr(); cout<<"\n1) Recorrido\n2) Busqueda\n3) Push\n4) Pop\n5) Eliminar un Dato\n6) Salir"<<endl; gotoxy(1,1); cout<<"Que deseas hacer?: "; cin>>op; gotoxy(1,10); switch (op) { case 1: tec.Recorrido(); break; case 2: cout<<"Que Numero deseas buscar?"<<endl; cin>>res;

Page 51: 19189723 estructura-de-datos-programacion-facil

51

tec.Busqueda(res); break; case 3: cout<<"Que Numero quieres Insertar?"<<endl; cin>>res; tec.Push(res); break; case 4: tec.Pop(); break; case 5: cout<<"Que Numero deseas eliminar?"<<endl; cin>>res; tec.Borrar(res); break; case 6: cout<<"Salida..."; break; default: cout<<"Opcion Erronea"<<endl; break; } getch(); }

Page 52: 19189723 estructura-de-datos-programacion-facil

52

} Unidad 3 : Listas Enlazadas Recorrido Definición: Recorrido simplemente despliega los datos almacenados en el arreglo Info, con ayuda de un segundo arreglo llamado Indice el cual guarda el orden en el que encuentran enlazados cada uno de los datos. Explicación: Apuntador toma el valor de Inicio, después ve si la condición cumple para efectuar un Ciclo mientras Apuntador sea diferente de 0, si cumple lo que hace es que despliega la Info[Apuntador], después Apuntador toma el valor de Indice[Apuntador] (El cual nos indica el siguiente nodo que sigue en la lista) y hace esto hasta que Apuntador sea igual a 0 (Cuando llega a este punto a llegado al fin de la Lista Enlazada). Algoritmo:

Recorrido(Inicio, Info, Indice) Apuntador ←- Inicio Repetir mientras Apuntador ≠ Nill Imprimir Info[Apuntador] Apuntador ←- Indice[Apuntador] Fin del ciclo Salir

Diagrama:

Programa: #include <conio.h> #include <iostream.h>

Page 53: 19189723 estructura-de-datos-programacion-facil

53

void Recorrido(char Info[8][2],int Indice[8],int Inicio,int Disp); void main() { char Info[8][2]={{"G"},{"I"},{" "},{"T"},{"O"},{"A"}, {" "},{"T"}}; int Indice[8]={5,7,6,1,-999,3,-999,4}; int Inicio=0,Disp=2; cout<<"El Recorrido es:\n"; Recorrido(Info,Indice,Inicio,Disp); getch(); } void Recorrido(char Info[8][2],int Indice[8],int Inicio,int Disp) { int Apuntador=Inicio; while(Apuntador!=-999) { cout<<Info[Apuntador]; Apuntador=Indice[Apuntador]; } } Corrida:

Page 54: 19189723 estructura-de-datos-programacion-facil

54

Búsqueda Definición: La Búsqueda su objetivo es encontrar un dato en el arreglo Info, si lo encuentra lo desplegara en la pantalla, si no lo encuentra no desplegara nada ya que el dato no se encuentra en el arreglo Info. Explicación: Apuntador toma el valor de Inicio, después ve si la condición cumple para efectuar un Ciclo mientras Apuntador sea diferente de 0, si cumple lo que hace a continuación es la comparación de Elemento (El dato que vamos a buscar) con Info[Apuntador], cuando lo encuentre lo despliega y sale del método. Si no, regresa el valor de Apuntador para así saber que no se encontró el dato. Algoritmo:

Recorrido(Inicio, Info, Indice, Elemento) Apuntador ←- Inicio Repetir mientras Apuntador ≠ Nill Si Elemento = Info[Apuntador] entonces: Imprimir Info[Apuntador] Regresa Apuntador Apuntador ←- Indice[Apuntador] Fin del ciclo Regresar Apuntador

Diagrama:

Programa:

Page 55: 19189723 estructura-de-datos-programacion-facil

55

#include <conio.h> #include <iostream.h> int Busqueda(int Info[8],int Indice[8],int Inicio,int Disp,int Elemento); void main() { int Info[8]={12,10,0,9,5,3,0,20}; int Indice[8]={5,7,6,1,-999,3,-999,4}; int Inicio=0,Disp=2,Elemento,Res; cout<<"Que Numero deseas buscar?"; cin>>Elemento; Res=Busqueda(Info,Indice,Inicio,Disp,Elemento); if(Res==-999) cout<<"Dato No Encontrado..."; getch(); } int Busqueda(int Info[8],int Indice[8],int Inicio,int Disp,int Elemento) { int Apuntador=Inicio; while(Apuntador!=-999) { if(Elemento==Info[Apuntador]) { cout<<"Numero "<<Info[Apuntador]<<" encontrado..."; return Apuntador; } Apuntador=Indice[Apuntador]; } return Apuntador; } CORRIDA:

Page 56: 19189723 estructura-de-datos-programacion-facil

56

Inserción al Principio Definición: La Inserción al Principio básicamente busca si existe algún lugar disponible en el arreglo Info y lo agrega como primer Nodo si es que es posible. Explicación: Hace una comparación para ver si es posible insertar otro Elemento al arreglo Info, para esto checa si Disp es Diferente de Nulo. Si no cumple con la condición se desplegar “Sobre Carga” ya que no se puede insertar un Nuevo Elemento. Si es cierto Apuntador toma el valor de Inicio, Disp cambia a Indice[Disp] ya que el primer Disp tomara el valor del Nuevo Elemento, después de esto solo copia la información de Elemento al arreglo Info en la posición que guarda Apuntador, Indice[Apuntador] toma el valor de Inicio y finalmente Inicio toma el valor de Apuntador. Algoritmo:

InsPr(Inicio, Disp, Info, Indice, Elemento) Si Disp ≠ Nill entonces: Apuntador ←- Disp Disp ←- Indice[Disp] Info*Apuntador+ ←- Elemento Indice*Apuntador+ ←- Inicio Inicio ←- Apuntador Si no: Imprimir “Sobre Carga” Salir

Diagrama:

Page 57: 19189723 estructura-de-datos-programacion-facil

57

Programa: #include <conio.h> #include <iostream.h> void Recorrido(int Info[8],int Indice[8],int Inicio,int Disp); void InsPr(int Info[8],int Indice[8],int Inicio,int Disp,int Elemento); void main() { int Info[8]={12,10,0,9,5,3,0,20}; int Indice[8]={5,7,6,1,-999,3,-999,4}; int Inicio=0,Disp=2,Elemento,Res; cout<<"Lista Original\n"; Recorrido(Info,Indice,Inicio,Disp); cout<<"Que Numero deseas Insertar?"; cin>>Elemento; InsPr(Info,Indice,Inicio,Disp,Elemento); getch(); } void Recorrido(int Info[8],int Indice[8],int Inicio,int Disp) { int Apuntador=Inicio; while(Apuntador!=-999) { cout<<Info[Apuntador]<<endl; Apuntador=Indice[Apuntador]; } }

Page 58: 19189723 estructura-de-datos-programacion-facil

58

void InsPr(int Info[8],int Indice[8],int Inicio,int Disp,int Elemento) { if(Disp!=-999) { int Apuntador=Disp; Disp=Indice[Disp]; Info[Apuntador]=Elemento; Indice[Apuntador]=Inicio; Inicio=Apuntador; Recorrido(Info,Indice,Inicio,Disp); } else cout<<"Overflow..."; } CORRIDA:

Inserción después de UN Nodo Determinado Definición: La Inserción después de un Nodo Determinado básicamente hace lo mismo que la inserción al principio, la única diferencia es que este recibe la posición del nodo en la que será Insertada. Este Algoritmo se usa para Inserción Ordenada que mas adelante explicaremos. Explicación: Primero confirma que sea posible insertar el Dato, si no es posible solo desplegara “Sobre Carga”. Si es posible insertar un dato nuevo lo posiciona en la primer posición Disponible en el arreglo Info, después

Page 59: 19189723 estructura-de-datos-programacion-facil

59

compara la Nueva Posición (Npos) que le mandamos con Nill si cumple la condición el dato es insertado en la primer posición, de otra forma se posicionara en la posición que guarde Npos. Algoritmo:

InsNd(Inicio, Disp, Info, Indice, Elemento, Npos) Si Disp ≠ Nill entonces: Apuntador ←- Disp Disp ←- Indice[Disp] Info *Apuntador+ ←- Elemento Si Npos = Nill entonces: Indice*Apuntador+ ←- Inicio Inicio ←- Apuntador Si no: Indice*Apuntador+ ←- Indice[Npos] Indice*Npos+ ←- Apuntador Si no: Imprimir “Sobre Carga” Salir

Inserción Ordenada Definición: La Inserción Ordenada busca la posición en donde será Insertado el Elemento y la posición anterior donde será Insertado, después de encontrar la posición en la que será Insertado el Elemento nos regresa ese valor y lo mandamos al método de la Inserción después de un Nodo. Explicación: En esta ocasión usaremos dos variables para determinar la posición deseada, comparamos si Inicio es igual a Nill ó si Elemento es menor al dato que se encuentra en Info[Inicio], si alguna de las dos cumple regresamos Nill, de esta manera Indicamos que el Elemento será el primero de todo el Arreglo Info, si no es así Temp tomara el valor de Inicio y Temp2 de la posición que le sigue a Inicio. Hace un ciclo hasta encontrar la posición en donde se insertara el Nuevo Elemento y va moviéndose de posición con las variables Temp y Temp2 para así determinar que posición debe de regresar. Algoritmo:

InsOrd(Inicio, Info, Indice, Elemento) Si Inicio = Nill ó Elemento < Info[Inicio] entonces: Regresar Nill Temp ←- Inicio Temp2 ←- Indice[Inicio] Repetir mientras Temp2 ≠ Nill Si Elemento < Info[Temp2] Regresar Temp Temp ←- Temp2 Temp2 ←- Indice[Temp2] Regresar Temp

Diagrama:

Page 60: 19189723 estructura-de-datos-programacion-facil

60

Programa: #include <conio.h> #include <iostream.h> int InsOrd(int Info[8],int Indice[8],int Inicio,int Elemento); void Recorrido(int Info[8],int Indice[8],int Inicio,int Disp); void InsNd(int Info[8],int Indice[8],int Inicio,int Disp, int Elemento, int Npos); void main() { int Info[8]={12,10,0,9,5,3,0,20}; int Indice[8]={5,7,6,1,-999,3,-999,4}; int Inicio=0,Disp=2,Elemento,Res; cout<<"Lista Original\n"; Recorrido(Info,Indice,Inicio,Disp); cout<<"Que Numero deseas Insertar?"; cin>>Elemento;

Page 61: 19189723 estructura-de-datos-programacion-facil

61

Res=InsOrd(Info,Indice,Inicio,Elemento); InsNd(Info,Indice,Inicio,Disp,Elemento,Res); getch(); } void Recorrido(int Info[8],int Indice[8],int Inicio,int Disp) { int Apuntador=Inicio; while(Apuntador!=-999) { cout<<Info[Apuntador]<<endl; Apuntador=Indice[Apuntador]; } } void InsNd(int Info[8],int Indice[8],int Inicio,int Disp, int Elemento, int Npos) { if(Disp!=-999) { int Apuntador=Disp; Disp=Indice[Disp]; Info[Apuntador]=Elemento; if(Npos==-999) { Indice[Apuntador]=Inicio; Inicio=Apuntador;

Page 62: 19189723 estructura-de-datos-programacion-facil

62

} else { Indice[Apuntador]=Indice[Npos]; Indice[Npos]=Apuntador; } Recorrido(Info,Indice,Inicio,Disp); } else cout<<"Overflow..."; } int InsOrd(int Info[8],int Indice[8],int Inicio,int Elemento) { int Temp=-999,Temp2; if(Inicio==Temp||Elemento<Info[Inicio]) return Temp; Temp=Inicio; Temp2=Indice[Inicio]; while(Temp2!=-999) { if(Elemento<Info[Temp2]) return Temp; Temp=Temp2;

Page 63: 19189723 estructura-de-datos-programacion-facil

63

Temp2=Indice[Temp2]; } return Temp; } CORRIDA:

Eliminación por Búsqueda Definición: La Eliminación simplemente cambia los nodos para que el dato que se desea eliminar sea el primer disponible, de esta forma ya no estará en el Arreglo de Info. Explicación: Lo primero que hace es ver si existe algún dato en la lista para eliminar, si Inicio es igual a Nill entonces solo desplegara “Imposible Eliminar”. De otra formas cambiar de Posición en Posición hasta encontrar el Elemento que sea desea Eliminar con ayudar de dos variables que guardan la Posición actual y la anterior en donde se encuentre el dato. Ya que lo encuentra cambia ese dato como la primera posición Disponible y lo apunta al siguiente nodo disponible. Si no encuentra el dato simplemente desplegara “Dato no encontrado” Algoritmo:

EliBusq(Inicio, Info, Indice, Elemento) Temp ←- Inicio Si Temp = Nill Imprimir “Lista Vacia… Imposible Eliminar” y Retornar Repetir mientras Temp ≠ Nill Si Elemento = Info[Temp] entonces: Si Temp = Inicio entonces: Inicio ←- Indice[Inicio] Si no: Indice*Temp2+ ←- Indice[Temp] Indice[Temp] ß Disp Disp ←- Temp Recorrido(Inicio, Info, Indice) y Retornar

Page 64: 19189723 estructura-de-datos-programacion-facil

64

Si no: Temp2 ←- Temp Temp ←- Indice[Temp] Imprimir “Dato no encontrado… Imposible Eliminar” y Retornar

Diagrama:

Programa: #include <conio.h> #include <iostream.h> void Recorrido(int Info[8],int Indice[8],int Inicio,int Disp); void EliBusq(int Info[8],int Indice[8],int Inicio,int Disp,int Elemento); void main() { int Info[8]={12,10,0,9,5,3,0,20}; int Indice[8]={5,7,6,1,-999,3,-999,4}; int Inicio=0,Disp=2,Elemento,Res; cout<<"Lista Original\n"; Recorrido(Info,Indice,Inicio,Disp); cout<<"Que Numero deseas Eliminar?";

Page 65: 19189723 estructura-de-datos-programacion-facil

65

cin>>Elemento; EliBusq(Info,Indice,Inicio,Disp,Elemento); getch(); } void Recorrido(int Info[8],int Indice[8],int Inicio,int Disp) { int Apuntador=Inicio; while(Apuntador!=-999) { cout<<Info[Apuntador]<<endl; Apuntador=Indice[Apuntador]; } } void EliBusq(int Info[8],int Indice[8],int Inicio,int Disp,int Elemento) { int Temp=Inicio,Temp2; if(Temp==-999) { cout<<"Lista Vacia... Imposible Eliminar"; return; } while(Temp!=-999) {

Page 66: 19189723 estructura-de-datos-programacion-facil

66

if(Elemento==Info[Temp]) { if(Temp==Inicio) Inicio=Indice[Inicio]; else Indice[Temp2]=Indice[Temp]; Indice[Temp]=Disp; Disp=Temp; Recorrido(Info,Indice,Inicio,Disp); return; } else { Temp2=Temp; Temp=Indice[Temp]; } } cout<<"Dato no encontrado... Imposible Eliminar"; return; } CORRIDA:

Page 67: 19189723 estructura-de-datos-programacion-facil

67

Prgrama clik here PROGRAMACION LISTAS ENLAZADAS ESTRUCTURA DE DATOS #include <stdio.h> #include <conio.h> #include <iomanip.h> #include <iostream.h> class Alumno { private: char Nombre[10][30]; int N_control[10],Edad[10],Indice1[10],Indice2[10],Inicio,Fin,Disp; public: //Constructor Alumno() { int i,j; Inicio=0; Fin=0; Disp=1;

Page 68: 19189723 estructura-de-datos-programacion-facil

68

Indice1[Inicio]=-999; Indice2[Fin]=-999; for(i=1,j=2;i<9;i++,j++) Indice1[i]=j; Indice1[9]=-999; } //Funcion de Recorrido void Recorrido(int op) { int i=0,Temp; if(op==1) { Temp=Indice1[Inicio]; if(Temp!=-999) { cout<<"Numero de Control"<<setw(19)<<"Nombre del Alumno"<<setw(5)<<"Edad"<<endl; while(Temp!=-999) { if(i==(int(Edad[Inicio]/2))) { N_control[Inicio]=N_control[i]; strcpy(Nombre[Inicio],Nombre[i]); }

Page 69: 19189723 estructura-de-datos-programacion-facil

69

cout<<setw(9)<<N_control[Temp]<<setw(22)<<Nombre[Temp]<<setw(9)<<Edad[Temp]<<endl; Temp=Indice1[Temp]; i++; } } else cout<<"Lista Vacia..."; } if(op==2) { Temp=Fin; if(Edad[Inicio]!=0) { cout<<"Numero de Control"<<setw(19)<<"Nombre del Alumno"<<setw(5)<<"Edad"<<endl; while(Temp!=-999&&i<Edad[Inicio]) { if(i==(int(Edad[Inicio]/2))) { N_control[Inicio]=N_control[i]; strcpy(Nombre[Inicio],Nombre[i]); } cout<<setw(9)<<N_control[Temp]<<setw(22)<<Nombre[Temp]<<setw(9)<<Edad[Temp]<<endl; Temp=Indice2[Temp]; i++;

Page 70: 19189723 estructura-de-datos-programacion-facil

70

} } else cout<<"Lista Vacia..."; } } //Funcion de Busqueda Sobrecargada para un Dato Entero int Busqueda(int Elem) { if(Elem<N_control[Inicio]) { int Temp=Indice1[Inicio]; while(Temp!=-999) { if(Elem==N_control[Temp]) { gotoxy(1,10); cout<<"Numero de Control"<<setw(19)<<"Nombre del Alumno"<<setw(5)<<"Edad"<<endl; cout<<setw(9)<<N_control[Temp]<<setw(22)<<Nombre[Temp]<<setw(9)<<Edad[Temp]<<endl; return Temp; } else Temp=Indice1[Temp];

Page 71: 19189723 estructura-de-datos-programacion-facil

71

} } else { int Temp=Fin; while(Temp!=-999) { if(Elem==N_control[Temp]) { gotoxy(1,10); cout<<"Numero de Control"<<setw(19)<<"Nombre del Alumno"<<setw(5)<<"Edad"<<endl; cout<<setw(9)<<N_control[Temp]<<setw(22)<<Nombre[Temp]<<setw(9)<<Edad[Temp]<<endl; return Temp; } else Temp=Indice2[Temp]; } } return -999; } //Funcion de Busqueda Sobrecargada para una Cadena de Caracteres int Busqueda(char Elem[30]) { if((strcmp(Elem,Nombre[Inicio]))<0)

Page 72: 19189723 estructura-de-datos-programacion-facil

72

{ int Temp=Indice1[Inicio]; while(Temp!=-999) { if((strcmp(Elem,Nombre[Temp]))==0) { gotoxy(1,10); cout<<"Numero de Control"<<setw(19)<<"Nombre del Alumno"<<setw(5)<<"Edad"<<endl; cout<<setw(9)<<N_control[Temp]<<setw(22)<<Nombre[Temp]<<setw(9)<<Edad[Temp]<<endl; return Temp; } else Temp=Indice1[Temp]; } } else { int Temp=Fin; while(Temp!=-999) { if((strcmp(Elem,Nombre[Temp]))==0) { gotoxy(1,10);

Page 73: 19189723 estructura-de-datos-programacion-facil

73

cout<<"Numero de Control"<<setw(19)<<"Nombre del Alumno"<<setw(5)<<"Edad"<<endl; cout<<setw(9)<<N_control[Temp]<<setw(22)<<Nombre[Temp]<<setw(9)<<Edad[Temp]<<endl; return Temp; } else Temp=Indice2[Temp]; } } return -999; } //Funcion Sobrecargada de Orden para un Dato Entero int Enca(int E_nc) { int Temp=Indice1[Inicio],Temp2; if(Temp==-999||E_nc<N_control[Temp]) return -999; Temp2=Indice1[Indice1[Inicio]]; while(Temp2!=-999) { if(E_nc<N_control[Temp2]) return Temp; Temp=Temp2; Temp2=Indice1[Temp2]; }

Page 74: 19189723 estructura-de-datos-programacion-facil

74

return Temp; } //Funcion Sobrecargada de Orden para una Cadena de Caracteres int Enca(char E_nom[30]) { int Temp=Indice1[Inicio],Temp2; if(Temp==-999) return -999; if((strcmp(E_nom,Nombre[Temp]))<0) return Temp; Temp2=Indice1[Indice1[Inicio]]; while(Temp2!=-999) { if((strcmp(E_nom,Nombre[Temp2]))<0) return Temp; Temp=Temp2; Temp2=Indice1[Temp2]; } return Temp; } //Funcion para la Insercion en un Lugar Determinado void InsLug(char E_nom[30],int E_nc,int E_edad,int Npos) {

Page 75: 19189723 estructura-de-datos-programacion-facil

75

if(Disp!=-999) { Edad[Inicio]++; int Temp=Disp; Disp=Indice1[Disp]; strcpy(Nombre[Temp],E_nom); N_control[Temp]=E_nc; Edad[Temp]=E_edad; if(Npos==-999) { Indice1[Temp]=Indice1[Inicio]; if(Indice2[Fin]==-999) { Indice2[Temp]=Fin; Fin=Temp; } else { Indice2[Temp]=Indice1[Inicio]; Indice2[Indice1[Inicio]]=Temp; } Indice1[Inicio]=Temp; } else

Page 76: 19189723 estructura-de-datos-programacion-facil

76

{ Indice1[Temp]=Indice1[Npos]; if(Fin==Npos) { Indice2[Temp]=Fin; Fin=Temp; } else { Indice2[Temp]=Npos; Indice2[Indice1[Npos]]=Temp; } Indice1[Npos]=Temp; } } else cout<<"Overflow..."<<endl; } //Funcion Sobrecargada para Borrar un Dato Entero void Borrar(int Elem) { int Temp2,Temp=Indice1[Inicio]; if(Temp==-999)

Page 77: 19189723 estructura-de-datos-programacion-facil

77

{ cout<<"Lista Vacia... Imposible Eliminar"; return; } while(Temp!=-999) { if(Elem==N_control[Temp]) { Edad[Inicio]--; if(Temp==Indice1[Inicio]) { Indice1[Inicio]=Indice1[Indice1[Inicio]]; Indice2[Indice1[Inicio]]=Inicio; } else if(Temp==Fin) { Indice1[Temp2]=Indice1[Temp]; Fin=Indice2[Fin]; } else { Indice1[Temp2]=Indice1[Temp]; Indice2[Indice1[Temp2]]=Temp2; }

Page 78: 19189723 estructura-de-datos-programacion-facil

78

Indice1[Temp]=Disp; Disp=Temp; return; } else { Temp2=Temp; Temp=Indice1[Temp]; } } cout<<"Dato no encontrado... Imposible Eliminar"; return; } //Funcion Sobrecargada para Borrar una Cadena de Caracteres void Borrar(char Elem[30]) { int Temp2,Temp=Indice1[Inicio]; if(Temp==Inicio) { cout<<"Lista Vacia... Imposible Eliminar"; return; } while(Temp!=Inicio)

Page 79: 19189723 estructura-de-datos-programacion-facil

79

{ if((strcmp(Elem,Nombre[Temp]))==0) { Edad[Inicio]--; if(Temp==Indice1[Inicio]) { Indice1[Inicio]=Indice1[Indice1[Inicio]]; Indice2[Indice1[Inicio]]=Inicio; } else if(Temp==Fin) { Indice1[Temp2]=Indice1[Temp]; Fin=Indice2[Fin]; } else { Indice1[Temp2]=Indice1[Temp]; Indice2[Indice1[Temp2]]=Temp2; } Indice1[Temp]=Disp; Disp=Temp; return; } else

Page 80: 19189723 estructura-de-datos-programacion-facil

80

{ Temp2=Temp; Temp=Indice1[Temp]; } } cout<<"Dato no encontrado... Imposible Eliminar"; return; } }tec; main() { int op=0,res; char inom[30]; int in_c,iedad; while(op!=6) { clrscr(); cout<<"\n1) Recorrido por Inicio\n2) Recorrido por Final\n3) Busqueda\n"; cout<<"4) Insercion\n5) Eliminar un Dato\n6) Salir"<<endl; gotoxy(1,1); cout<<"Que deseas hacer: "; cin>>op; gotoxy(1,10);

Page 81: 19189723 estructura-de-datos-programacion-facil

81

switch (op) { case 1: tec.Recorrido(1); break; case 2: tec.Recorrido(2); break; case 3: cout<<"Que Numero de Control deseas buscar?"<<endl; cin>>res; res=tec.Busqueda(res); if(res==-999) cout<<"Dato no encontrado"; break; case 4: cout<<"Que nombre quieres Insertar?"<<endl; gets(inom); cout<<"Cual es su Numero de Control?"<<endl; cin>>in_c; cout<<"Cual es su Edad?"<<endl; cin>>iedad; res=tec.Enca(in_c); tec.InsLug(inom,in_c,iedad,res);

Page 82: 19189723 estructura-de-datos-programacion-facil

82

break; case 5: cout<<"Que Numero de Control deseas eliminar?"<<endl; cin>>res; tec.Borrar(res); break; case 6: cout<<"Salida..."; break; default: cout<<"Opcion Erronea"<<endl; break; } getch(); } } Unidad 3: LISTAS CIRCULARES Recorrido Definición: Recorrido simplemente despliega los datos almacenados en el arreglo Info, con ayuda de un segundo arreglo llamado Indice el cual guarda el orden en el que encuentran enlazados cada uno de los datos. Detalle: Apuntador toma el valor de Indice[Inicio], después ve si la condición cumple para efectuar un Ciclo mientras Apuntador sea diferente de Inicio, si cumple lo que hace es que despliega la Info[Apuntador], después Apuntador toma el valor de Indice[Apuntador] (El cual nos indica el siguiente nodo que sigue en la lista) y hace esto hasta que Apuntador sea igual a Inicio (Cuando llega a este punto a llegado al fin de la Lista). Algoritmo:

Recorrido(Inicio, Info, Indice) Apuntador → Indice*Inicio+

Page 83: 19189723 estructura-de-datos-programacion-facil

83

Repetir mientras Apuntador ≠ Inicio Imprimir Info[Apuntador] Apuntador → Indice*Apuntador+ Fin del ciclo Salir

Diagrama:

Programa: #include <conio.h> #include <iostream.h> void Recorrido(char Info[8][2],int Indice[8],int Inicio,int Disp); void main() { char Info[8][2]={{" "},{"I"},{" "},{"T"},{"O"},{"A"}, {"G"},{"T"}}; int Indice[8]={6,7,-999,1,0,3,5,4}; int Inicio=0,Disp=2; cout<<"El Recorrido es:\n"; Recorrido(Info,Indice,Inicio,Disp);

Page 84: 19189723 estructura-de-datos-programacion-facil

84

getch(); } void Recorrido(char Info[8][2],int Indice[8],int Inicio,int Disp) { int Apuntador=Indice[Inicio]; while(Apuntador!=Inicio) { cout<<Info[Apuntador]; Apuntador=Indice[Apuntador]; } }

Búsqueda Definición: La Búsqueda su objetivo es encontrar un dato en el arreglo Info, si lo encuentra lo desplegara en la pantalla, si no lo encuentra no desplegara nada ya que el dato no se encuentra en el arreglo Info. Detalle: Apuntador toma el valor de Inicio, después ve si la condición cumple para efectuar un Ciclo mientras Apuntador sea diferente de 0, si cumple lo que hace a continuación es la comparación de Elemento (El dato que vamos a buscar) con Info[Apuntador], cuando lo encuentre lo despliega y sale del método. Si no, regresa el valor de Apuntador para así saber que no se encontró el dato. Algoritmo:

Recorrido(Inicio, Info, Indice, Elemento) Apuntador → Indice*Inicio+ Repetir mientras Apuntador ≠ Inicio Si Elemento = Info[Apuntador] entonces: Imprimir Info[Apuntador] Regresa Apuntador

Page 85: 19189723 estructura-de-datos-programacion-facil

85

Apuntador → Indice*Apuntador+ Fin del ciclo Regresar Apuntador

Diagrama:

Programa: #include <conio.h> #include <iostream.h> int Busqueda(int Info[8],int Indice[8],int Inicio,int Disp,int Elemento); void main() { int Info[8]={0,10,0,9,5,3,0,20}; int Indice[8]={5,7,6,1,0,3,-999,4}; int Inicio=0,Disp=2,Elemento,Res; cout<<"Que Numero deseas buscar?"; cin>>Elemento; Res=Busqueda(Info,Indice,Inicio,Disp,Elemento); if(Res==-999)

Page 86: 19189723 estructura-de-datos-programacion-facil

86

cout<<"Dato No Encontrado..."; getch(); } int Busqueda(int Info[8],int Indice[8],int Inicio,int Disp,int Elemento) { int Apuntador=Indice[Inicio]; while(Apuntador!=Inicio) { if(Elemento==Info[Apuntador]) { cout<<"Numero "<<Info[Apuntador]<<" encontrado..."; return Apuntador; } Apuntador=Indice[Apuntador]; } return Apuntador; }

Page 87: 19189723 estructura-de-datos-programacion-facil

87

Inserción al Principio Definición: La Inserción al Principio básicamente busca si existe algún lugar disponible en el arreglo Info y lo agrega como primer Nodo si es que es posible. Detalle: Hace una comparación para ver si es posible insertar otro Elemento al arreglo Info, para esto checa si Disp es Diferente de Nulo. Si no cumple con la condición se desplegar “Sobre Carga” ya que no se puede insertar un Nuevo Elemento. Si es cierto Apuntador toma el valor de Inicio, Disp cambia a Indice[Disp] ya que el primer Disp tomara el valor del Nuevo Elemento, después de esto solo copia la información de Elemento al arreglo Info en la posición que guarda Apuntador, Indice[Apuntador] toma el valor de Indice[Inicio] y finalmente Indice[Inicio] toma el valor de Apuntador. Algoritmo:

InsPr(Inicio, Disp, Info, Indice, Elemento) Si Disp ≠ Nill entonces: Apuntador → Disp Disp → Indice*Disp+ Info*Apuntador+ → Elemento Indice*Apuntador+ → Indice*Inicio+ Indice*Inicio+ → Apuntador Si no: Imprimir “Sobre Carga” Salir

Diagrama:

Page 88: 19189723 estructura-de-datos-programacion-facil

88

Programa: #include <conio.h> #include <iostream.h> void Recorrido(int Info[8],int Indice[8],int Inicio,int Disp); void InsPr(int Info[8],int Indice[8],int Inicio,int Disp,int Elemento); void main() { int Info[8]={0,10,0,9,5,3,0,20}; int Indice[8]={5,7,6,1,0,3,-999,4}; int Inicio=0,Disp=2,Elemento,Res; cout<<"Lista Original\n"; Recorrido(Info,Indice,Inicio,Disp); cout<<"Que Numero deseas Insertar?"; cin>>Elemento; InsPr(Info,Indice,Inicio,Disp,Elemento);

Page 89: 19189723 estructura-de-datos-programacion-facil

89

getch(); } void Recorrido(int Info[8],int Indice[8],int Inicio,int Disp) { int Apuntador=Indice[Inicio]; while(Apuntador!=Inicio) { cout<<Info[Apuntador]<<endl; Apuntador=Indice[Apuntador]; } } void InsPr(int Info[8],int Indice[8],int Inicio,int Disp,int Elemento) { if(Disp!=-999) { int Apuntador=Disp; Disp=Indice[Disp]; Info[Apuntador]=Elemento; Indice[Apuntador]=Indice[Inicio]; Indice[Inicio]=Apuntador; Recorrido(Info,Indice,Inicio,Disp); } else cout<<"Overflow...";

Page 90: 19189723 estructura-de-datos-programacion-facil

90

}

Inserción después de un Nodo Determinado Definición: La Inserción después de un Nodo Determinado básicamente hace lo mismo que la inserción al principio, la única diferencia es que este recibe la posición del nodo en la que será Insertada. Este Algoritmo se usa para Inserción Ordenada que mas adelante explicaremos. Detalle: Primero confirma que sea posible insertar el Dato, si no es posible solo desplegara “Sobre Carga”. Si es posible insertar un dato nuevo lo posiciona en la primer posición Disponible en el arreglo Info, después compara la Nueva Posición (Npos) que le mandamos con Nill si cumple la condición el dato es insertado en la primer posición, de otra forma se posicionara en la posición que guarde Npos. Algoritmo:

InsOrd(Inicio, Disp, Info, Indice, Elemento, Npos) Si Disp ≠ Nill entonces: Apuntador → Disp Disp → Indice*Disp+ Info *Apuntador+ → Elemento Si Npos = Nill entonces: Indice*Apuntador+ → Indice*Inicio+ Indice*Inicio+ → Apuntador Si no: Indice*Apuntador+ → Indice*Npos+

Page 91: 19189723 estructura-de-datos-programacion-facil

91

Indice*Npos+ → Apuntador Si no: Imprimir “Sobre Carga” Salir

Inserción Ordenada Definición: La Inserción Ordenada busca la posición en donde será Insertado el Elemento y la posición anterior donde será Insertado, después de encontrar la posición en la que será Insertado el Elemento nos regresa ese valor y lo mandamos al método de la Inserción después de un Nodo. Detalle:

En esta ocasión usaremos dos variables para determinar la posición deseada, comparamos si Indice[Inicio] es igual a Inicio ó si Elemento es menor al dato que se encuentra en Info[Inicio], si alguna de las dos cumple regresamos Nill, de esta manera Indicamos que el Elemento será el primero de todo el Arreglo Info, si no es así Temp tomara el valor de Inicio y Temp2 de la posición que le sigue a Inicio. Hace un ciclo hasta encontrar la posición en donde se insertara el Nuevo Elemento y va moviéndose de posición con las variables Temp y Temp2 para así determinar que posición debe de regresar. Algoritmo:

InsOrd(Inicio, Info, Indice, Elemento) Si Inicio = Indice[Inicio] ó Elemento < Info[Inicio] entonces: Regresar Nill Temp → Indice*Inicio+ Temp2 → Indice*Temp+ Repetir mientras Temp2 ≠ Inicio Si Elemento < Info[Temp2] Regresar Temp Temp → Temp2 Temp2 → Indice*Temp2+ Regresar Temp

Diagrama:

Page 92: 19189723 estructura-de-datos-programacion-facil

92

Programa: #include <stdio.h> #include <conio.h> #include <iostream.h> void Recorrido(char Info[8][10],int Indice[8],int Inicio,int Disp); void InsPr(char Info[8][10],int Indice[8],int Inicio,int Disp,char Elemento[10]); void InsOrd(char Info[8][10],int Indice[8],int Inicio,int Disp,char Elemento[10]); void main() { char Info[8][10]={{"Cabeza"},{"e"},{" "},{"c"},{"i"},{"a"},{" "},{"g"}}; char Elemento[10]; int Indice[8]={5,7,6,1,0,3,-999,4}; int Inicio=0,Disp=2,Res; cout<<"Lista Original\n"; Recorrido(Info,Indice,Inicio,Disp); cout<<"Que Numero deseas Insertar?";

Page 93: 19189723 estructura-de-datos-programacion-facil

93

gets(Elemento); InsOrd(Info,Indice,Inicio,Disp,Elemento); getch(); } void Recorrido(char Info[8][10],int Indice[8],int Inicio,int Disp) { int Apuntador=Indice[Inicio]; while(Apuntador!=Inicio) { cout<<Info[Apuntador]<<endl; Apuntador=Indice[Apuntador]; } } void InsPr(char Info[8][10],int Indice[8],int Inicio,int Disp,char Elemento[10]) { if(Disp!=-999) { strcpy(Info[Disp],Elemento); Indice[Disp]=Indice[Inicio]; Indice[Inicio]=Disp; Disp=Indice[Disp]; } Recorrido(Info,Indice,Inicio,Disp);

Page 94: 19189723 estructura-de-datos-programacion-facil

94

} void InsOrd(char Info[8][10],int Indice[8],int Inicio,int Disp,char Elemento[10]) { if(Inicio==Indice[Inicio]||(strcmp(Elemento,Info[Indice[Inicio]]))==0) { InsPr(Info,Indice,Inicio,Disp,Elemento); return; } int Temp=Indice[Inicio],Temp2=Indice[Temp]; while(Temp2!=Inicio) { if((strcmp(Elemento,Info[Temp2]))<0) break; Temp=Temp2; Temp2=Indice[Temp2]; } strcpy(Info[Disp],Elemento); Indice[Disp]=Indice[Temp]; Indice[Temp]=Disp; Disp=Indice[Disp]; Recorrido(Info,Indice,Inicio,Disp); }

Eliminación por Búsqueda Definición:

Page 95: 19189723 estructura-de-datos-programacion-facil

95

La Eliminación simplemente cambia los nodos para que el dato que se desea eliminar sea el primer disponible, de esta forma ya no estará en el Arreglo de Info. Detalle: Lo primero que hace es ver si existe algún dato en la lista para eliminar, si Indice[Inicio] es igual a Inicio entonces solo desplegara “Imposible Eliminar”. De otra formas cambiar de Posición en Posición hasta encontrar el Elemento que sea desea Eliminar con ayudar de dos variables que guardan la Posición actual y la anterior en donde se encuentre el dato. Ya que lo encuentra cambia ese dato como la primera posición Disponible y lo apunta al siguiente nodo disponible. Si no encuentra el dato simplemente desplegara “Dato no encontrado” Algoritmo:

EliBusq(Inicio, Info, Indice, Elemento) Temp → Indice*Inicio+ Si Temp = Inicio Imprimir “Lista Vacia… Imposible Eliminar” y Retornar Repetir mientras Temp ≠ Inicio Si Elemento = Info[Temp] entonces: Si Temp = Indice[Inicio] entonces: Indice*Inicio+ → Indice*Indice*Inicio++ Si no: Indice[Temp2+ → Indice*Temp+ Indice*Temp+ → Disp Disp → Temp Recorrido(Inicio, Info, Indice) y Retornar Si no: Temp2 → Temp Temp → Indice*Temp+ Imprimir “Dato no encontrado… Imposible Eliminar” y Retornar

Diagrama:

Programa:

Page 96: 19189723 estructura-de-datos-programacion-facil

96

#include <conio.h> #include <iostream.h> void Recorrido(int Info[8],int Indice[8],int Inicio,int Disp); void EliBusq(int Info[8],int Indice[8],int Inicio,int Disp,int Elemento); void main() { int Info[8]={0,10,0,9,5,3,0,20}; int Indice[8]={5,7,6,1,0,3,-999,4}; int Inicio=0,Disp=2,Elemento,Res; cout<<"Lista Original\n"; Recorrido(Info,Indice,Inicio,Disp); cout<<"Que Numero deseas Eliminar?"; cin>>Elemento; EliBusq(Info,Indice,Inicio,Disp,Elemento); getch(); } void Recorrido(int Info[8],int Indice[8],int Inicio,int Disp) { int Apuntador=Indice[Inicio]; while(Apuntador!=Inicio) { cout<<Info[Apuntador]<<endl; Apuntador=Indice[Apuntador];

Page 97: 19189723 estructura-de-datos-programacion-facil

97

} } void EliBusq(int Info[8],int Indice[8],int Inicio,int Disp,int Elemento) { int Temp=Indice[Inicio],Temp2; if(Temp==Inicio) { cout<<"Lista Vacia... Imposible Eliminar"; return; } while(Temp!=Inicio) { if(Elemento==Info[Temp]) { if(Temp==Inicio) Inicio=Indice[Inicio]; else Indice[Temp2]=Indice[Temp]; Indice[Temp]=Disp; Disp=Temp; Recorrido(Info,Indice,Inicio,Disp); return; } else

Page 98: 19189723 estructura-de-datos-programacion-facil

98

{ Temp2=Temp; Temp=Indice[Temp]; } } cout<<"Dato no encontrado... Imposible Eliminar"; return; }

Proyecto Final: Unidad 3: Listas Dobles Recorrido Definición: Recorrido simplemente despliega los datos almacenados en el arreglo Info, con ayuda de un segundo arreglo llamado Indice1 o Indice2 el cual guarda el orden en el que encuentran enlazados cada uno de los datos. Estos datos se pueden recorrer de Arriba hacia Abajo o de Abajo hacia Arriba. Explicación: Dependiendo de la forma en la que se desea recorrer el Arreglo, la variable Apuntador tomara el valor de Indice1[Inicio], o de Fin. Después recorrerá el Arreglo mientras la condición no se rompa (Dicha condición será diferente dependiendo el caso). Diagrama:

Page 99: 19189723 estructura-de-datos-programacion-facil

99

Búsqueda Definición: La Búsqueda su objetivo es encontrar un dato en el arreglo Info, si lo encuentra lo desplegara en la pantalla, si no lo encuentra no desplegara nada ya que el dato no se encuentra en el arreglo Info. Esta búsqueda es mas efectiva ya que compara el dato de la mitad y dependiendo el resultado, empezara la búsqueda por el Final o Inicio. Explicación: Primeramente usaremos un contador y la cabecera, esto nos permitirá determinar cual es dato de la mitad. Para esto se utiliza el Recorrido el cual al encontrar el Dato de la mitad lo copia ese dato a la cabecera con la cual se comparara para determinar por donde empezar (Inicio y Fin). Diagrama:

Inserción Ordenada Definición:

Page 100: 19189723 estructura-de-datos-programacion-facil

100

La Inserción Ordenada busca la posición en donde será Insertado el Elemento y la posición anterior donde será Insertado, después de encontrar la posición en la que será Insertado el Elemento nos regresa ese valor y lo mandamos al método de la Inserción después de un Nodo. Explicación: Esta Inserción ordenada es similar a las anteriores aunque en este caso consta de mas comparación y movimientos de variables, esto se debe a que tenemos 2 arreglos que nos indican los movimientos y al insertar un dato ambos arreglos deben direccionar nuevamente. Diagrama:

Eliminación por Búsqueda Definición: La Eliminación simplemente cambia los nodos para que el dato que se desea eliminar sea el primer disponible, de esta forma ya no estará en el Arreglo de Info. Explicación: Lo primero que hace es ver si existe algún dato en la lista para eliminar, si Indice[Inicio] es igual a Inicio entonces solo desplegara “Imposible Eliminar”. De otra formas cambiar de Posición en Posición hasta encontrar el Elemento que sea desea Eliminar con ayudar de dos variables que guardan la Posición actual y la anterior en donde se encuentre el dato. Ya que lo encuentra cambia ese dato como la primera posición Disponible y lo apunta al siguiente nodo disponible. Si no encuentra el dato simplemente desplegara “Dato no encontrado” Diagrama:

Page 101: 19189723 estructura-de-datos-programacion-facil

101

Corrida:

PROGRAMA CLICK HERE PROGRAMACION LISTAS DOBLES ESTRUCTURAS DE DATOS #include <stdio.h> #include <conio.h> #include <iomanip.h>

Page 102: 19189723 estructura-de-datos-programacion-facil

102

#include <iostream.h> class Alumno { private: char Nombre[10][30]; int N_control[10],Edad[10],Indice1[10],Indice2[10],Inicio,Fin,Disp; public: //Constructor Alumno() { int i,j; Inicio=0; Fin=0; Disp=1; Indice1[Inicio]=-999; Indice2[Fin]=-999; for(i=1,j=2;i<9;i++,j++) Indice1[i]=j; Indice1[9]=-999; } //Funcion de Recorrido void Recorrido(int op) { int i=0,Temp;

Page 103: 19189723 estructura-de-datos-programacion-facil

103

if(op==1) { Temp=Indice1[Inicio]; if(Temp!=-999) { cout<<"Numero de Control"<<setw(19)<<"Nombre del Alumno"<<setw(5)<<"Edad"<<endl; while(Temp!=-999) { if(i==(int(Edad[Inicio]/2))) { N_control[Inicio]=N_control[i]; strcpy(Nombre[Inicio],Nombre[i]); } cout<<setw(9)<<N_control[Temp]<<setw(22)<<Nombre[Temp]<<setw(9)<<Edad[Temp]<<endl; Temp=Indice1[Temp]; i++; } } else cout<<"Lista Vacia..."; } if(op==2) {

Page 104: 19189723 estructura-de-datos-programacion-facil

104

Temp=Fin; if(Edad[Inicio]!=0) { cout<<"Numero de Control"<<setw(19)<<"Nombre del Alumno"<<setw(5)<<"Edad"<<endl; while(Temp!=-999&&i<Edad[Inicio]) { if(i==(int(Edad[Inicio]/2))) { N_control[Inicio]=N_control[i]; strcpy(Nombre[Inicio],Nombre[i]); } cout<<setw(9)<<N_control[Temp]<<setw(22)<<Nombre[Temp]<<setw(9)<<Edad[Temp]<<endl; Temp=Indice2[Temp]; i++; } } else cout<<"Lista Vacia..."; } } //Funcion Sobrecargada de Busqueda para Enteros int Busqueda(int Elem) { if(Elem<N_control[Inicio])

Page 105: 19189723 estructura-de-datos-programacion-facil

105

{ int Temp=Indice1[Inicio]; while(Temp!=-999) { if(Elem==N_control[Temp]) { gotoxy(1,10); cout<<"Numero de Control"<<setw(19)<<"Nombre del Alumno"<<setw(5)<<"Edad"<<endl; cout<<setw(9)<<N_control[Temp]<<setw(22)<<Nombre[Temp]<<setw(9)<<Edad[Temp]<<endl; return Temp; } else Temp=Indice1[Temp]; } } else { int Temp=Fin; while(Temp!=-999) { if(Elem==N_control[Temp]) { gotoxy(1,10);

Page 106: 19189723 estructura-de-datos-programacion-facil

106

cout<<"Numero de Control"<<setw(19)<<"Nombre del Alumno"<<setw(5)<<"Edad"<<endl; cout<<setw(9)<<N_control[Temp]<<setw(22)<<Nombre[Temp]<<setw(9)<<Edad[Temp]<<endl; return Temp; } else Temp=Indice2[Temp]; } } return -999; } //Funcion Sobrecargada de Busqueda de Cadenas de Caracteres int Busqueda(char Elem[30]) { if((strcmp(Elem,Nombre[Inicio]))<0) { int Temp=Indice1[Inicio]; while(Temp!=-999) { if((strcmp(Elem,Nombre[Temp]))==0) { gotoxy(1,10); cout<<"Numero de Control"<<setw(19)<<"Nombre del Alumno"<<setw(5)<<"Edad"<<endl; cout<<setw(9)<<N_control[Temp]<<setw(22)<<Nombre[Temp]<<setw(9)<<Edad[Temp]<<endl; return Temp;

Page 107: 19189723 estructura-de-datos-programacion-facil

107

} else Temp=Indice1[Temp]; } } else { int Temp=Fin; while(Temp!=-999) { if((strcmp(Elem,Nombre[Temp]))==0) { gotoxy(1,10); cout<<"Numero de Control"<<setw(19)<<"Nombre del Alumno"<<setw(5)<<"Edad"<<endl; cout<<setw(9)<<N_control[Temp]<<setw(22)<<Nombre[Temp]<<setw(9)<<Edad[Temp]<<endl; return Temp; } else Temp=Indice2[Temp]; } } return -999; }

Page 108: 19189723 estructura-de-datos-programacion-facil

108

//Funcion Sobrecargada de Orden para Numeros Enteros int Enca(int E_nc) { int Temp=Indice1[Inicio],Temp2; if(Temp==-999||E_nc<N_control[Temp]) return -999; Temp2=Indice1[Indice1[Inicio]]; while(Temp2!=-999) { if(E_nc<N_control[Temp2]) return Temp; Temp=Temp2; Temp2=Indice1[Temp2]; } return Temp; } //Funcion Sobrecargada de Orden para Cadena de Caracteres int Enca(char E_nom[30]) { int Temp=Indice1[Inicio],Temp2; if(Temp==-999) return -999; if((strcmp(E_nom,Nombre[Temp]))<0) return Temp;

Page 109: 19189723 estructura-de-datos-programacion-facil

109

Temp2=Indice1[Indice1[Inicio]]; while(Temp2!=-999) { if((strcmp(E_nom,Nombre[Temp2]))<0) return Temp; Temp=Temp2; Temp2=Indice1[Temp2]; } return Temp; } //Funcion de Inserción en un Lugar Determinado void InsLug(char E_nom[30],int E_nc,int E_edad,int Npos) { if(Disp!=-999) { Edad[Inicio]++; int Temp=Disp; Disp=Indice1[Disp]; strcpy(Nombre[Temp],E_nom); N_control[Temp]=E_nc; Edad[Temp]=E_edad; if(Npos==-999) {

Page 110: 19189723 estructura-de-datos-programacion-facil

110

Indice1[Temp]=Indice1[Inicio]; if(Indice2[Fin]==-999) { Indice2[Temp]=Fin; Fin=Temp; } else { Indice2[Temp]=Indice1[Inicio]; Indice2[Indice1[Inicio]]=Temp; } Indice1[Inicio]=Temp; } else { Indice1[Temp]=Indice1[Npos]; if(Fin==Npos) { Indice2[Temp]=Fin; Fin=Temp; } else { Indice2[Temp]=Npos;

Page 111: 19189723 estructura-de-datos-programacion-facil

111

Indice2[Indice1[Npos]]=Temp; } Indice1[Npos]=Temp; } } else cout<<"Overflow..."<<endl; } //Funcion Sobrecargada para Borrar un Dato que sea Entero void Borrar(int Elem) { int Temp2,Temp=Indice1[Inicio]; if(Temp==-999) { cout<<"Lista Vacia... Imposible Eliminar"; return; } while(Temp!=-999) { if(Elem==N_control[Temp]) { Edad[Inicio]--; if(Temp==Indice1[Inicio])

Page 112: 19189723 estructura-de-datos-programacion-facil

112

{ Indice1[Inicio]=Indice1[Indice1[Inicio]]; Indice2[Indice1[Inicio]]=Inicio; } else if(Temp==Fin) { Indice1[Temp2]=Indice1[Temp]; Fin=Indice2[Fin]; } else { Indice1[Temp2]=Indice1[Temp]; Indice2[Indice1[Temp2]]=Temp2; } Indice1[Temp]=Disp; Disp=Temp; return; } else { Temp2=Temp; Temp=Indice1[Temp]; } }

Page 113: 19189723 estructura-de-datos-programacion-facil

113

cout<<"Dato no encontrado... Imposible Eliminar"; return; } //Funcion Sobrecargada para Borrar una Cadena de Caracteres void Borrar(char Elem[30]) { int Temp2,Temp=Indice1[Inicio]; if(Temp==Inicio) { cout<<"Lista Vacia... Imposible Eliminar"; return; } while(Temp!=Inicio) { if((strcmp(Elem,Nombre[Temp]))==0) { Edad[Inicio]--; if(Temp==Indice1[Inicio]) { Indice1[Inicio]=Indice1[Indice1[Inicio]]; Indice2[Indice1[Inicio]]=Inicio; } else if(Temp==Fin)

Page 114: 19189723 estructura-de-datos-programacion-facil

114

{ Indice1[Temp2]=Indice1[Temp]; Fin=Indice2[Fin]; } else { Indice1[Temp2]=Indice1[Temp]; Indice2[Indice1[Temp2]]=Temp2; } Indice1[Temp]=Disp; Disp=Temp; return; } else { Temp2=Temp; Temp=Indice1[Temp]; } } cout<<"Dato no encontrado... Imposible Eliminar"; return; } }tec; main()

Page 115: 19189723 estructura-de-datos-programacion-facil

115

{ int op=0,res; char inom[30]; int in_c,iedad; while(op!=6) { clrscr(); cout<<"\n1) Recorrido por Inicio\n2) Recorrido por Final\n3) Busqueda\n"; cout<<"4) Insercion\n5) Eliminar un Dato\n6) Salir"<<endl; gotoxy(1,1); cout<<"Que deseas hacer: "; cin>>op; gotoxy(1,10); switch (op) { case 1: tec.Recorrido(1); break; case 2: tec.Recorrido(2); break; case 3: cout<<"Que Numero de Control deseas buscar?"<<endl;

Page 116: 19189723 estructura-de-datos-programacion-facil

116

cin>>res; res=tec.Busqueda(res); if(res==-999) cout<<"Dato no encontrado"; break; case 4: cout<<"Que nombre quieres Insertar?"<<endl; gets(inom); cout<<"Cual es su Numero de Control?"<<endl; cin>>in_c; cout<<"Cual es su Edad?"<<endl; cin>>iedad; res=tec.Enca(in_c); tec.InsLug(inom,in_c,iedad,res); break; case 5: cout<<"Que Numero de Control deseas eliminar?"<<endl; cin>>res; tec.Borrar(res); break; case 6: cout<<"Salida..."; break; default:

Page 117: 19189723 estructura-de-datos-programacion-facil

117

cout<<"Opcion Erronea"<<endl; break; } getch(); } } ESTRUCTURA DE DATOS Recursividad Definición: Capacidad que tiene los métodos de invocarse a si mismos, esta es una potente herramienta en la informática. Con esta herramienta muchos algoritmos pueden simplificarse significativamente. Programa: #include <stdio.h> #include <conio.h> #include <string.h> #include <iomanip.h> #include <iostream.h> class Matematicas { public: void Tablas(int T,int B) { if(B<11) { cout<<T<<" X "<<setw(2)<<B<<" = "<<(T*B)<<endl; Tablas(T,B+1);

Page 118: 19189723 estructura-de-datos-programacion-facil

118

} return; } long Factorial(long n) { if(n<=1) return 1; else return (n* Factorial(n - 1)); } void Formula(int X) { if(X<11) { cout<<"f("<<X<<") = "<<((X*X*X)+(2*X)+(3))<<endl; Formula(X+1); } return; } void Torres(int N,char Inicio,char Aux,char Fin) { if(N==1) {

Page 119: 19189723 estructura-de-datos-programacion-facil

119

cout<<Inicio<<" --> "<<Fin<<endl; return; } Torres(N-1,Inicio,Fin,Aux); cout<<Inicio<<" --> "<<Fin<<endl; Torres(N-1,Aux,Inicio,Fin); return; } }tec; main() { int t,b,op=0; while(op!=5) { clrscr(); cout<<"\n1) Tablas de Multiplicar\n2) Factorial de un Numero\n"; cout<<"3) Formula Lineal\n4) Torres de Hanoi\n5) Salida"<<endl; gotoxy(1,1); cout<<"Que deseas hacer: "; cin>>op; clrscr(); switch(op) { case 1:

Page 120: 19189723 estructura-de-datos-programacion-facil

120

cout<<"Que Tabla de Multiplicar deseas Imprimir?"<<endl; cin>>t; cout<<"Desde que Numero deseas empezar a multiplicar (Menor que 10)"<<endl; cin>>b; tec.Tablas(t,b); break; case 2: cout<<"Que Factorial deseas conocer"<<endl; cin>>t; cout<<t<<"! = "<<tec.Factorial(t)<<endl; break; case 3: cout<<"f(x) = x^3 + 2x + 3"<<endl; cout<<"Escribe la Base (Menor de 10)"<<endl; cin>>t; tec.Formula(t); break; case 4: cout<<"Cuantos discos deseas mover?"<<endl; cin>>t; tec.Torres(t,'A','B','C'); break; case 5:

Page 121: 19189723 estructura-de-datos-programacion-facil

121

cout<<"Salida..."; break; default: cout<<"Opcion Erronea..."; break; } getch(); } } Unidad 5: Arboles Binarios Definición: Un Árbol Binario es un conjunto de finito de Elementos, de nombre Nodos de forma que: El Árbol Binario es Vació si no tiene ningún elemento en el. El Árbol Binario contiene un Nodo Raíz y los dos que parten de él, llamados Nodo Izquierdo y Nodo Derecho. Los Árboles tiene 3 Recorridos Diferentes los cuales son: Pre-Orden In-Orden Post-Orden Pre-Orden Definición: El Recorrido “Pre-Orden” lo recorre de la siguiente manera, viaje a través del Árbol Binario desplegando el Contenido en la Raíz, después viaje a través del Nodo Izquierdo y después a través del Nodo Derecho. Detalle: Temp toma el Valor de la Raíz y compara si el Árbol tiene algún Elemento, de otra manera Desplegara “Árbol Vació…” y terminara el método. Si el Árbol tiene elementos dentro de él, lo recorrerá y viajara a través de los Arreglos Izq y Der para determinar que valor meter en la Pila y en Temp para de esta manera imprimir el siguiente Elemento correspondiente. Algoritmo:

PreOrd(Arbol, Der, Izq, Pila, Raiz) Temp → Raiz Top → Pila*Top+ → Nulo Si Raiz = Nulo Imprimir “Árbol Vació…” y Salir Repetir mientras Temp ≠ Nulo Imprimir Arbol[Temp]

Page 122: 19189723 estructura-de-datos-programacion-facil

122

Si Der*Temp+ ≠ Nulo Top → Top + 1 Pila*Top+ → Der*Temp+ Si Izq*Temp+ ≠ Nulo Temp → Izq*Temp+ Si no: Temp → Pila*Top+; Top → Top - 1 Fin del ciclo Salir

Diagrama:

Corrida:

In-Orden Definición: El Recorrido “In-Orden” lo recorre de la siguiente manera, viaje a través del Árbol Binario desplegando el Contenido en el Nodo Izquierdo después la Raíz y finalmente viaja a través del Nodo Derecho.

Page 123: 19189723 estructura-de-datos-programacion-facil

123

Detalle: Temp toma el Valor de la Raíz y compara si el Árbol tiene algún Elemento, de otra manera Desplegara “Árbol Vació…” y terminara el método. Si el Árbol tiene elementos dentro de él, lo recorrerá y viajara a través de los Arreglos Izq y Der para determinar que valor meter en la Pila y en Temp para de esta manera imprimir el siguiente Elemento correspondiente. Algoritmo:

PreOrd(Arbol, Der, Izq, Pila, Raiz) Temp → Raiz Top → Pila*Top+ → Nulo Si Raiz = Nulo Imprmir “Arbol Vacio…” y Salir Etiqueta: Mientras Temp ≠ Nulo Top → Top + 1 Pila*Top+ → Temp Temp → Izq*Temp+ Fin del ciclo Temp → Pila*Top+ Top → Top - 1 Mientras Temp ≠ Nulo Imprimir Arbol[Temp] Si Der*Temp+ ≠ Nulo Temp → Der*Temp+ Ir a Etiqueta Temp → Pila*Top+ Top → Top - 1 Fin del ciclo Salir

Diagrama:

Page 124: 19189723 estructura-de-datos-programacion-facil

124

Corrida:

In-Orden Definición: El Recorrido “In-Orden” lo recorre de la siguiente manera, viaje a través del Árbol Binario desplegando el Contenido en el Nodo Izquierdo después el Nodo Derecho y finalmente viaja a través de la Raiz. Detalle: Temp toma el Valor de la Raíz y compara si el Árbol tiene algún Elemento, de otra manera Desplegara “Árbol Vació…” y terminara el método. Si el Árbol tiene elementos dentro de él, lo recorrerá y viajara a través de los Arreglos Izq y Der para determinar que valor meter en la Pila y en Temp para de esta manera imprimir el siguiente Elemento correspondiente. Algoritmo:

PostOrd(Arbol, Der, Izq, Pila, Raiz) Temp → Raiz Top → Pila*Top+ → Nulo Si Raiz = Nulo

Page 125: 19189723 estructura-de-datos-programacion-facil

125

Imprimir “Arbol Vacio…” y Salir Etiqueta: Mientras Temp ≠ Nulo Top → Top + 1 Pila*Top+ → Temp Si Der*Temp+ ≠ Nulo Top → Top + 1 Pila*Top+ → - (Der[Temp]) Temp → Izq*Temp+ Temp → Pila*Top+ Top → Top - 1 Fin del ciclo Mientras Temp ≥ 0 Imprimir Arbol[Temp] Si Arbol[Temp] = Info[Raiz] Salir Temp → Pila*Top+ Top → Top - 1 Fin del ciclo Si Temp < 0 Temp = -(Temp) Ir a Etiqueta Salir

Diagrama:

Corrida:

Page 126: 19189723 estructura-de-datos-programacion-facil

126

Búsqueda Definición: La Búsqueda es Similar a todas los Métodos anteriores de Búsqueda, simplemente efectúa un recorrido comparando el Elemento que deseas encontrar contra cada uno de los Elementos en los Arreglos. Detalle: El Algoritmo de Búsqueda compara el Elemento a buscar con cada uno de los datos de nuestro Árbol, compara si el Elemento con el Nodo Raíz, si no se encuentra en la Raíz… compara Elemento contra la Raíz para empezar a viajar por el Árbol respectivamente, usa un método similar al anterior hasta encontrar el Elemento. De otra forma la búsqueda es fallida. Algoritmo:

Busqueda(Arbol, Der, Izq, Pila, Raiz, Elem) Si Raiz = Nulo Imprimir “Arbol Vacio” Pos → Nulo Pad → Nulo Regresar Pos y Pad Salir Si Elem = Arbol[Raiz] Imprimir “Elemento Encontrado” Pos → Raiz Pad → Nulo Regresar Pos y Pad Salir Si Elem < Arbol[Raiz] Temp → Izq*Raiz+ Temp2 → Raiz Si no: Temp → Der*Raiz+ Temp2 → Raiz Mientras Temp ≠ Nulo Si Elem = Arbol[Temp] Imprimir “Elemento Encontrado…” Pos → Temp Pad → Temp2

Page 127: 19189723 estructura-de-datos-programacion-facil

127

Regresar Pos y Pad Salir Si Elem < Arbol[Temp] Temp2 → Temp Temp → Izq*Temp+ Si no: Temp2 → Temp Temp → Der*Temp+ Fin del ciclo Imprimir “Elemento no Encontrado…” Pos → Nulo Pad → Temp2 Regresar Pos y Pad Salir

Diagrama:

Corrida:

Page 128: 19189723 estructura-de-datos-programacion-facil

128

Programa click here: PROGRAMACION ARBOL BINARIO ESTRUCTURAS DE DATOS #include <conio.h> #include <iostream.h> class Arbol { private: int Top,Pila[10]; int Info[10],Izq[10],Der[10],Raiz,Disp; public: Arbol() { int in[10]={0,0,0,0,0,0,0,0,0,0}; for(int i=0;i<10;i++) { Info[i]=0; Izq[i]=i+1; Der[i]=-999; Pila[i]=0; } Top=0; Disp=0; Raiz=-999; Izq[9]=-999;

Page 129: 19189723 estructura-de-datos-programacion-facil

129

} void PreOrd(void) { int Temp=Raiz; Top=0; Pila[0]=-999; if(Raiz==-999) { cout<<"Arbol Vacio..."<<endl; return; } while(Temp!=-999) { cout<<Info[Temp]<<endl; if(Der[Temp]!=-999) { Top++; Pila[Top]=Der[Temp]; } if(Izq[Temp]!=-999) { Temp=Izq[Temp]; } else

Page 130: 19189723 estructura-de-datos-programacion-facil

130

{ Temp=Pila[Top]; Top--; } } } void InOrd(void) { int Temp=Raiz, Top=0; Pila[0]=-999; if(Raiz==-999) { cout<<"Arbol Vacio..."<<endl; return; } Back: while(Temp!=-999) { Top++; Pila[Top]=Temp; Temp=Izq[Temp]; }

Page 131: 19189723 estructura-de-datos-programacion-facil

131

Temp=Pila[Top]; Top--; while(Temp!=-999) { cout<<Info[Temp]<<endl; if(Der[Temp]!=-999) { Temp=Der[Temp]; goto Back; } Temp=Pila[Top]; Top--; } } void PostOrd(void) { int Temp=Raiz; Top=0; Pila[0]=-999; if(Raiz==-999) { cout<<"Arbol Vacio..."<<endl; return; }

Page 132: 19189723 estructura-de-datos-programacion-facil

132

Back1: while(Temp!=-999) { Top++; Pila[Top]=Temp; if(Der[Temp]!=-999) { Top++; Pila[Top]=-Der[Temp]; } Temp=Izq[Temp]; } Temp=Pila[Top]; Top--; while(Temp>=0) { cout<<Info[Temp]<<endl; if(Info[Temp]==Info[Raiz]) return; Temp=Pila[Top]; Top--; } if(Temp<0)

Page 133: 19189723 estructura-de-datos-programacion-facil

133

{ Temp=-Temp; goto Back1; } } void Busqueda(int PosPad[2],int Elem) { int Temp,Temp2; if(Raiz==-999) { PosPad[0]=-999; PosPad[1]=-999; cout<<"Arbol Vacio..."<<endl; return; } if(Elem==Info[Raiz]) { PosPad[0]=Raiz; PosPad[1]=-999; cout<<"Elemento Encontrado..."<<endl; return; } if(Elem<Info[Raiz]) {

Page 134: 19189723 estructura-de-datos-programacion-facil

134

Temp=Izq[Raiz]; Temp2=Raiz; } else { Temp=Der[Raiz]; Temp2=Raiz; } while(Temp!=-999) { if(Elem==Info[Temp]) { cout<<"Elemento Encontrado..."<<endl; PosPad[0]=Temp; PosPad[1]=Temp2; return; } if(Elem<Info[Temp]) { Temp2=Temp; Temp=Izq[Temp]; } else

Page 135: 19189723 estructura-de-datos-programacion-facil

135

{ Temp2=Temp; Temp=Der[Temp]; } } PosPad[0]=-999; PosPad[1]=Temp2; cout<<"Elemento no Encontrado..."<<endl; } void InsOrd(int Elem) { int PosPad[2],Temp; if(Disp!=-999) { Busqueda(PosPad,Elem); clrscr(); if(PosPad[0]!=-999) { cout<<"Elemento Existente... Imposible Insertar..."<<endl; return; } Temp=Disp; Disp=Izq[Disp]; Info[Temp]=Elem;

Page 136: 19189723 estructura-de-datos-programacion-facil

136

PosPad[0]=Temp; Izq[Temp]=-999; Der[Temp]=-999; if(PosPad[1]==-999) Raiz=Temp; else if(Elem<Info[PosPad[1]]) Izq[PosPad[1]]=Temp; else Der[PosPad[1]]=Temp; cout<<"Elemento Insertado..."<<endl; return; } cout<<"Arbol Lleno... Imposible Insertar..."<<endl; } void Eliminar(int Elem) { int PosPad[2]; Busqueda(PosPad,Elem); clrscr(); if(PosPad[0]==-999) { cout<<"El Elemento no se Encuentra en el Arbol... Imposible Eliminar..."<<endl; return;

Page 137: 19189723 estructura-de-datos-programacion-facil

137

} if(Der[PosPad[0]]!=-999&&Izq[PosPad[0]]!=-999) CasoB(PosPad); else CasoA(PosPad); Izq[PosPad[0]]=Disp; Disp=PosPad[0]; } void CasoA(int PosPad[2]) { int Temp; if(Izq[PosPad[0]]==-999&&Der[PosPad[0]]==-999) Temp=-999; else if(Izq[PosPad[0]]!=-999) Temp=Izq[PosPad[0]]; else Temp=Der[PosPad[0]]; if(PosPad[1]!=-999) { if(PosPad[0]==Izq[PosPad[1]]) Izq[PosPad[1]]=Temp; else Der[PosPad[1]]=Temp; }

Page 138: 19189723 estructura-de-datos-programacion-facil

138

else Raiz=Temp; } void CasoB(int PosPad[2]) { int PosPad2[2],Temp=Der[PosPad[0]],Temp2=PosPad[0]; while(Izq[Temp]!=-999) { Temp2=Temp; Temp=Izq[Temp]; } PosPad2[0]=Temp; PosPad2[1]=Temp2; CasoA(PosPad2); if(PosPad[1]!=-999) { if(PosPad[0]==Izq[PosPad[1]]) Izq[PosPad[1]]=PosPad2[0]; else Der[PosPad[1]]=PosPad2[0]; } else Raiz=PosPad2[0];

Page 139: 19189723 estructura-de-datos-programacion-facil

139

Izq[PosPad2[0]]=Izq[PosPad[0]]; Der[PosPad2[0]]=Der[PosPad[0]]; } }tec; main() { int PosPad[2],res,op=0; while(op!=7) { clrscr(); cout<<"\n1) Pre-Orden\n2) In-Orden\n3) Post-Orden\n4) Busqueda\n5) Insercion\n6) Eliminar\n7) Salir"<<endl; gotoxy(1,1); cout<<"Que deseas hacer?: "; cin>>op; gotoxy(1,10); switch (op) { case 1: tec.PreOrd(); break; case 2: tec.InOrd(); break;

Page 140: 19189723 estructura-de-datos-programacion-facil

140

case 3: tec.PostOrd(); break; case 4: cout<<"Que Numero deseas buscar?"<<endl; cin>>res; tec.Busqueda(PosPad,res); break; case 5: cout<<"Que Numero quieres Insertar?"<<endl; cin>>res; tec.InsOrd(res); break; case 6: cout<<"Que Numero quieres Eliminar?"<<endl; cin>>res; tec.Eliminar(res); break; case 7: cout<<"Salida..."; break; default: cout<<"Opcion Erronea"<<endl; break;

Page 141: 19189723 estructura-de-datos-programacion-facil

141

} getch(); } } Unidad 5: Arboles en Monton Definición: El Arbol en Monton consisten en el ordenamiento de un conjunto de Elemento en un solo arreglo. Trabajaremos sobre la siguientes Operaciones en este Tema:

1. Inserción 2. Búsqueda 3. Eliminación 4. Recorrido (Ordenado)

Inserción Definición: El Concepto de Inserción ya es familiar para nosotros y sabemos que para realizar el mismo no resulta complejo el procedimiento. Pero en los Árboles en Montón es uno de los Métodos más largos para efectuarlo. Detalle: Básicamente lo que hace estos Algoritmos es la Inserción Ordenada. Primero comparan si es posible insertar algún Elemento al Arreglo, si es posible hacerlo Ingresa el Elemento a la Ultima posición. Después básicamente acomoda el Arreglo con el Método de la Burbuja llamando a otra serie de Métodos. Algoritmos: Insertar(Arbol, N, Elemento) Si N<25 Arbol[N] -> a N -> N + 1 OrdMon(Arbol, N) Salir //Fin de la condición// Imprimir "Árbol Lleno..." Salir OrdMon(Arbol, Total)

Page 142: 19189723 estructura-de-datos-programacion-facil

142

ConstMon(Arbol, Total) Mientras Total > 1 Total -> Total - 1 Burbuja(0, Total) RecMon(Total, 0) //Fin del ciclo// Salir ConstMon(Arbol, Total) v -> (Total/2) - 1 Mientras v ≥ 0 RecMon(Arbol, Total, v) v -> v - 1 //Fin del ciclo// Salir ---- RecMon(Arbol, Total, v) w -> 2*v+1 Mientras w < Total Si (w+1) < Total Si Arbol[w+1] > Arbol[w] w++ //Fin de la condición// Fin de la condición

Page 143: 19189723 estructura-de-datos-programacion-facil

143

Si Arbol*v+ ≥ Arbol[w] Salir //Fin de la condición// Burbuja(Arbol, v, w) v -> w w -> 2*v+1 //Fin del ciclo// Salir ---- Burbuja(Arbol, v, w) t -> Arbol[v] Arbol[v] -> Arbol[w] Arbol[w] -> t Salir Diagrama:

Page 144: 19189723 estructura-de-datos-programacion-facil

144

Corrida:

Búsqueda Definición: El Concepto de Búsqueda es sencillo, simplemente es un método de búsqueda lineal. Existen 3 posible resultados:

1. Que el Árbol este Vació y no se puede realizar la búsqueda. 2. Que el Elemento sea encuentre en el Árbol 3. Que el Elemento no este dentro del Árbol

Detalle: Se manda al Método Búsqueda el Dato que se desea buscar, se acomoda el Árbol en Orden en caso que no estuviera Ordenado y después compara con cada uno de los datos. Algoritmos: **Busqueda(Arbol, N, Elemento)** Si N ≠ 0 OrdMon(Arbol, N) i -> Mientras i < N;i++) Si Arbol[i] = Elemento Imprimir "Elemento Encontrado..." Salir //Fin de la condición// i -> i + 1 //Fin del ciclo// Imprimir "El Elemento no esta en el Árbol..."

Page 145: 19189723 estructura-de-datos-programacion-facil

145

Salir //Fin de la condición// Imprimir "Árbol Vació..." Salir Diagrama:

Corrida:

Eliminación Definición: El Concepto de Eliminación consiste en la búsqueda de un Elemento y sacarlo del Arreglo. Existen 3 casos Diferentes;

1. Que el Árbol este Vació y no se puede realizar la eliminación 2. Que el Elemento sea encuentre en el Árbol y sea eliminado 3. Que el Elemento no este dentro del Árbol por lo tanto no se elimina

Detalle:

Page 146: 19189723 estructura-de-datos-programacion-facil

146

Vemos si el Árbol tiene Elementos insertados en el, de otra forma será imposible realizar la Eliminación ya que esta Vació. Después si el Árbol tiene Elementos lo ordenamos y hacemos un búsqueda lineal para encontrar el dato. Después usamos el método de la Burbuja para dejar el Elemento Eliminado hasta el final y le Restamos a N un Elemento. Algoritmo: Eliminar(Arbol, N, Elemento) Si N ≠ 0 OrdMon(Arbol, N) i -> Mientras I < N Si Arbol[i] = Elemento j -> i + 1 Mientras j < N t -> Arbol[i] Arbol[i] -> Arbol[j] Arbol[j] -> t j -> j + 1 //Fin del ciclo// N -> n - 1 Imprimir "Elemento Eliminado..." Salir //Fin de la condición// i -> i + 1 //Fin del ciclo// Fin de la condición Imprimir "Arbol Vacio... Imposible Eliminar..."

Page 147: 19189723 estructura-de-datos-programacion-facil

147

Salir Diagrama:

Corrida:

Recorrido (Ordenado) Definición: El Recorrido simplemente ira desplegando cada uno de los Elementos del Árbol. Solo existen 2 posibles casos:

1. Que el Árbol este Vació y no se pueda recorrer 2. El Árbol tenga Elementos para desplegar

Detalle: Comparamos para comprobar que el Árbol tiene Elementos dentro de el, de ser así Desplegamos cada uno de ellos. De otra manera Desplegamos Árbol Vació. Algoritmo: Recorrido(Arbol, N) Si N ≠ 0

Page 148: 19189723 estructura-de-datos-programacion-facil

148

i -> Mientras i < N Imprimir Arbol[i] i -> i + 1 //Fin del ciclo// Salir //Fin de la condición// Imprimir "Arbol Vacio..." Salir Corrida:

Programa Click Here: PROGRAMACION ARBOL EN MONTON ESTRUCTURAS DE DATOS #include <conio.h> #include <iostream.h> class Arbol_Monton { private: int Arbol[25]; int N;

Page 149: 19189723 estructura-de-datos-programacion-facil

149

public: Arbol_Monton() { for(int i=0;i<25;i++) Arbol[i]=0; N=0; } void Insertar(int a) { if(N<25) { Arbol[N]=a; N++; OrdMon(N); return; } cout<<"Arbol Lleno..."<<endl; } void Eliminar(int a) { int t; if(N!=0) {

Page 150: 19189723 estructura-de-datos-programacion-facil

150

OrdMon(N); for(int i=0;i<N;i++) { if(Arbol[i]==a) { for(int j=i+1;j<N;j++) { t=Arbol[i]; Arbol[i]=Arbol[j]; Arbol[j]=t; } N--; cout<<"Elemento Eliminado..."<<endl; return; } } } cout<<"Arbol Vacio... Imposible Eliminar..."<<endl; } void Busqueda(int a) { if(N!=0) { OrdMon(N);

Page 151: 19189723 estructura-de-datos-programacion-facil

151

for(int i=0;i<N;i++) if(Arbol[i]==a) { cout<<"Elemento Encontrado..."<<endl; return; } cout<<"El Elemento no esta en el Arbol..."<<endl; return; } cout<<"Arbol Vacio..."<<endl; } void OrdMon(int n) { ConstMon(n); while(n>1) { n--; Burbuja(0,n); RecMon(n,0); } } void ConstMon(int n) {

Page 152: 19189723 estructura-de-datos-programacion-facil

152

for(int v=n/2-1;v>=0;v--) RecMon(n,v); } void RecMon(int n,int v) { int w=2*v+1; while(w<n) { if(w+1<n) if (Arbol[w+1]>Arbol[w]) w++; if(Arbol[v]>=Arbol[w]) return; Burbuja(v,w); v=w; w=2*v+1; } } void Burbuja(int i,int j) { int t=Arbol[i]; Arbol[i]=Arbol[j]; Arbol[j]=t; }

Page 153: 19189723 estructura-de-datos-programacion-facil

153

void Recorrido() { if(N!=0) { for(int i=0;i<N;i++) cout<<Arbol[i]<<endl; return; } cout<<"Arbol Vacio..."<<endl; } }tec; main() { int res,op=0; while(op!=5) { clrscr(); cout<<"\n1) Recorrido\n2) Busqueda\n3) Insercion\n4) Eliminar\n5) Salir"<<endl; gotoxy(1,1); cout<<"Que deseas hacer?: "; cin>>op; gotoxy(1,10); switch (op)

Page 154: 19189723 estructura-de-datos-programacion-facil

154

{ case 1: tec.Recorrido(); break; case 2: cout<<"Que Numero deseas buscar?"<<endl; cin>>res; tec.Busqueda(res); break; case 3: cout<<"Que Numero quieres Insertar?"<<endl; cin>>res; tec.Insertar(res); break; case 4: cout<<"Que Numero quieres Eliminar?"<<endl; cin>>res; tec.Eliminar(res); break; case 5: cout<<"Salida..."; break; default: cout<<"Opcion Erronea"<<endl;

Page 155: 19189723 estructura-de-datos-programacion-facil

155

break; } getch(); } } Unidad 6: Ordenamientos Internos Introducción: En esta Unidad explicaremos 4 algoritmos para el Ordenamiento de Arreglos en Memoria Ram. A continuación mencionaremos los diferentes métodos para ordenar:

1. Burbuja 2. ShellSort 3. RadixSort 4. QuickSort

Burbuja Definición: El método de la burbuja es una comparación lineal con cada uno de los elementos, el elemento que sea menor contra el que se esta comparado intercambiaran posiciones. Este método no es recomendado para grandes comparaciones, ya que es un proceso muy lento y requiere de una gran cantidad de Memoria Ram. Programa: #include <conio.h> #include <iostream.h> class Lista { private: int Lista[10],N; public: Lista() { for(int i=0;i<10;i++) Lista[i]=0;

Page 156: 19189723 estructura-de-datos-programacion-facil

156

N=0; } void Burbuja(void) { if(N!=0) { int i,j,aux; for(i=0;i<9;i++) for(j=i+1;j<10;j++) if(Lista[i]<Lista[j]) { aux=Lista[i]; Lista[i]=Lista[j]; Lista[j]=aux; } cout<<"Lista Ordenada..."<<endl; return; } cout<<"Lista Vacia..."<<endl; } void Busqueda(int Elem) { if(N!=0)

Page 157: 19189723 estructura-de-datos-programacion-facil

157

{ for(int i=0;i<N;i++) if(Lista[i]==Elem) { cout<<"El "<<Elem<<" esta en la Lista"<<endl; return; } } cout<<"Lista Vacia..."<<endl; return; } void Insertar(int Elem) { if(N<10) { Lista[N]=Elem; N++; cout<<"El "<<Elem<<" fue Insertado"<<endl; return; } cout<<"Lista Llena... Imposible Insertar"<<endl; return; } void Eliminar(int Elem)

Page 158: 19189723 estructura-de-datos-programacion-facil

158

{ if(N!=0) { for(int i=0;i<N;i++) if(Lista[i]==Elem) { Lista[i]=0; Burbuja(); N--; return; } } cout<<"Lista Vacia... Imposible Eliminar..."<<endl; return; } void Recorrido() { if(N!=0) { for(int i=0;i<N;i++) cout<<Lista[i]<<endl; } cout<<"Lista Vacia..."<<endl;

Page 159: 19189723 estructura-de-datos-programacion-facil

159

} }tec; main() { int op=0,res; while(op!=6) { clrscr(); cout<<"\n1) Recorrido\n2) Ordenar\n3) Busqueda\n4) Insercion\n5) Eliminar un Dato\n6) Salir"<<endl; gotoxy(1,1); cout<<"Que deseas hacer: "; cin>>op; gotoxy(1,10); switch (op) { case 1: tec.Recorrido(); break; case 2: tec.Burbuja(); break; case 3: cout<<"Que Numero de Control deseas buscar?"<<endl; cin>>res;

Page 160: 19189723 estructura-de-datos-programacion-facil

160

tec.Busqueda(res); break; case 4: cout<<"Que Numero Deseas Insertar?"<<endl; cin>>res; tec.Insertar(res); break; case 5: cout<<"Que Numero de Control deseas Eliminar?"<<endl; cin>>res; tec.Eliminar(res); break; case 6: cout<<"Salida..."; break; default: cout<<"Opcion Erronea"<<endl; break; } getch(); } } ShellSort Definición:

Page 161: 19189723 estructura-de-datos-programacion-facil

161

Esta forma de ordenación es muy parecida a la ordenación con burbuja. La diferencia es que no es una comparación lineal, sino que trabaja con una segmentación entre los datos. Por lo tanto es un buen método, pero no el mejor para implementarlos en grandes arreglos. Programa: #include <conio.h> #include <iostream.h> class Lista { private: int Lista[10],N; public: Lista() { for(int i=0;i<10;i++) Lista[i]=0; N=0; } void ShellSort(void) { if(N!=0) { int salto,aux,i; for(salto=6/2;salto!=0;salto/=2) { for(i=salto;i<6;i++)

Page 162: 19189723 estructura-de-datos-programacion-facil

162

if(Lista[i-salto]<Lista[i]) { aux=Lista[i]; Lista[i]=Lista[i-salto]; Lista[i-salto]=aux; } } cout<<"Lista Ordenada..."<<endl; return; } cout<<"Lista Vacia..."<<endl; } void Busqueda(int Elem) { if(N!=0) { for(int i=0;i<N;i++) if(Lista[i]==Elem) { cout<<"El "<<Elem<<" esta en la Lista"<<endl; return; } } cout<<"Lista Vacia..."<<endl;

Page 163: 19189723 estructura-de-datos-programacion-facil

163

return; } void Insertar(int Elem) { if(N<10) { Lista[N]=Elem; N++; cout<<"El "<<Elem<<" fue Insertado"<<endl; return; } cout<<"Lista Llena... Imposible Insertar"<<endl; return; } void Eliminar(int Elem) { if(N!=0) { for(int i=0;i<N;i++) if(Lista[i]==Elem) { Lista[i]=0; ShellSort();

Page 164: 19189723 estructura-de-datos-programacion-facil

164

N--; return; } } cout<<"Lista Vacia... Imposible Eliminar..."<<endl; return; } void Recorrido() { if(N!=0) { for(int i=0;i<N;i++) cout<<Lista[i]<<endl; } cout<<"Lista Vacia..."<<endl; } }tec; main() { int op=0,res; while(op!=6) { clrscr(); cout<<"\n1) Recorrido\n2) Ordenar\n3) Busqueda\n4) Insercion\n5) Eliminar un Dato\n6) Salir"<<endl;

Page 165: 19189723 estructura-de-datos-programacion-facil

165

gotoxy(1,1); cout<<"Que deseas hacer: "; cin>>op; gotoxy(1,10); switch (op) { case 1: tec.Recorrido(); break; case 2: tec.ShellSort(); break; case 3: cout<<"Que Numero de Control deseas buscar?"<<endl; cin>>res; tec.Busqueda(res); break; case 4: cout<<"Que Numero Deseas Insertar?"<<endl; cin>>res; tec.Insertar(res); break; case 5:

Page 166: 19189723 estructura-de-datos-programacion-facil

166

cout<<"Que Numero de Control deseas Eliminar?"<<endl; cin>>res; tec.Eliminar(res); break; case 6: cout<<"Salida..."; break; default: cout<<"Opcion Erronea"<<endl; break; } getch(); } } RadixSort Definición: Este ordenamiento se basa en los valores de los dígitos reales en las representaciones de posiciones de los números que se ordenan. Es decir… toma un número y lo descompone en sus unidades, decenas, centenas, etc… de esta manera va determinando las posiciones de cada uno de ellos. Programa: #include <math.h> #include <conio.h> #include <iostream.h> class Lista { private:

Page 167: 19189723 estructura-de-datos-programacion-facil

167

int Lista[10],Temp[10],Elementos,N; public: Lista() { for(int i=0;i<10;i++) Lista[i]=0; N=9; Elementos=0; } void Ordenar() { if(N!=9) { RadixSort(0,Elementos,Lista,Temp); RadixSort(1,Elementos,Temp,Lista); RadixSort(2,Elementos,Lista,Temp); RadixSort(3,Elementos,Temp,Lista); cout<<"Lista Ordenada..."<<endl; return; } cout<<"Lista Vacia..."<<endl; } void RadixSort (int byte, int N, int *fuente, int *dest) {

Page 168: 19189723 estructura-de-datos-programacion-facil

168

int cont[256]; int ind[256]; int i; memset(cont,0,sizeof(cont)); for(i=0;i<10;i++) cont[((fuente[i])>>(byte*8))&0xff]++; ind[0]=0; for(i=1;i<256;i++) ind[i]=ind[i-1]+cont[i-1]; for(i=0;i<10;i++) dest[ind[((fuente[i])>>(byte*8))&0xff]++]=fuente[i]; } void Busqueda(int Elem) { if(N!=9) { for(int i=0;i<N;i++) if(Lista[i]==Elem) { cout<<"El "<<Elem<<" esta en la Lista"<<endl; return; } }

Page 169: 19189723 estructura-de-datos-programacion-facil

169

cout<<"Lista Vacia..."<<endl; return; } void Insertar(int Elem) { if(N!=-1) { Elementos++; Lista[N]=Elem; N--; cout<<"El "<<Elem<<" fue Insertado"<<endl; return; } cout<<"Lista Llena... Imposible Insertar"<<endl; return; } void Eliminar(int Elem) { if(N!=9) { for(int i=0;i<N;i++) if(Lista[i]==Elem) { Lista[i]=0;

Page 170: 19189723 estructura-de-datos-programacion-facil

170

Ordenar(); N++; Elementos--; return; } } cout<<"Lista Vacia... Imposible Eliminar..."<<endl; return; } void Recorrido() { if(N!=9) { for(int i=9;i!=N;i--) cout<<Lista[i]<<endl; return; } cout<<"Lista Vacia..."<<endl; } }tec; main() { int op=0,res;

Page 171: 19189723 estructura-de-datos-programacion-facil

171

while(op!=6) { clrscr(); cout<<"\n1) Recorrido\n2) Ordenar\n3) Busqueda\n4) Insercion\n5) Eliminar un Dato\n6) Salir"<<endl; gotoxy(1,1); cout<<"Que deseas hacer: "; cin>>op; gotoxy(1,10); switch (op) { case 1: tec.Recorrido(); break; case 2: tec.Ordenar(); break; case 3: cout<<"Que Numero de Control deseas buscar?"<<endl; cin>>res; tec.Busqueda(res); break; case 4: cout<<"Que Numero Deseas Insertar?"<<endl; cin>>res;

Page 172: 19189723 estructura-de-datos-programacion-facil

172

tec.Insertar(res); break; case 5: cout<<"Que Numero de Control deseas Eliminar?"<<endl; cin>>res; tec.Eliminar(res); break; case 6: cout<<"Salida..."; break; default: cout<<"Opcion Erronea"<<endl; break; } getch(); } } QuickSort Definición: Probablemente este será el mejor de los métodos que mencionamos en esta unidad. Este divide aleatoriamente el arreglo para comparar si un elemento es mayor o menor. Dependiendo el resultado lo partirá ya sea por la izquierda o derecha, de esta forma se repite el procedimiento para ordenarlos. Programa: #include <conio.h> #include <iostream.h> class Lista

Page 173: 19189723 estructura-de-datos-programacion-facil

173

{ private: int Lista[10],N; public: Lista() { for(int i=0;i<10;i++) Lista[i]=0; N=1; } int Dividir(int menor,int mayor) { int izq,dch,temp; izq=menor; dch=mayor; while(izq<dch) { while(Lista[dch]>Lista[menor]) dch--; while((izq<dch)&&(Lista[izq]<=Lista[menor])) izq++; if(izq<dch) {

Page 174: 19189723 estructura-de-datos-programacion-facil

174

temp=Lista[izq]; Lista[izq]=Lista[dch]; Lista[dch]=temp; } } temp=Lista[dch]; Lista[dch]=Lista[menor]; Lista[menor]=temp; return dch; } void QuickSort(int menor,int mayor) { if(N!=1) { int medio; if(menor<mayor) { medio=Dividir(menor,mayor); QuickSort (menor,medio-1); QuickSort (medio+1,mayor); } cout<<"Lista Ordenada..."<<endl; } cout<<"Lista Vacia..."<<endl;

Page 175: 19189723 estructura-de-datos-programacion-facil

175

} void Busqueda(int Elem) { if(N!=0) { for(int i=0;i<N;i++) if(Lista[i]==Elem) { cout<<"El "<<Elem<<" esta en la Lista"<<endl; return; } } cout<<"Lista Vacia..."<<endl; return; } void Insertar(int Elem) { if(N<11) { Lista[10-N]=Elem; N++; cout<<"El "<<Elem<<" fue Insertado"<<endl; return;

Page 176: 19189723 estructura-de-datos-programacion-facil

176

} cout<<"Lista Llena... Imposible Insertar"<<endl; return; } void Eliminar(int Elem) { if(N!=0) { for(int i=0;i<N;i++) if(Lista[i]==Elem) { Lista[i]=0; QuickSort(0,9); N--; return; } } cout<<"Lista Vacia... Imposible Eliminar..."<<endl; return; } void Recorrido() { if(N!=1) {

Page 177: 19189723 estructura-de-datos-programacion-facil

177

for(int i=1;i!=N;i++) cout<<Lista[10-i]<<endl; } cout<<"Lista Vacia..."<<endl; } }tec; main() { int op=0,res; while(op!=6) { clrscr(); cout<<"\n1) Recorrido\n2) Ordenar\n3) Busqueda\n4) Insercion\n5) Eliminar un Dato\n6) Salir"<<endl; gotoxy(1,1); cout<<"Que deseas hacer: "; cin>>op; gotoxy(1,10); switch (op) { case 1: tec.Recorrido(); break; case 2:

Page 178: 19189723 estructura-de-datos-programacion-facil

178

tec.QuickSort(0,9); break; case 3: cout<<"Que Numero de Control deseas buscar?"<<endl; cin>>res; tec.Busqueda(res); break; case 4: cout<<"Que Numero Deseas Insertar?"<<endl; cin>>res; tec.Insertar(res); break; case 5: cout<<"Que Numero de Control deseas Eliminar?"<<endl; cin>>res; tec.Eliminar(res); break; case 6: cout<<"Salida..."; break; default: cout<<"Opcion Erronea"<<endl; break; }

Page 179: 19189723 estructura-de-datos-programacion-facil

179

getch(); } } Unidad 7: Ordenamientos Externos Introducción: En esta Unidad explicaremos 2 algoritmos para el Ordenamiento de Archivos. A continuación mencionaremos los diferentes métodos para ordenar:

1. Mezcla Directa 2. Mezcla Natural

Mezcla Directa Definición: Este algoritmo consiste en tener un archivo A desordenado. Este archivo se ordenara haciendo los siguientes pasos: 1.- Definir tamaño de tramo igual a 1 2.- Repartir el archivo A en dos archivos B y C escribiendo alternadamente un tramo en cada uno 3.- Aplicar el algoritmo de mezcla simple a cada par de tramos correspondiente de los archivos B y C guardando el resultado en el archivo A 4.- Duplicar el tamaño del tramo 5.- Regresar al paso 2 si el tamaño del tramo es menor que la cantidad de elementos a ordenar Programa: #include <stdio.h> #include <conio.h> #include <stdlib.h> #include <string.h> #include <iostream.h> class Archivos { public: void Mostrar(FILE *fich) { char linea[128]; rewind(fich);

Page 180: 19189723 estructura-de-datos-programacion-facil

180

fgets(linea, 128, fich); while(!feof(fich)) { puts(linea); fgets(linea, 128, fich); } } void Mezcla(FILE *fich) { int ordenado; FILE *aux[2]; do { aux[0] = fopen("aux1.txt", "w+"); aux[1] = fopen("aux2.txt", "w+"); rewind(fich); Separar(fich, aux); rewind(aux[0]); rewind(aux[1]); rewind(fich); ordenado = Mezclar(fich, aux); fclose(aux[0]); fclose(aux[1]);

Page 181: 19189723 estructura-de-datos-programacion-facil

181

}while(!ordenado); remove("aux1.txt"); remove("aux2.txt"); } void Separar(FILE *fich, FILE **aux) { char linea[128], anterior[2][128]; int salida = 0; strcpy(anterior[0], ""); strcpy(anterior[1], ""); fgets(linea, 128, fich); while(!feof(fich)) { if(salida == 0 && strcmp(linea, anterior[0]) < 0) salida = 1; else if(salida == 1 && strcmp(linea, anterior[1]) < 0) salida = 0; strcpy(anterior[salida], linea); fputs(linea, aux[salida]); fgets(linea, 128, fich); } } int Mezclar(FILE *fich, FILE **aux) {

Page 182: 19189723 estructura-de-datos-programacion-facil

182

char ultima[128], linea[2][128], anterior[2][128]; int entrada; int tramos = 0; fgets(linea[0], 128, aux[0]); fgets(linea[1], 128, aux[1]); strcpy(ultima, ""); strcpy(anterior[0], ""); strcpy(anterior[1], ""); while(!feof(aux[0]) && !feof(aux[1])) { if(strcmp(linea[0], linea[1]) <= 0) entrada = 0; else entrada = 1; strcpy(anterior[entrada], linea[entrada]); fputs(linea[entrada], fich); fgets(linea[entrada], 128, aux[entrada]); if(strcmp(anterior[entrada], linea[entrada]) >= 0) { if(!entrada) entrada = 1; else entrada = 0;

Page 183: 19189723 estructura-de-datos-programacion-facil

183

tramos++; do { strcpy(anterior[entrada], linea[entrada]); fputs(linea[entrada], fich); fgets(linea[entrada], 128, aux[entrada]); }while(!feof(aux[entrada]) && strcmp(anterior[entrada], linea[entrada]) <= 0); } } if(!feof(aux[0])) tramos++; while(!feof(aux[0])) { fputs(linea[0], fich); fgets(linea[0], 128, aux[0]); } if(!feof(aux[1])) tramos++; while(!feof(aux[1])) { fputs(linea[1], fich); fgets(linea[1], 128, aux[1]); } return(tramos == 1);

Page 184: 19189723 estructura-de-datos-programacion-facil

184

} }tec; main() { FILE *fichero; int res,op=0,b=0; while(op!=3) { clrscr(); cout<<"\n1) Recorrido Desordenado\n2) Recorrido Ordenado\n3) Salir"<<endl; gotoxy(1,1); cout<<"Que deseas hacer?: "; cin>>op; gotoxy(1,10); fichero = fopen("mezcla.txt", "r+"); switch (op) { case 1: if(b!=1) { b=1; tec.Mostrar(fichero); }

Page 185: 19189723 estructura-de-datos-programacion-facil

185

else cout<<"El Archivo ya esta Ordenado..."<<endl; break; case 2: tec.Mezcla(fichero); tec.Mostrar(fichero); break; case 3: cout<<"Salir..."<<endl; break; default: cout<<"Opcion Erronea..."<<endl; break; } fclose(fichero); getch(); } } Mezcla Directa Definición: Es una mejora del algoritmo de mezcla directa puesto que en vez de considerar tramos de tamaño fijo se toman en cuenta para la ordenación en todo momento tramos de longitud máxima. Al igual que el mezcla directa se debe hacer un proceso de partir el archivo original para mezclarlo, posteriormente mientras en el archivo C haya elementos a mezclar. Programa: #include <conio.h> #include <stdio.h>

Page 186: 19189723 estructura-de-datos-programacion-facil

186

#include <iostream.h> #include <string.h> void mezcla_directa(char *); void mezclar(char *, int ); void partir(char *, int ); void mezcla_simple(char *,char *,char *); void main(){ char n[10]="mezcla.txt"; mezcla_directa(n); getch(); } void mezcla_simple(char *A,char *B,char *C) { FILE *a,*b,*c; int ra,rb; a=fopen(A,"rb"); b=fopen(B,"rb"); c=fopen(C,"rb"); if(a&&b&&c) { fread(&ra,sizeof(ra),1,a); fread(&rb,sizeof(rb),1,b); while(!feof(a)&&!feof(b))

Page 187: 19189723 estructura-de-datos-programacion-facil

187

{ if(ra<=rb) { fwrite(&ra,sizeof(ra),1,c); fread(&ra,sizeof(ra),1,a); } else { fwrite(&rb,sizeof(rb),1,c); fread(&ra,sizeof(ra),1,b); } } while(!feof(a)) { fwrite(&ra,sizeof(ra),1,c); fread(&ra,sizeof(ra),1,a); } while(!feof(a)) { fwrite(&rb,sizeof(rb),1,c); fread(&rb,sizeof(rb),1,b); } fclose(a); fclose(b);

Page 188: 19189723 estructura-de-datos-programacion-facil

188

fclose(c); } } void mezcla_directa(char *nom){ int t=1, n=5; FILE *a,*b,*c; a=fopen(nom,"r+"); b=fopen("m1.txt","r+"); c=fopen("m2.txt","r+"); while(t<n){ partir(nom,t); mezcla_simple("m1.txt","m2.txt",nom); mezclar(nom,t); t = t* 2; } } void partir(char *nom, int t){ FILE *a,*b,*c; int reg, cont, sw=1; a=fopen(nom,"r+"); b=fopen("m1.txt","a+"); c=fopen("m2.txt","a+"); if(a&&b&&c){

Page 189: 19189723 estructura-de-datos-programacion-facil

189

fread(&reg,sizeof(reg),1,a); while(!feof(a)){ for(cont=0;cont<t && !feof(a);cont++){ if(sw) fwrite(&reg,sizeof(reg),1,b); else fwrite(&reg,sizeof(reg),1,c); fread(&reg,sizeof(reg),1,a); } sw=!sw ; } } fclose(a); fclose(b); fclose(c); } void mezclar(char *nom, int t){ FILE *a,*b,*c; int rb,rc,ctb,ctc; a= fopen(nom,"w+"); b= fopen("m1","r+"); c= fopen("m2","r+"); if(a&&b&&c){ fread(&rb,sizeof(rb),1,b);

Page 190: 19189723 estructura-de-datos-programacion-facil

190

fread(&rc,sizeof(rb),1,c); while(!feof(b) && !feof(c)){ ctb=ctc=t; while(ctb && ctc && !feof(b) && !feof(c)){ if(rb<rc){ fwrite(&rb,sizeof(rb),1,a); fread(&rb,sizeof(rb),1,b); ctb--; } else{ fwrite(&rc,sizeof(rc),1,a); fread(&rc,sizeof(rc),1,c); ctc--; } } while(ctb && !feof(b)){ fwrite(&rb,sizeof(rb),1,a); fread(&rb,sizeof(rb),1,b); ctb--; } while(ctc && !feof(c)){ fwrite(&rc,sizeof(rc),1,a); fread(&rc,sizeof(rc),1,c);

Page 191: 19189723 estructura-de-datos-programacion-facil

191

ctc--; } } while(!feof(b)){ fwrite(&rb,sizeof(rb),1,a); fread(&rb,sizeof(rb),1,b); } while(!feof(c)){ fwrite(&rc,sizeof(rc),1,a); fread(&rc,sizeof(rc),1,c); } } fclose(a); fclose(b); fclose(c); remove("m1"); remove("m2"); } Metodos de Busquedas Busqueda Secuencial Definicion: La búsqueda es el proceso de localizar un registro (elemento) con un valor de llave particular. La búsqueda termina exitosamente cuando se localiza el registro que contenga la llave buscada, o termina sin éxito, cuando se determina que no aparece ningún registro con esa llave. Búsqueda secuencial, también se le conoce como búsqueda lineal. Supongamos una colección de registros organizados como una lista lineal. El algoritmo básico de búsqueda secuencial consiste en empezar al inicio de la lista e ir a través de cada registro hasta encontrar la llave indicada (k), o hasta al final de la lista.

Page 192: 19189723 estructura-de-datos-programacion-facil

192

La situación óptima es que el registro buscado sea el primero en ser examinado. El peor caso es cuando las llaves de todos los n registros son comparados con k (lo que se busca). El caso promedio es n/2 comparaciones. Este método de búsqueda es muy lento, pero si los datos no están en orden es el único método que puede emplearse para hacer las búsquedas. Si los valores de la llave no son únicos, para encontrar todos los registros con una llave particular, se requiere buscar en toda la lista. Mejoras en la eficiencia de la búsqueda secuencial 1)Muestreo de acceso Este método consiste en observar que tan frecuentemente se solicita cada registro y ordenarlos de acuerdo a las probabilidades de acceso detectadas. 2)Movimiento hacia el frente Este esquema consiste en que la lista de registros se reorganicen dinámicamente. Con este método, cada vez que búsqueda de una llave sea exitosa, el registro correspondiente se mueve a la primera posición de la lista y se recorren una posición hacia abajo los que estaban antes que el. 3)Transposición Este es otro esquema de reorganización dinámica que consiste en que, cada vez que se lleve a cabo una búsqueda exitosa, el registro correspondiente se intercambia con el anterior. Con este procedimiento, entre mas accesos tenga el registro, mas rápidamente avanzara hacia la primera posición. Comparado con el método de movimiento al frente, el método requiere mas tiempo de actividad para reorganizar al conjunto de registros . Una ventaja de método de transposición es que no permite que el requerimiento aislado de un registro, cambie de posición todo el conjunto de registros. De hecho, un registro debe ganar poco a poco su derecho a alcanzar el inicio de la lista. 4)Ordenamiento Una forma de reducir el numero de comparaciones esperadas cuando hay una significativa frecuencia de búsqueda sin éxito es la de ordenar los registros en base al valor de la llave. Esta técnica es útil cuando la lista es una lista de excepciones, tales como una lista de decisiones, en cuyo caso la mayoría de las búsquedas no tendrán éxito. Con este método una búsqueda sin éxito termina cuando se encuentra el primer valor de la llave mayor que el buscado, en lugar de la final de la lista. Programa: #include <conio.h> #include <iostream.h> class Lista { private: int Lista[10],N; public: Lista() {

Page 193: 19189723 estructura-de-datos-programacion-facil

193

for(int i=0;i<10;i++) Lista[i]=0; N=0; } void Busqueda(int Elem) { if(N!=0) { for(int i=0;i<N;i++) if(Lista[i]==Elem) { cout<<"El "<<Elem<<" esta en la Lista"<<endl; return; } cout<<"El "<<Elem<<" no esta en la Lista"<<endl; return; } cout<<"Lista Vacia..."<<endl; return; } void Insertar(int Elem) { if(N<10)

Page 194: 19189723 estructura-de-datos-programacion-facil

194

{ Lista[N]=Elem; N++; cout<<"El "<<Elem<<" fue Insertado"<<endl; return; } cout<<"Lista Llena... Imposible Insertar"<<endl; return; } void Eliminar(int Elem) { if(N!=0) { for(int i=0;i<N;i++) if(Lista[i]==Elem) { Lista[i]=0; N--; return; } } cout<<"Lista Vacia... Imposible Eliminar..."<<endl; return; }

Page 195: 19189723 estructura-de-datos-programacion-facil

195

void Recorrido() { if(N!=0) { for(int i=0;i<N;i++) cout<<Lista[i]<<endl; } cout<<"Lista Vacia..."<<endl; } }tec; main() { int op=0,res; while(op!=5) { clrscr(); cout<<"\n1) Recorrido\n2) Busqueda\n3) Insercion\n4) Eliminar un Dato\n5) Salir"<<endl; gotoxy(1,1); cout<<"Que deseas hacer: "; cin>>op; gotoxy(1,10); switch (op) {

Page 196: 19189723 estructura-de-datos-programacion-facil

196

case 1: tec.Recorrido(); break; case 2: cout<<"Que Numero de Control deseas buscar?"<<endl; cin>>res; tec.Busqueda(res); break; case 3: cout<<"Que Numero Deseas Insertar?"<<endl; cin>>res; tec.Insertar(res); break; case 4: cout<<"Que Numero de Control deseas Eliminar?"<<endl; cin>>res; tec.Eliminar(res); break; case 5: cout<<"Salida..."; break; default: cout<<"Opcion Erronea"<<endl; break;

Page 197: 19189723 estructura-de-datos-programacion-facil

197

} getch(); } } CORRIDA:

Búsqueda Binaria Definicion: Se puede aplicar tanto a datos en listas lineales como en árboles binarios de búsqueda. Los prerrequisitos principales para la búsqueda binaria son: La lista debe estar ordenada en un orden especifíco de acuerdo al valor de la llave. Debe conocerse el número de registros. Algoritmo:

Se compara la llave buscada con la llave localizada al centro del arreglo. Si la llave analizada corresponde a la buscada fin de búsqueda si no. Si la llave buscada es menor que la analizada repetir proceso en mitad superior, sino en la mitad inferior. El proceso de partir por la mitad el arreglo se repite hasta encontrar el registro o hasta que el tamaño de la lista restante sea cero , lo cual implica que el valor de la llave buscada no esta en la lista.

Page 198: 19189723 estructura-de-datos-programacion-facil

198

El esfuerzo máximo para este algoritmo es de log2n. El mínimo de 1 y en promedio ½ log2 n. Programa: #include <conio.h> #include <iostream.h> class Lista { private: int Lista[10],N; public: Lista() { for(int i=0;i<10;i++) Lista[i]=0; N=0; } void Busqueda(int Elem) { if(N!=0) { int inicio=0,medio,final=9; while(inicio<=final) { medio=(inicio+final)/2; if(Elem==Lista[medio])

Page 199: 19189723 estructura-de-datos-programacion-facil

199

{ cout<<"El "<<Elem<<" esta en la Lista"<<endl; return; } else if(Elem<Lista[medio]) { final=medio-1; } else { inicio=medio+1; } } cout<<"El "<<Elem<<" no esta en la Lista"<<endl; return; } cout<<"Lista Vacia..."<<endl; return; } void Insertar(int Elem) { if(N<10) {

Page 200: 19189723 estructura-de-datos-programacion-facil

200

Lista[N]=Elem; N++; cout<<"El "<<Elem<<" fue Insertado"<<endl; return; } cout<<"Lista Llena... Imposible Insertar"<<endl; return; } void Eliminar(int Elem) { if(N!=0) { for(int i=0;i<N;i++) if(Lista[i]==Elem) { Lista[i]=0; N--; return; } } cout<<"Lista Vacia... Imposible Eliminar..."<<endl; return; } void Recorrido()

Page 201: 19189723 estructura-de-datos-programacion-facil

201

{ if(N!=0) { for(int i=0;i<N;i++) cout<<Lista[i]<<endl; } cout<<"Lista Vacia..."<<endl; } }tec; main() { int op=0,res; while(op!=5) { clrscr(); cout<<"\n1) Recorrido\n2) Busqueda\n3) Insercion\n4) Eliminar un Dato\n5) Salir"<<endl; gotoxy(1,1); cout<<"Que deseas hacer: "; cin>>op; gotoxy(1,10); switch (op) { case 1:

Page 202: 19189723 estructura-de-datos-programacion-facil

202

tec.Recorrido(); break; case 2: cout<<"Que Numero de Control deseas buscar?"<<endl; cin>>res; tec.Busqueda(res); break; case 3: cout<<"Que Numero Deseas Insertar?"<<endl; cin>>res; tec.Insertar(res); break; case 4: cout<<"Que Numero de Control deseas Eliminar?"<<endl; cin>>res; tec.Eliminar(res); break; case 5: cout<<"Salida..."; break; default: cout<<"Opcion Erronea"<<endl; break; }

Page 203: 19189723 estructura-de-datos-programacion-facil

203

getch(); } CORRIDA

}

Búsqueda por Hash Definicion: Hasta ahora las técnicas de localización de registros vistas, emplean un proceso de búsqueda que implica cierto tiempo y esfuerzo. El siguiente método nos permite encontrar directamente el registro buscado. La idea básica de este método consiste en aplicar una función que traduce un conjunto de posibles valores llave en un rango de direcciones relativas. Un problema potencial encontrado en este proceso, es que tal función no puede ser uno a uno; las direcciones calculadas pueden no ser todas únicas, cuando R(k1 )= R(k2) Pero : K1 diferente de K2 decimos que hay una colisión. A dos llaves diferentes que les corresponda la misma dirección relativa se les llama sinónimos. A las técnicas de calculo de direcciones también se les conoce como :

Técnicas de almacenamiento disperso Técnicas aleatorias Métodos de transformación de llave - a- dirección Técnicas de direccionamiento directo Métodos de tabla Hash Métodos de Hashing

Page 204: 19189723 estructura-de-datos-programacion-facil

204

Pero el término mas usado es el de hashing. Al cálculo que se realiza para obtener una dirección a partir de una llave se le conoce como función hash. Ventaja

1. Se pueden usar los valores naturales de la llave, puesto que se traducen internamente a direcciones fáciles de localizar

2. Se logra independencia lógica y física, debido a que los valores de las llaves son independientes del espacio de direcciones

3. No se requiere almacenamiento adicional para los índices. Desventajas

1. No pueden usarse registros de longitud variable 2. El archivo no esta clasificado 3. No permite llaves repetidas 4. Solo permite acceso por una sola llave

Costos Tiempo de procesamiento requerido para la aplicación de la función hash Tiempo de procesamiento y los accesos E/S requeridos para solucionar las colisiones.

La eficiencia de una función hash depende de: 1. La distribución de los valores de llave que realmente se usan 2. El numero de valores de llave que realmente están en uso con respecto al tamaño del espacio

de direcciones 3. El numero de registros que pueden almacenarse en una dirección dad sin causar una colisión 4. La técnica usada para resolver el problema de las colisiones

Las funciones hash mas comunes son: Residuo de la división Medio del cuadrado Pliegue

HASHING POR RESIDUO DE LA DIVISIÓN La idea de este método es la de dividir el valor de la llave entre un numero apropiado, y después utilizar el residuo de la división como dirección relativa para el registro (dirección = llave módulo divisor). Mientras que el valor calculado real de una dirección relativa, dados tanto un valor de llave como el divisor, es directo; la elección del divisor apropiado puede no ser tan simple. Existen varios factores que deben considerarse para seleccionar el divisor:

1. El rango de valores que resultan de la operación “llave % divisor”, va desde cero hasta el divisor 1. Luego, el divisor determina el tamaño del espacio de direcciones relativas. Si se sabe que el archivo va a contener por lo menos n registros, entonces tendremos que hacer que divisor > n, suponiendo que solamente un registro puede ser almacenado en una dirección relativa dada.

2. El divisor deberá seleccionarse de tal forma que la probabilidad de colisión sea minimizada. ¿Como escoger este numero? Mediante investigaciones se ha demostrado que los divisores que son números pares tienden a comportase pobremente, especialmente con los conjuntos de valores de llave que son predominantemente impares. Algunas investigaciones sugieren que el divisor deberá ser un numero primo. Sin embargo, otras sugieren que los divisores no primos trabajan también como los divisores primos, siempre y cuando los divisores no primos no contengan ningún factor primo menor de 20. Lo mas común es elegir el número primo mas próximo al total de direcciones.

Ejemplo:

Page 205: 19189723 estructura-de-datos-programacion-facil

205

Independientemente de que tan bueno sea el divisor, cuando el espacio de direcciones de un archivo esta completamente lleno, la probabilidad de colisión crece dramáticamente. La saturación de archivo de mide mediante su factor de carga, el cual se define como la relación del numero de registros en el archivo contra el numero de registros que el archivo podría contener si estuviese completamente lleno.

Todas las funciones hash comienzan a trabajar probablemente cuando el archivo esta casi lleno. Por lo general el máximo factor de carga que puede tolerarse en un archivo para un rendimiento razonable es de entre el 70 % y 80 %. HASHING POR MEDIO DEL CUADRADO En esta técnica, la llave es elevada al cuadrado, después algunos dígitos específicos se extraen de la mitad del resultado para constituir la dirección relativa. Si se desea una dirección de n dígitos, entonces los dígitos se truncan en ambos extremos de la llave elevada al cuadrado, tomando n dígitos intermedios. Las mismas posiciones de n dígitos deben extraerse para cada llave. Ejemplo: Utilizando esta función hashing el tamaño del archivo resultante es de 10n donde n es el numero de dígitos extraídos de los valores de la llave elevada al cuadrado. HASHING POR PLIEGUE En esta técnica el valor de la llave es particionada en varias partes, cada una de las cuales (excepto la ultima) tiene el mismo numero de dígitos que tiene la dirección relativa objetivo. Estas particiones son después plegadas una sobre otra y sumadas. El resultado, es la dirección relativa. Igual que para el método del medio del cuadrado, el tamaño del espacio de direcciones relativas es una potencia de 10. Ejemplo: COMPARACIÓN ENTRE LAS FUNCIONES HASH Aunque alguna otra técnica pueda desempeñarse mejor en situaciones particulares, la técnica del residuo de la división proporciona el mejor desempeño. Ninguna función hash se desempeña siempre mejor que las otras. El método del medio del cuadrado puede aplicarse en archivos con factores de cargas bastantes bajas para dar generalmente un buen desempeño. El método de pliegues puede ser la técnica mas fácil de calcular pero produce resultados bastante erráticos, a menos que la longitud de la llave se aproximadamente igual a la longitud de la dirección. Si la distribución de los valores de llaves no es conocida, entonces el método del residuo de la división es preferible. Note que el hashing puede ser aplicado a llaves no numéricas. Las posiciones de ordenamiento de secuencia de los caracteres en un valor de llave pueden ser utilizadas como sus equivalentes “numéricos”. Alternativamente, el algoritmo hash actúa sobre las representaciones binarias de los caracteres. Todas las funciones hash presentadas tienen destinado un espacio de tamaño fijo. Aumentar el tamaño del archivo relativo creado al usar una de estas funciones, implica cambiar la función hash, para que se refiera a un espacio mayor y volver a cargar el nuevo archivo. MÉTODOS PARA RESOLVER EL PROBLEMA DE LAS COLISIONES Considere las llaves K1 y K2 que son sinónimas para la función hash R. Si K1 es almacenada primero en el archivo y su dirección es R(K1), entonces se dice que K1 esta almacenado en su dirección de origen. Existen dos métodos básicos para determinar donde debe ser alojado K2 :

Direccionamiento abierto.- Se encuentra entre dirección de origen para K2 dentro del archivo. Separación de desborde (Area de desborde).- Se encuentra una dirección para K2 fuera del

área principal del archivo, en un área especial de desborde, que es utilizada exclusivamente para almacenar registro que no pueden ser asignados en su dirección de origen

Page 206: 19189723 estructura-de-datos-programacion-facil

206

Los métodos mas conocidos para resolver colisiones son: Sondeo lineal Que es una técnica de direccionamiento abierto. Este es un proceso de búsqueda secuencial desde la dirección de origen para encontrar la siguiente localidad vacía. Esta técnica es también conocida como método de desbordamiento consecutivo. Para almacenar un registro por hashing con sondeo lineal, la dirección no debe caer fuera del limite del archivo, En lugar de terminar cuando el limite del espacio de dirección se alcanza, se regresa al inicio del espacio y sondeamos desde ahí. Por lo que debe ser posible detectar si la dirección base ha sido encontrada de nuevo, lo cual indica que el archivo esta lleno y no hay espacio para la llave. Para la búsqueda de un registro por hashing con sondeo lineal, los valores de llave de los registros encontrados en la dirección de origen, y en las direcciones alcanzadas con el sondeo lineal, deberá compararse con el valor de la llave buscada, para determinar si el registro objetivo ha sido localizado o no.

El sondeo lineal puede usarse para cualquier técnica de hashing. Si se emplea sondeo lineal para almacenar registros, también deberá emplearse para recuperarlos.

Doble hashing En esta técnica se aplica una segunda función hash para combinar la llave original con el resultado del primer hash. El resultado del segundo hash puede situarse dentro del mismo archivo o en un archivo de sobreflujo independiente; de cualquier modo, será necesario algún método de solución si ocurren colisiones durante el segundo hash. La ventaja del método de separación de desborde es que reduce la situación de una doble colisión, la cual puede ocurrir con el método de direccionamiento abierto, en el cual un registro que no esta almacenado en su dirección de origen desplazara a otro registro, el que después buscará su dirección de origen. Esto puede evitarse con direccionamiento abierto, simplemente moviendo el registro extraño a otra localidad y almacenando al nuevo registro en la dirección de origen ahora vacía. Puede ser aplicado como cualquier direccionamiento abierto o técnica de separación de desborde. Para ambas métodos para la solución de colisiones existen técnicas para mejorar su desempeño como: 1.- Encadenamiento de sinónimos Una buena manera de mejorar la eficiencia de un archivo que utiliza el calculo de direcciones, sin directorio auxiliar para guiar la recuperación de registros, es el encadenamiento de sinónimos. Mantener una lista ligada de registros, con la misma dirección de origen, no reduce el numero de colisiones, pero reduce los tiempos de acceso para recuperar los registros que no se encuentran en su localidad de origen. El encadenamiento de sinónimos puede emplearse con cualquier técnica de solución de colisiones. Cuando un registro debe ser recuperado del archivo, solo los sinónimos de la llave objetivo son accesados. 2.- Direccionamiento por cubetas Otro enfoque para resolver el problema de las colisiones es asignar bloques de espacio (cubetas), que pueden acomodar ocurrencias múltiples de registros, en lugar de asignar celdas individuales a registros. Cuando una cubeta es desbordada, alguna nueva localización deberá ser encontrada para el registro. Los métodos para el problema de sobrecupo son básicamente los mismo que los métodos para resolver colisiones. COMPARACIÓN ENTRE SONDEO LINEAL Y DOBLE HASHING

Page 207: 19189723 estructura-de-datos-programacion-facil

207

De ambos métodos resultan distribuciones diferentes de sinónimos en un archivo relativo. Para aquellos casos en que el factor de carga es bajo (< 0.5), el sondeo lineal tiende a agrupar los sinónimos, mientras que el doble hashing tiende a dispersar los sinónimos mas ampliamente a travéz del espacio de direcciones. El doble hashing tiende a comportarse casi también como el sondeo lineal con factores de carga pequeños (< 0.5), pero actúa un poco mejor para factores de carga mayores. Con un factor de carga > 80 %, el sondeo lineal por lo general resulta tener un comportamiento terrible, mientras que el doble hashing es bastante tolerable para búsquedas exitosas pero no así en búsquedas no exitosas. Unidad 9: Grafos Definicion: Un grafo dirigido G consiste en un conjunto de vértices V y un conjunto de arcos o aristas A. Los vertice se denominan también nodos o puntos. Un arco, es un par ordenado de vértices(V,W) donde V es el vértice inicial y W es el vértice terminal del arco. Un arco se expresa como: V–>W y se representa de la siguiente manera:

Los vértice de un grafo pueden usarse para representar objetos. Los arcos se utilizan para representar relaciones entre estos objetos. Las aplicaciones más importantes de los grafos son las siguientes: Rutas entre ciudades. Determinar tiempos máximos y mínimos en un proceso. Flujo y control en un programa. Operaciones Sobre Grafos: En esta sección analizaremos algunas de las operaciones sobre grafos, como : Creación. Inserción. Búsqueda. Eliminación. En esta sección, continuaremos utilizando los apuntadores que se usaron en las secciones anteriores. TOP para hacer referencia al primer nodo, LD para indicar liga derecha y LA para indicar liga abajo, por último usaremos los apuntadores P y Q para hacer referencia a los nuevos nodos que vayan a ser usados. ALGORITMO DE CREACION.

repite si top=NIL entonces new(top) top(la)←NIL top(ld)←NIL lee(top(dato)) q←top en caso contrario new(p) p(ld)←NIL p(la)←NIL q(la)←p lee(p(dato)) q←-p

Page 208: 19189723 estructura-de-datos-programacion-facil

208

mensaje(otro vertice ?) lee(respuesta) hasta repuesta=no p←top mientras p<>NIL haz mensaje(tiene vértices adyacentes p(dato) ?) lee(respuesta) si respueta=si entonces repite new(q) lee(q(dato)) q(ld)←p(ld) p(ld)←q mensaje(otro vértice ?) lee(respuesta2) hasta respuesta2=no p←p(la)

ALGORITMO DE INSERCION

mensaje(valor a insertar ?) lee(valor_a_insertar) si top<>NIL entonces p←top mientras p(la)<>NIL haz p←p(la) new(q) lee(q(dato)) p(la)←q q(la)←NIL mensaje(Hay vértices adyacentes?) lee(respuesta) si respuesta=si entonces mensaje(Cuantos vértices?) lee(número_vértices) desde i=1 hasta número_vértices haz new(p) lee(p(dato)) q(ld)←p q←q(ld) en caso contrario mensaje(no existe lista)

ALGORITMO DE BUSQUEDA

mensaje(vértice a buscar) lee(vértice_a_buscar)

Page 209: 19189723 estructura-de-datos-programacion-facil

209

p←top repite si p(dato)=vértice_a_buscar entonces repite p←p(ld) escribe(p(dato)) hasta p(ld)=NIL en caso contrario p←(la) hasta p=NIL

ALGORITMO DE BORRADO

mensaje(vértice a borrar ?) lee(vértice_a_borrar) p←top r←p q←p sw←falso repite si p(dato)=vértice_a_borrar entonces si p=top entonces top←top(la) r←top sw←verdadero en caso contrario r(la)←p(la) repite p←p(ld) dispose(q) q←p hasta p=NIL si sw=verdadero entonces p←r q←p en caso contrario p←r(la) q←p en caso contrario r←p repite q←p(ld) si q(dato)=vértice_a_borrar entonces p(ld)←q(ld) dispose(q) q←p en caso contrario

Page 210: 19189723 estructura-de-datos-programacion-facil

210

p←p(ld) hasta p=NIL

Camino Mínimo: Se denomina camino mínimo entre dos vértices V y W, al camino óptimo entre ambos vértices.Para determinar el camino mínimo entre dos vértices se utiliza el siguiente algoritmo:

desde i=1 hasta número_vértices haz desde j=1 hasta número_vértices haz si w[i,j]=0 entonces q**i,j+←infinito en caso contrario q*i,j+←w*i,j+ desde k=1 hasta número_vértices haz desde i=1 hasta número_vértices haz desde j=1 hasta número_vértices haz q*i,j+←min(q*i,j+, q*i,k+ + q*k,j+)