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:
1
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.
2
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
3
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:
4
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 ≠ Nulo
Imprimir Pila[Apuntador]
Apuntador ←- Apuntador - 1
Fin del ciclo
Salir
Diagrama:
5
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 ≠ Max
Top ←- Top + 1
Pila[Top] ←- Elemento
Si no:
Imprimir “Pila Llena”
Salir
Diagrama:
6
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 ≠ Nulo
Imprimir Pila[Top]
Top ←- Top - 1
Si no:
Imprimir “Pila Vacía”
Salir
Diagrama:
7
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 ≠ Nulo
Apuntador ←- Top
Repetir mientras Apuntador ≠ Nulo
Si Pila[Apuntador] = Elemento
Imprimir “El Dato fue encontrado” y Salir
Apuntador ←- Apuntador - 1
Fin del ciclo
8
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 ≠ Nulo
9
10. Apuntador1 ←- Top
Repetir mientras Apuntador1 ≠ Nulo
Si Pila[Apuntador1] = Elemento
Imprimir “Eliminando el Dato…”
Repetir mientras Apuntador2 ≠ 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:
10
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);
}
11
21. }tec;
main()
{
int res,op=0;
while(op!=6)
{
clrscr();
cout<<"n1) Recorridon2) Busquedan3) Pushn4) Popn5) Eliminar un Daton6) 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:
21
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:
22
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:
23
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)
24
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:
25
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
26
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
27
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:
28
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:
29
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:
30
50. else
cout<<"Cola Vacia... Imposible Eliminar...";
}
}tec;
main()
{
int res,op=0;
while(op!=6)
{
clrscr();
cout<<"n1) Recorridon2) Busquedan3) Pushn4) Popn5) Eliminar un Daton6) 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;
50
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();
}
51
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>
52
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:
54
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:
55
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:
56
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
58
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:
59
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 Originaln";
Recorrido(Info,Indice,Inicio,Disp);
cout<<"Que Numero deseas Insertar?";
cin>>Elemento;
60
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
63
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 Originaln";
Recorrido(Info,Indice,Inicio,Disp);
cout<<"Que Numero deseas Eliminar?";
64
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];
}
73
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)
{
74
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 Inicion2) Recorrido por Finaln3) Busquedan";
cout<<"4) Insercionn5) Eliminar un Daton6) Salir"<<endl;
gotoxy(1,1);
cout<<"Que deseas hacer: ";
cin>>op;
gotoxy(1,10);
80
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);
81
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+
82
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);
83
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
84
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)
85
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:
87
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 Originaln";
Recorrido(Info,Indice,Inicio,Disp);
cout<<"Que Numero deseas Insertar?";
cin>>Elemento;
InsPr(Info,Indice,Inicio,Disp,Elemento);
88
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+
90
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:
91
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:
95
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:
98
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:
99
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:
100
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;
108
115. {
int op=0,res;
char inom[30];
int in_c,iedad;
while(op!=6)
{
clrscr();
cout<<"n1) Recorrido por Inicion2) Recorrido por Finaln3) Busquedan";
cout<<"4) Insercionn5) Eliminar un Daton6) 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;
115
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:
116
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);
117
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 Multiplicarn2) Factorial de un Numeron";
cout<<"3) Formula Linealn4) Torres de Hanoin5) Salida"<<endl;
gotoxy(1,1);
cout<<"Que deseas hacer: ";
cin>>op;
clrscr();
switch(op)
{
case 1:
119
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:
120
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]
121
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.
122
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:
123
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
124
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:
125
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
126
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:
127
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;
128
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;
140
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)
141
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
142
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:
143
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..."
144
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:
145
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..."
146
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
147
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;
148
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;
154
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;
155
159. }
}tec;
main()
{
int op=0,res;
while(op!=6)
{
clrscr();
cout<<"n1) Recorridon2) Ordenarn3) Busquedan4) Insercionn5) Eliminar un Daton6) 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;
159
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:
160
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++)
161
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:
165