material didactico programacion ii
TRANSCRIPT
-
8/3/2019 Material Didactico Programacion II
1/83
-
8/3/2019 Material Didactico Programacion II
2/83
ndice
Recopilado por: Docentes del rea de Programacin / Trayecto I / Trimestre IIIMdulo: Programacin II Pgina 1
PginaUnidad I.- Archivos
Introduccin 4Tipos de archivos 4
Archivos de Texto. Operaciones que se realizan sobre ellos 10
Archivos Binarios. Operaciones que se realizan sobre ellos 14
Ejemplos de Programas de Archivos y manipulacin 17
Unidad II.- Listas Enlazadas Simples, Dobles y CircularesIntroduccin 21
Generalidades 22
Listas Enlazadas Simples 23Conformacin de las Listas Enlazadas Simples 24
Operaciones a realizar en una Lista Enlazada Simple 24
Ejemplos de Listas Enlazadas Simples 29
Listas Enlazadas Dobles 32
Conformacin de las Listas Enlazadas Dobles 32
Operaciones a realizar en una Lista Enlazada Dobles 33
Ejemplos de Listas Enlazadas Dobles 39Listas Enlazadas Circulares 42
Conformacin de las Listas Enlazadas Circulares 42
Operaciones a realizar en una Lista Enlazada Circular 43
Ejemplos de Listas Enlazadas Circulares 46
Unidad III.- Pilas y ColasIntroduccin 50Pilas 51
Conformacin de una Pila 51Operaciones a realizar en una Pila 51
Ejemplo de una Pila 52
Colas 54
Conformacin de una Cola 54
Operaciones a realizar en una Cola 55
Ejemplo de una Cola 57
-
8/3/2019 Material Didactico Programacion II
3/83
ndice
Recopilado por: Docentes del rea de Programacin / Trayecto I / Trimestre IIIMdulo: Programacin II Pgina 2
Unidad IV.- rbolesIntroduccin 59
Definicin de rbol 60Conceptos Bsicos a manejar 60
Recorridos 62
rboles Ordenados 64
rboles Binarios de Bsqueda (ABB) 66
Operaciones a realizar en los rboles Binarios de Bsqueda (ABB) 66
Ejemplo de un rbol Binario de Bsqueda (ABB) 76
-
8/3/2019 Material Didactico Programacion II
4/83
Unidad I.- Archivos
Recopilado por: Docentes del rea de Programacin / Trayecto I / Trimestre IIIMdulo: Programacin II Pgina 3
Conceptos Bsicos
Durante la historia de los computadores se han usado varios mtodosdistintos para el almacenamiento de datos. Al principio se recurri a cintas
de papel perforadas, despus a tarjetas perforadas. A continuacin se
pas al soporte magntico, empezando por grandes rollos de cintas
magnticas abiertas.
Hasta aqu, todos los sistemas de almacenamiento externo eran
secuenciales, es decir, no permitan acceder al punto exacto donde seguardaba la informacin sin antes haber partido desde el principio y sin
haber ledo toda la informacin, hasta el punto donde se encontraba lo
que estbamos buscando.
Con las cintas magnticas empez lo que con el tiempo sera el
acceso aleatorio a los datos. Se poda reservar parte de la cinta para
guardar cierta informacin sobre la situacin de los datos, y aadir ciertas
marcas que hicieran ms sencillo localizarla.
Pero no fu hasta la aparicin de los discos magnticos cuando sta
tcnica lleg a su sentido ms amplio. En los discos es ms sencillo acceder
a cualquier punto de la superficie en poco tiempo, ya que se accede al
punto de lectura y escritura usando dos coordenadas fsicas. Por una parte
la cabeza de lectura/escritura se puede mover en el sentido del radio del
disco, y por otra el disco gira permanentemente, con lo que cualquier
punto del disco pasa por la cabeza en un tiempo relativamente corto. Esto
no pasa con las cintas, donde slo hay una coordenada fsica.
-
8/3/2019 Material Didactico Programacion II
5/83
Unidad I.- Archivos
Recopilado por: Docentes del rea de Programacin / Trayecto I / Trimestre IIIMdulo: Programacin II Pgina 4
Con la invencin y proliferacin de los discos se desarrollaron los
archivos o archivos de acceso aleatorio, que permiten acceder a
cualquier dato almacenado en un archivo en relativamente poco tiempo.
Actualmente, los discos duros tienen una enorme capacidad y son
muy rpidos, aunque an siguen siendo lentos, en comparacin con las
memorias RAM. El caso de los CD es algo intermedio. En realidad son
secuenciales en cuanto al modo de guardar los datos, cada disco slo
tiene una pista de datos grabada en espiral. Sin embargo, este sistema,
combinado con algo de memoria RAM, proporciona un acceso muy
prximo al de los discos duros.
Los datos que hemos tratado hasta el momento han residido en la
memoria principal. Sin embargo, las grandes cantidades de datos se
almacenan normalmente en un dispositivo de memoria secundaria.
Estas colecciones de datos se conocen como archivos. Un archivo es
un conjunto de datos estructurados en una coleccin de entidades
elementales o bsicas denominadas registros que son de igual tipo y
constan a su vez de diferentes entidades de nivel ms bajos denominadas
campos.
Tipos de Archivos
1. Dependiendo de la direccin del flujo de datos:o De entrada: los datos se leen por el programa desde el
archivo.
o De salida: los datos se escriben por el programa hacia elarchivo.
o De entrada/salida: los datos pueden ser escritos o ledos.
-
8/3/2019 Material Didactico Programacion II
6/83
Unidad I.- Archivos
Recopilado por: Docentes del rea de Programacin / Trayecto I / Trimestre IIIMdulo: Programacin II Pgina 5
2. Dependiendo del tipo de valores permitidos a cada byte:o De texto: slo estn permitidos ciertos rangos de valores para
cada byte. Algunos bytes tienen un significado especial, por
ejemplo, el valor hexadecimal 0x1A marca el fin de archivo. Si
abrimos un archivo en modo texto, no ser posible leer ms
all de un byte con ese valor, aunque el archivo sea ms
largo.
o Binarios: estn permitidos todos los valores para cada byte. Enestos archivos el final del archivo se detecta de otro modo,
dependiendo del soporte y del sistema operativo. La mayora
de las veces se hace guardando la longitud del archivo.
Cuando queramos almacenar valores enteros, o en coma
flotante, o imgenes, etc., deberemos usar este tipo de
archivos.
3. Segn el tipo de acceso:o Archivos secuenciales: imitan el modo de acceso de los
antiguos archivos secuenciales almacenados en cintas
magnticas y
o Archivos de acceso aleatorio: permiten acceder a cualquierpunto de ellos para realizar lecturas y/o escrituras.
4. Segn la longitud de registro:o Longitud variable: en realidad, en este tipo de archivos no
tiene sentido hablar de longitud de registro, podemos
considerar cada byte como un registro. Tambin puede
suceder que nuestra aplicacin conozca el tipo y longitud de
cada dato almacenado en el archivo, y lea o escriba los bytes
necesarios en cada ocasin. Otro caso es cuando se usa una
marca para el final de registro, por ejemplo, en archivos de
-
8/3/2019 Material Didactico Programacion II
7/83
Unidad I.- Archivos
Recopilado por: Docentes del rea de Programacin / Trayecto I / Trimestre IIIMdulo: Programacin II Pgina 6
texto se usa el carcter de retorno de lnea para eso. En estos
casos cada registro es de longitud diferente.
o Longitud constante: en estos archivos los datos se almacenanen forma de registro de tamao contante. En C usaremos
estructuras para definir los registros. C dispone de funciones de
librera adecuadas para manejar este tipo de archivos.
o Mixtos: en ocasiones pueden crearse archivos que combinenlos dos tipos de registros, por ejemplo, dBASE usa registros de
longitud constante, pero aade un registro especial de
cabecera al principio para definir, entre otras cosas, el tamao
y el tipo de los registros.
Es posible crear archivos combinando cada una de estas categoras,
por ejemplo: archivos secuenciales de texto de longitud de registro
variable, que son los tpicos archivos de texto. Archivos de acceso aleatorio
binarios de longitud de registro constante, normalmente usados en bases
de datos. Y tambin cualquier combinacin menos corriente, como
archivos secuenciales binarios de longitud de registro constante, etc.
En cuanto a cmo se definen estas propiedades, hay dos casos: Si
son binarios o de texto o de entrada, salida o entrada/salida,
Un Flujo (Stream), no es ms que una abstraccin que se refiere a
una corriente de datos que fluyen entre un origen o fuente (productor) y un
destino o sumidero (consumidor), entre el origen y el destino debe existir
una conexin o canal (pipe) por la que circulen los datos. La apertura de
un archivo supone establecer la conexin del programa con el dispositivo
que contiene el archivo, por el canal que comunica el archivo con el
programa van a fluir las secuencias de datos. Hay tres flujos o canales
abiertos automticamente:
-
8/3/2019 Material Didactico Programacion II
8/83
Unidad I.- Archivos
Recopilado por: Docentes del rea de Programacin / Trayecto I / Trimestre IIIMdulo: Programacin II Pgina 7
extern FILE *stdin;
extern FILE *stdout;
extern FILE *stderr;
Estas tres variables se inicializan al comenzar la ejecucin del
programa para admitir secuencias de caracteres, en modo texto. Su
contenido es el siguiente:
stdin asocia la entrada estndar (teclado) con el programa.
stdout asocia la salida estndar (pantalla) con el programa.
stderr asocia la salida de mensajes de error (pantalla) con el
programa.
Asi cuando se ejecuta printf(Calle Mayor 2.); se escribe en stdout,
en pantalla; si se desea leer una variable entera con scanf(%d,&x); secaptan los dgitos de la secuencia de entrada stdin. El acceso a archivos
se hace con un buffer intermedio. Se puede pensar en el buffer como un
array donde se van almacenando los datos dirigidos al archivo, o desde el
archivo; el buffer se vuelca cuando de una forma u otra se da la orden de
vaciarlo. Por ejemplo, cuando se llama a una funcin para leer del archivo
una cadena, la funcin lee tantos caracteres como quepan en el buffer. A
continuacin se obtiene la cadena del buffer; una posterior llamada a la
funcin obtendr la siguiente cadena del buffer y as sucesivamente hasta
que quede vaco y se llene con una llamada posterior a la funcin de
lectura. El C trabaja con archivos con buffer, y est diseado para
acceder a una amplia gama de dispositivos, de tal forma que trata cada
dispositivo como una secuencia, pudiendo haber secuencias de
-
8/3/2019 Material Didactico Programacion II
9/83
Unidad I.- Archivos
Recopilado por: Docentes del rea de Programacin / Trayecto I / Trimestre IIIMdulo: Programacin II Pgina 8
caracteres y secuencias binarias. Con las secuencias se simplifica el
manejo de archivos en C.
En el programa el archivo tiene un nombre interno que es un puntero
a una estructura predefinida (puntero a archivo). Esta estructura contiene
la informacin sobre el archivo, tal como la direccin del buffer que utiliza,
el modo de apertura del archivo, el ltimo carcter ledo del buffer y otros
detalles que generalmente el usuario no necesita saber. El identificador del
tipo de la estructura es FILE y est declarada en el archivo de cabecera
stdio.h
Ejemplo:
FILE *pf;
Apertura de un archivo
Sintaxis:
FILE *fopen(char *nombre, char *modo);
Esta funcin sirve para abrir y crear archivos en disco. El valor de retorno
es un puntero a una estructura FILE. Los parmetros de entrada son:
1. nombre: una cadena que contiene un nombre de archivo vlido,esto depende del sistema operativo que estemos usando. El nombre
puede incluir el camino completo.
2. modo: especifica en tipo de archivo que se abrir o se crear y eltipo de datos que puede contener, de texto o binarios:
o r: slo lectura. El archivo debe existir.o w: se abre para escritura, se crea un archivo nuevo o se
sobreescribe si ya existe.
-
8/3/2019 Material Didactico Programacion II
10/83
Unidad I.- Archivos
Recopilado por: Docentes del rea de Programacin / Trayecto I / Trimestre IIIMdulo: Programacin II Pgina 9
o a: aadir, se abre para escritura, el cursor se sita al final delarchivo. Si el archivo no existe, se crea.
o r+: lectura y escritura. El archivo debe existir.o w+: lectura y escritura, se crea un archivo nuevo o se
sobrescribe si ya existe.
o a+: aadir, lectura y escritura, el cursor se sita al final delarchivo. Si el archivo no existe, se crea.
o t: tipo texto, si no se especifica "t" ni "b", se asume por defectoque es "t"
o b: tipo binario.
Ejemplo:
FILE *archivo;archivo = fopen("ejemplo1.c", "r");
Clausura de un archivo
Sintaxis:
int fclose(FILE *archivo);
Es importante cerrar los archivos abiertos antes de abandonar la
aplicacin. Esta funcin sirve para eso. Cerrar un archivo almacena los
datos que an estn en el buffer de memoria, y actualiza algunos datos de
la cabecera del archivo que mantiene el sistema operativo.
Adems permite que otros programas puedan abrir el archivo para
su uso. Muy a menudo, los archivos no pueden ser compartidos por varios
programas.
Un valor de retorno cero indica que el archivo ha sido
correctamente cerrado, si ha habido algn error, el valor de retorno es la
-
8/3/2019 Material Didactico Programacion II
11/83
Unidad I.- Archivos
Recopilado por: Docentes del rea de Programacin / Trayecto I / Trimestre IIIMdulo: Programacin II Pgina 10
constante EOF. El parmetro es un puntero a la estructura FILE del archivo
que queremos cerrar.
Ejemplo:
fclose(archivo);
NULL y EOF
Las funciones de biblioteca que devuelvan un puntero (strcpy(),
fopen()) especifican que si no pueden realizar la operacin
(generalmente si hay un error) devuelven NULL. Esta es una macro definidaen varios archivos de cabecera, entre los que se encuentran stdio.h y
stdlib.h. Las funciones de librera de E/S de archivos generalmente
empiezan por f de file, tienen especificado que son de tipo entero de tal
forma que si la operacin falla devuelven EOF, tambin devuelven EOF
para indicar que se ha ledo el fin de archivo.
Esta macro est definida en stdio.h
Archivos de Texto
Un archivo de texto es una secuencia de caracteres organizadas en
lneas terminadas por un carcter de nueva lnea. En estos archivos se
pueden almacenar canciones, fuentes de programas, base de datos
simples, etc. Los archivos de texto se caracterizan por ser planos, es decir,todas las letras tienen el mismo formato y no hay palabras subrayadas, en
negrita, o letras de distinto tamao o ancho. Una vez abierto el archivo
para escribir datos hay que grabar los datos en el archivo. La biblioteca C
proporciona diversas funciones para escribir datos en el archivo a travs
del puntero a FILE asociado. Las funciones de entrada y salida de archivos
-
8/3/2019 Material Didactico Programacion II
12/83
Unidad I.- Archivos
Recopilado por: Docentes del rea de Programacin / Trayecto I / Trimestre IIIMdulo: Programacin II Pgina 11
tienen mucho parecido a las funciones utilizadas para entrada y salida de
flujos stdin (teclado) y stdout (pantalla); printf(), scanf(), getchar(),
putchar(), gets() y puts(). Todas tienen una versin para archivos que
empieza por la letra f, as se tiene fprintf(), fscanf(), fputs(), fgets(); la
mayora de las funciones especficas de archivos empiezan por f.
Funciones putc() y fputc()
Sintaxis
putc(int caracter, FILE *archivo);
fputc(int caracter, FILE *archivo);
Estas funciones escriben un carcter a un archivo. El valor de retorno
es el carcter escrito, si la operacin fue completada con xito, en caso
contrario ser EOF. Los parmetros de entrada son el carcter a escribir,
convertido a int y un puntero a una estructura FILE del archivo en el que se
har la escritura.
Funciones getc() y fgetc()
Sintaxis
getc( FILE *archivo);
fgetc(FILE *archivo);
Estas funciones leen un carcter desde un archivo. El valor de retornoes el carcter ledo como un unsigned char convertido a int. Si no hay
ningn carcter disponible, el valor de retorno es EOF. El parmetro es un
puntero a una estructura FILE del archivo del que se har la lectura.
-
8/3/2019 Material Didactico Programacion II
13/83
Unidad I.- Archivos
Recopilado por: Docentes del rea de Programacin / Trayecto I / Trimestre IIIMdulo: Programacin II Pgina 12
Funciones fputs() y fgets()
Sintaxis
fputs(const char *cadena, FILE *archivo);
fgetc(const char *cadena, int n, FILE *archivo);
La funcin fputs escribe una cadena en un archivo. No se aade el
carcter de retorno de lnea ni el carcter nulo final.
El valor de retorno es un nmero no negativo o EOF en caso de error.
Los parmetros de entrada son la cadena a escribir y un puntero a la
estructura FILE del archivo donde se realizar la escritura.
La funcin fgets est diseada para leer cadenas de caracteres.
Leer hasta n-1 caracteres o hasta que lea un retorno de lnea. En este
ltimo caso, el carcter de retorno de lnea tambin es ledo.
El parmetro n nos permite limitar la lectura para evitar desbordar el
espacio disponible en la cadena.
El valor de retorno es un puntero a la cadena leda, si se ley con
xito, y es NULL si se detecta el final del archivo o si hay un error. Los
parmetros son: la cadena a leer, el nmero de caracteres mximo a leer
y un puntero a una estructura FILE del archivo del que se leer.
Funciones fprintf() y fscanf()
Sintaxis
int fprintf(FILE *archivo, const char *formato, ...);
-
8/3/2019 Material Didactico Programacion II
14/83
Unidad I.- Archivos
Recopilado por: Docentes del rea de Programacin / Trayecto I / Trimestre IIIMdulo: Programacin II Pgina 13
int fscanf(FILE *archivo, const char *formato, ...);
La funcin fprintf funciona igual que printf en cuanto a parmetros,
pero la salida se dirige a un archivo en lugar de a la pantalla.
La funcin fscanf funciona igual que scanf en cuanto a parmetros,
pero la entrada se toma de un archivo en lugar del teclado.
Funcin feof()
Sintaxis
int feof(FILE *archivo);
Esta funcin sirve para comprobar si se ha alcanzado el final del
archivo. Muy frecuentemente deberemos trabajar con todos los valores
almacenados en un archivo de forma secuencial, la forma que suelen
tener los bucles para leer todos los datos de un archivo es permanecer
leyendo mientras no se detecte el fin de archivo. Esta funcin suele usarse
como prueba para verificar si se ha alcanzado o no ese punto.
El valor de retorno es distinto de cero slo si no se ha alcanzado el fin
de archivo. El parmetro es un puntero a la estructura FILE del archivo que
queremos verificar.
Funcin rewind()
Sintaxis
void rewind(FILE *archivo)
-
8/3/2019 Material Didactico Programacion II
15/83
Unidad I.- Archivos
Recopilado por: Docentes del rea de Programacin / Trayecto I / Trimestre IIIMdulo: Programacin II Pgina 14
Es una funcin heredada de los tiempos de las cintas magnticas.
Literalmente significa "rebobinar", y hace referencia a que para volver al
principio de un archivo almacenado en cinta, haba que rebobinarla. Eso
es lo que hace sta funcin, sita el cursor de lectura/escritura al principio
del archivo.
El parmetro es un puntero a la estructura FILE del archivo que
queremos rebobinar.
Archivos Binarios
Un archivo binario es una secuencia de bytes que tienen una
correspondencia uno a uno con un dispositivo externo. As que no tendr
lugar ninguna traduccin de caracteres. Adems, el nmero de bytes
escritos (ledos) ser el mismo que los encontrados en el dispositivo externo.
Ejemplos de estos archivos son Fotografas, imgenes, texto con formatos,
archivos ejecutables (aplicaciones), etc.
Funcin de Salida fwrite()
Sintaxis
fwrite(void *puntero, size_t tamao, size_t nregistros, FILE *archivo);
Esta funcin tambin est pensada para trabajar con registros delongitud constante y forma pareja con fread. Es capaz de escribir hacia un
archivo uno o varios registros de la misma longitud almacenados a partir
de una direccin de memoria determinada.
El valor de retorno es el nmero de registros escritos, no el nmero de
bytes. Los parmetros son: un puntero a la zona de memoria donde se
-
8/3/2019 Material Didactico Programacion II
16/83
Unidad I.- Archivos
Recopilado por: Docentes del rea de Programacin / Trayecto I / Trimestre IIIMdulo: Programacin II Pgina 15
almacenarn los datos ledos, el tamao de cada registro, el nmero de
registros a leer y un puntero a la estructura FILE del archivo del que se har
la lectura.
Funcin de Entrada fread()
Sintaxis
fread(void *puntero, size_t tamao, size_t nregistros, FILE *archivo);
Esta funcin est pensada para trabajar con registros de longitud
constante. Es capaz de leer desde un archivo uno o varios registros de la
misma longitud y a partir de una direccin de memoria determinada. El
usuario es responsable de asegurarse de que hay espacio suficiente para
contener la informacin leda.
El valor de retorno es el nmero de registros ledos, no el nmero de
bytes. Los parmetros son: un puntero a la zona de memoria donde se
almacenarn los datos ledos, el tamao de cada registro, el nmero de
registros a leer y un puntero a la estructura FILE del archivo del que se har
la lectura.
Funciones para el acceso aleatorio
El acceso directo aleatorio a los datos de un archivo se hace
mediante su posicin, es decir, el lugar relativo que ocupan. Tiene la
ventaja de que se pueden leer y escribir registros en cualquier orden y
posicin. Son muy rpidos de acceso a la informacin que contienen.
-
8/3/2019 Material Didactico Programacion II
17/83
Unidad I.- Archivos
Recopilado por: Docentes del rea de Programacin / Trayecto I / Trimestre IIIMdulo: Programacin II Pgina 16
El principal inconveniente que tiene la organizacin directa es que
necesita programar la relacin existente entre el contenido de un registro y
la posicin que ocupan. Las funciones fseek() y ftell() se usan
principalmente para el acceso directo a archivos en C. stas consideran el
archivo como una secuencia de bytes; el nmero de bytes es el ndice del
archivo. Segn se va leyendo o escribiendo registros o datos en el archivo,
el programa mantiene a travs de un puntero la posicin actual. Con la
llamada a la funcin ftell() se obtiene el valor de dicha posicin. La funcin
fseek() permite cambiar la posicin del puntero a archivo a una direccin
determinada.
Funcin fseek()
Sintaxis
fseek(FILE *archivo, long int desplazamiento, int origen);
Esta funcin sirve para situar el cursor del archivo para leer o escribir
en el lugar deseado. El valor de retorno es cero si la funcin tuvo xito, y un
valor distinto de cero si hubo algn error. Los parmetros de entrada son:
un puntero a una estructura FILE del archivo en el que queremos cambiar
el cursor de lectura/escritura, el valor del desplazamiento y el punto de
origen desde el que se calcular el desplazamiento. El parmetro origen
puede tener tres posibles valores:
SEEK_SETel desplazamiento se cuenta desde el principio del archivo.
El primer byte del archivo tiene un desplazamiento cero.
SEEK_CUR el desplazamiento se cuenta desde la posicin actual del
cursor.
-
8/3/2019 Material Didactico Programacion II
18/83
Unidad I.- Archivos
Recopilado por: Docentes del rea de Programacin / Trayecto I / Trimestre IIIMdulo: Programacin II Pgina 17
SEEK_END el desplazamiento se cuenta desde el final del archivo.
Funcin ftell()
Sintaxis
ftell(FILE *archivo);
La funcin ftell sirve para averiguar la posicin actual del cursor de
lectura/escritura de un archivo. El valor de retorno ser esa posicin, o -1 si
hay algn error. El parmetro de entrada es un puntero a una estructura
FILE del archivo del que queremos leer la posicin del cursor de
lectura/escritura.
Ejemplo
// alea.c: Ejemplo de ficheros de acceso aleatorio.#include
#include
#include
#include
struct stRegistro {
char valido; // Campo que indica si el registro es vlido S->Vlido,
N->Invlido
char nombre[34];
int dato[4];
};
int Menu();
void Leer(struct stRegistro *reg);
void Mostrar(struct stRegistro *reg);
void Listar(long n, struct stRegistro *reg);
long LeeNumero();
void Empaquetar(FILE **fa);
int main()
{
struct stRegistro reg;
FILE *fa;
int opcion;
-
8/3/2019 Material Didactico Programacion II
19/83
Unidad I.- Archivos
Recopilado por: Docentes del rea de Programacin / Trayecto I / Trimestre IIIMdulo: Programacin II Pgina 18
long numero;
fa = fopen("alea.dat", "r+b"); // Este modo permite leer y
escribir
if(!fa) fa = fopen("alea.dat", "w+b"); // si el fichero no existe, locrea.
do {
opcion = Menu();
switch(opcion) {
case '1': // Aadir registro
Leer(®);
// Insertar al final:
fseek(fa, 0, SEEK_END);
fwrite(®, sizeof(struct stRegistro), 1, fa);
break;
case '2': // Mostrar registro
clrscr();
printf("Mostrar registro: ");
numero = LeeNumero();
fseek(fa, numero*sizeof(struct stRegistro), SEEK_SET);
fread(®, sizeof(struct stRegistro), 1, fa);
Mostrar(®);
break;
case '3': // Eliminar registro
clrscr();
printf("Eliminar registro: ");
numero = LeeNumero();
fseek(fa, numero*sizeof(struct stRegistro), SEEK_SET);
fread(®, sizeof(struct stRegistro), 1, fa);
reg.valido = 'N';
fseek(fa, numero*sizeof(struct stRegistro), SEEK_SET);
fwrite(®, sizeof(struct stRegistro), 1, fa);break;
case '4': // Mostrar todo
rewind(fa);
numero = 0;
clrscr();
printf("Nombre Datos\n");
while(fread(®, sizeof(struct stRegistro), 1, fa))
Listar(numero++, ®);
system("PAUSE");
break;
case '5': // Eliminar marcados
Empaquetar(&fa);
break;
}
} while(opcion != '0');
fclose(fa);
return 0;
}
// Muestra un men con las opciones disponibles y captura una opcin del
usuario
int Menu()
{
char resp[20];
do {
-
8/3/2019 Material Didactico Programacion II
20/83
Unidad I.- Archivos
Recopilado por: Docentes del rea de Programacin / Trayecto I / Trimestre IIIMdulo: Programacin II Pgina 19
clrscr();
printf("MENU PRINCIPAL\n");
printf("--------------\n\n");
printf("1- Insertar registro\n");printf("2- Mostrar registro\n");
printf("3- Eliminar registro\n");
printf("4- Mostrar todo\n");
printf("5- Eliminar registros marcados\n");
printf("0- Salir\n");
fgets(resp, 20, stdin);
} while(resp[0] < '0' && resp[0] > '5');
return resp[0];
}
// Permite que el usuario introduzca un registro por pantalla
void Leer(struct stRegistro *reg)
{
int i;
char numero[6];
clrscr();
printf("Leer registro:\n\n");
reg->valido = 'S';
printf("Nombre: ");
fgets(reg->nombre, 34, stdin);
// la funcin fgets captura el retorno de lnea, hay que eliminarlo:
for(i = strlen(reg->nombre)-1; i && reg->nombre[i] < ' '; i--)
reg->nombre[i] = 0;
for(i = 0; i < 4; i++) {
printf("Dato[%1d]: ", i);
fgets(numero, 6, stdin);
reg->dato[i] = atoi(numero);}
}
// Muestra un registro en pantalla, si no est marcado como borrado
void Mostrar(struct stRegistro *reg)
{
int i;
clrscr();
if(reg->valido == 'S') {
printf("Nombre: %s\n", reg->nombre);
for(i = 0; i < 4; i++) printf("Dato[%1d]: %d\n", i, reg->dato[i]);
}
getch();
}
// Muestra un registro por pantalla en forma de listado,
// si no est marcado como borrado
void Listar(long n, struct stRegistro *reg)
{
int i;
if(reg->valido == 'S') {
printf("[%6ld] %-34s", n, reg->nombre);
for(i = 0; i < 4; i++) printf(", %4d", reg->dato[i]);
printf("\n");
}
-
8/3/2019 Material Didactico Programacion II
21/83
Unidad I.- Archivos
Recopilado por: Docentes del rea de Programacin / Trayecto I / Trimestre IIIMdulo: Programacin II Pgina 20
}
// Lee un nmero suministrado por el usuario
long LeeNumero(){
char numero[6];
fgets(numero, 6, stdin);
return atoi(numero);
}
// Elimina los registros marcados como borrados
void Empaquetar(FILE **fa)
{
FILE *ftemp;
struct stRegistro reg;
ftemp = fopen("alea.tmp", "wb");
rewind(*fa);
while(fread(®, sizeof(struct stRegistro), 1, *fa))
if(reg.valido == 'S')
fwrite(®, sizeof(struct stRegistro), 1, ftemp);
fclose(ftemp);
fclose(*fa);
remove("alea.bak");
rename("alea.dat", "alea.bak");
rename("alea.tmp", "alea.dat");
*fa = fopen("alea.dat", "r+b");
}
-
8/3/2019 Material Didactico Programacion II
22/83
Unidad II.- Listas Enlazadas Simples, Dobles y Circulares
Recopilado por: Docentes del rea de Programacin / Trayecto I / Trimestre IIIMdulo: Programacin II Pgina 21
Las estructuras dinmicas nos permiten crear estructuras de datos
que se adapten a las necesidades reales a las que suelen enfrentarse
nuestros programas. Pero no slo eso, como veremos, tambin nos
permitir crear estructuras de datos muy flexibles, ya sea en cuanto al
orden, la estructura interna o las relaciones entre los elementos que las
componen.
Aqu desarrollaremos los siguientes tems:
Generalidades Listas Enlazadas Simples Conformacin de las Listas Enlazadas Simples Operaciones a realizar en una Lista Enlazada Simple Ejemplos de Listas Enlazadas Simples Listas Enlazadas Dobles Conformacin de las Listas Enlazadas Doble Operaciones a realizar en una Lista Enlazada Doble Ejemplos de Listas Enlazadas Doble Listas Enlazadas Circulares Conformacin de las Listas Enlazadas Circulares Operaciones a realizar en una Lista Enlazada Circular Ejemplos de Listas Enlazadas Circulares
-
8/3/2019 Material Didactico Programacion II
23/83
Unidad II.- Listas Enlazadas Simples, Dobles y Circulares
Recopilado por: Docentes del rea de Programacin / Trayecto I / Trimestre IIIMdulo: Programacin II Pgina 22
Generalidades
En muchas ocasiones se necesitan estructuras que puedan cambiarde tamao durante la ejecucin del programa. Por supuesto, podemos
hacer 'arrays' dinmicos, pero una vez creados, su tamao tambin ser
fijo, y para hacer que crezcan o disminuyan de tamao, deberemos
reconstruirlas desde el principio.
Las estructuras de datos estn compuestas de otras pequeas
estructuras a las que llamaremos nodos o elementos, que agrupan losdatos con los que trabajar nuestro programa y adems uno o ms
punteros autoreferenciales, es decir, punteros a objetos del mismo tipo
nodo.
Las estructuras dinmicas son una implementacin de TDAs o TADs
(Tipos Abstractos de Datos). En estos tipos el inters se centra ms en la
estructura de los datos que en el tipo concreto de informacin que
almacenan.
Dependiendo del nmero de punteros y de las relaciones entre
nodos, podemos distinguir varios tipos de estructuras dinmicas.
Enumeraremos ahora slo de los tipos bsicos:
Listas Simples o Abiertas: cada elemento slo dispone de un puntero,que apuntar al siguiente elemento de la lista o valdr NULL si es elltimo elemento.
Listas Doblemente Enlazadas: cada elemento dispone de dospunteros, uno a punta al siguiente elemento y el otro al elemento
anterior. Al contrario que las listas abiertas anteriores, estas listas
pueden recorrerse en los dos sentidos.
-
8/3/2019 Material Didactico Programacion II
24/83
Unidad II.- Listas Enlazadas Simples, Dobles y Circulares
Recopilado por: Docentes del rea de Programacin / Trayecto I / Trimestre IIIMdulo: Programacin II Pgina 23
Listas Circulares o Listas Cerradas: son parecidas a las listas abiertas,pero el ltimo elemento apunta al primero. De hecho, en las listas
circulares no puede hablarse de "primero" ni de "ltimo". Cualquier
nodo puede ser el nodo de entrada y salida.
Pilas: son un tipo especial de lista, conocidas como listas LIFO (Last In,First Out: el ltimo en entrar es el primero en salir). Los elementos se
"amontonan" o apilan, de modo que slo el elemento que est
encima de la pila puede ser ledo, y slo pueden aadirse elementos
encima de la pila.
Colas: otro tipo de listas, conocidas como listas FIFO (First In, First Out:El primero en entrar es el primero en salir). Los elementos se
almacenan en fila, pero slo pueden aadirse por un extremo y
leerse por el otro.
Arboles: cada elemento dispone de dos o ms punteros, pero lasreferencias nunca son a elementos anteriores, de modo que la
estructura se ramifica y crece igual que un rbol.
Arboles binarios: son rboles donde cada nodo slo puede apuntara dos nodos.
Arboles Binarios de Bsqueda (ABB): son rboles binarios ordenados.Desde cada nodo todos los nodos de una rama sern mayores,
segn la norma que se haya seguido para ordenar el rbol, y los de
la otra rama sern menores.
Arboles AVL: son tambin rboles de bsqueda, pero su estructuraest ms optimizada para reducir los tiempos de bsqueda.
Arboles B: son estructuras ms complejas, aunque tambin se tratade rboles de bsqueda, estn mucho ms optimizados que los
anteriores.
Grafos: es el siguiente nivel de complejidad, podemos considerarestas estructuras como rboles no jerarquizados.
-
8/3/2019 Material Didactico Programacion II
25/83
Unidad II.- Listas Enlazadas Simples, Dobles y Circulares
Recopilado por: Docentes del rea de Programacin / Trayecto I / Trimestre IIIMdulo: Programacin II Pgina 24
Listas Enlazadas Simples
Definicin de Listas Enlazadas Simples: Los Nodos apuntan alsiguiente y el ltimo apunta a NULL.
Nodo Especial: Sera el primero, por ser el elemento por dondeempezaremos a insertar nuevos nodos tambin se le denomina
CABEZA.
Operaciones: Declaracin Aadir o Insertar elementos Buscar o localizar elementos Borrar elementos Moverse a travs de la lista
Declaracin
Sintaxis:
typedef struct _nodo{
int dato;struct _nodo *siguiente;
} tipoNodo;
typedef tipoNodo *pNodo;typedef tipoNodo *Lista;
-
8/3/2019 Material Didactico Programacion II
26/83
Unidad II.- Listas Enlazadas Simples, Dobles y Circulares
Recopilado por: Docentes del rea de Programacin / Trayecto I / Trimestre IIIMdulo: Programacin II Pgina 25
Aadir o Insertar elementos
1. Insercin de un elemento a una lista Vaca:1) nodo->siguiente apunte a NULL.
2) Lista apunte a nodo.
2. Insercin de un elemento en la primera posicin de la lista:1) Hacemos que nodo->siguiente apunte a Lista.
2) Hacemos que Lista apunte a nodo.
3. Insercin de un elemento en la ltima posicin de la lista:1) Necesitamos un puntero que seale al ltimo elemento de la lista.
La manera de conseguirlo es empezar por el primero y avanzar hasta
que el nodo que tenga como siguiente el valor NULL.
-
8/3/2019 Material Didactico Programacion II
27/83
Unidad II.- Listas Enlazadas Simples, Dobles y Circulares
Recopilado por: Docentes del rea de Programacin / Trayecto I / Trimestre IIIMdulo: Programacin II Pgina 26
2) Hacer que nodo->siguiente sea NULL.
3) Hacer que ultimo->siguiente sea nodo.
4. Insercin de un elemento a continuacin de un nodo cualquiera dela lista:
1) Hacer que nodo->siguiente seale a anterior->siguiente.
2) Hacer que anterior->siguiente seale a nodo.
Buscar o Localizar elementos:
Para recorrer una lista enlazada simple o abierta procederemos
siempre del mismo modo, usaremos un puntero auxiliar como ndice:
-
8/3/2019 Material Didactico Programacion II
28/83
Unidad II.- Listas Enlazadas Simples, Dobles y Circulares
Recopilado por: Docentes del rea de Programacin / Trayecto I / Trimestre IIIMdulo: Programacin II Pgina 27
a.- Asignamos al puntero ndice el valor de Lista.
b.- Abriremos un bucle que al menos debe tener una condicin,que el ndice no sea NULL.
c.- Dentro del bucle asignaremos al ndice el valor del nodo siguiente
al ndice actual.
Eliminar elementos:
1. Eliminar el primer nodo:1.- Hacemos que nodo apunte al primer elemento de la lista, es
decir a Lista.
2.- Asignamos a Lista la direccin del segundo nodo de la lista:
Lista->siguiente.
3.- Liberamos la memoria asignada al primer nodo, el quequeremos eliminar.
-
8/3/2019 Material Didactico Programacion II
29/83
Unidad II.- Listas Enlazadas Simples, Dobles y Circulares
Recopilado por: Docentes del rea de Programacin / Trayecto I / Trimestre IIIMdulo: Programacin II Pgina 28
2. Eliminar un nodo cualquiera:
1) Hacemos que nodo apunte al nodo que queremos borrar.
2) Ahora, asignamos como nodo siguiente del nodo anterior, el
siguiente al que queremos eliminar:
anterior->siguiente = nodo->siguiente.
3) Eliminamos la memoria asociada al nodo que queremos eliminar.
Moverse dentro de la lista:
Casos:
a.- Primer elemento de una lista:
El primer elemento es el ms accesible, ya que es a ese a queapunta el puntero que define la lista. Para obtener un puntero al
primer elemento bastar con copiar el puntero Lista.
-
8/3/2019 Material Didactico Programacion II
30/83
Unidad II.- Listas Enlazadas Simples, Dobles y Circulares
Recopilado por: Docentes del rea de Programacin / Trayecto I / Trimestre IIIMdulo: Programacin II Pgina 29
b.- Elemento siguiente a uno cualquiera:
Supongamos que tenemos un puntero nodo que seala a un
elemento de una lista. Para obtener un puntero al siguiente bastar
con asignarle el campo "siguiente" del nodo, nodo->siguiente.
c.- Elemento anterior a uno cualquiera:
Ya hemos dicho que no es posible retroceder en una lista, de
modo que para obtener un puntero al nodo anterior a uno dado
tendremos que partir del primero, e ir avanzando hasta que el nodo
siguiente sea precisamente nuestro nodo.
d.- Ultimo elemento de una lista:
Para obtener un puntero al ltimo elemento de una lista
partiremos de un nodo cualquiera, por ejemplo el primero, y
avanzaremos hasta que su nodo siguiente sea NULL.
e.- Saber si una lista est vaca:
Basta con comparar el puntero Lista con NULL, si Lista vale NULL
la lista est vaca.
Ejemplo
#include
#include
typedef struct _nodo {int valor;
struct _nodo *siguiente;
} tipoNodo;
typedef tipoNodo *pNodo;
typedef tipoNodo *Lista;
/* Funciones con listas: */
void Insertar(Lista *l, int v);
void Borrar(Lista *l, int v);
-
8/3/2019 Material Didactico Programacion II
31/83
Unidad II.- Listas Enlazadas Simples, Dobles y Circulares
Recopilado por: Docentes del rea de Programacin / Trayecto I / Trimestre IIIMdulo: Programacin II Pgina 30
int ListaVacia(Lista l);
void BorrarLista(Lista *);void MostrarLista(Lista l);
int main() {
Lista lista = NULL;
pNodo p;
Insertar(&lista, 20);
Insertar(&lista, 10);
Insertar(&lista, 40);
Insertar(&lista, 30);
MostrarLista(lista);
Borrar(&lista, 10);
Borrar(&lista, 15);
Borrar(&lista, 45);
Borrar(&lista, 30);
Borrar(&lista, 40);
MostrarLista(lista);
BorrarLista(&lista);
getchar();
return 0;
}
void Insertar(Lista *lista, int v) {
pNodo nuevo, anterior;
/* Crear un nodo nuevo */
nuevo = (pNodo)malloc(sizeof(tipoNodo));
nuevo->valor = v;
/* Si la lista est vaca */
if(ListaVacia(*lista) || (*lista)->valor > v) {
/* Aadimos la lista a continuacin del nuevo nodo */
nuevo->siguiente = *lista;
/* Ahora, el comienzo de nuestra lista es en nuevo nodo */
*lista = nuevo;
}
else {
/* Buscar el nodo de valor menor a v */
anterior = *lista;
/* Avanzamos hasta el ltimo elemento o hasta que el siguiente
tenga
un valor mayor que v */
while(anterior->siguiente && anterior->siguiente->valor siguiente;
/* Insertamos el nuevo nodo despus del nodo anterior */
nuevo->siguiente = anterior->siguiente;
anterior->siguiente = nuevo;
-
8/3/2019 Material Didactico Programacion II
32/83
Unidad II.- Listas Enlazadas Simples, Dobles y Circulares
Recopilado por: Docentes del rea de Programacin / Trayecto I / Trimestre IIIMdulo: Programacin II Pgina 31
}
}
void Borrar(Lista *lista, int v) {pNodo anterior, nodo;
nodo = *lista;
anterior = NULL;
while(nodo && nodo->valor < v) {
anterior = nodo;
nodo = nodo->siguiente;
}
if(!nodo || nodo->valor != v) return;
else { /* Borrar el nodo */
if(!anterior) /* Primer elemento */
*lista = nodo->siguiente;
else /* un elemento cualquiera */
anterior->siguiente = nodo->siguiente;
free(nodo);
}
}
int ListaVacia(Lista lista) {
return (lista == NULL);
}
void BorrarLista(Lista *lista) {
pNodo nodo;
while(*lista) {
nodo = *lista;*lista = nodo->siguiente;
free(nodo);
}
}
void MostrarLista(Lista lista) {
pNodo nodo = lista;
if(ListaVacia(lista)) printf("Lista vaca\n");
else {
while(nodo) {
printf("%d -> ", nodo->valor);
nodo = nodo->siguiente;
}
printf("\n");
}
}
-
8/3/2019 Material Didactico Programacion II
33/83
Unidad II.- Listas Enlazadas Simples, Dobles y Circulares
Recopilado por: Docentes del rea de Programacin / Trayecto I / Trimestre IIIMdulo: Programacin II Pgina 32
Listas Enlazadas Dobles
Definicin de Listas Enlazadas Dobles: Una lista doblemente enlazadaes una lista lineal en la que cada nodo tiene dos enlaces, uno al nodo
siguiente, y otro al anterior. Las listas doblemente enlazadas no
necesitan un nodo especial para acceder a ellas, pueden recorrerse en
ambos sentidos a partir de cualquier nodo, esto es porque a partir de
cualquier nodo, siempre es posible alcanzar cualquier nodo de la lista,
hasta que se llega a uno de los extremos.
Operaciones: Declaracin Aadir o Insertar elementos Buscar o localizar elementos Borrar elementos
Declaracin
Sintaxis:
typedef struct _nodo{
int dato;struct _nodo *siguiente;struct _nodo *anterior;
} tipoNodo;typedef tipoNodo *pNodo;typedef tipoNodo *Lista;
-
8/3/2019 Material Didactico Programacion II
34/83
Unidad II.- Listas Enlazadas Simples, Dobles y Circulares
Recopilado por: Docentes del rea de Programacin / Trayecto I / Trimestre IIIMdulo: Programacin II Pgina 33
Aadir o Insertar elementos
1. Insercin de un elemento a una lista doblemente enlazada Vaca:1) lista apunta a nodo.
2) lista->siguiente y lista->anterior apunten a null.
2. Insercin de un elemento en la primera posicin de la lista:1) nodo->siguiente debe apuntar a Lista.
2) nodo->anterior apuntar a Lista->anterior.
3) Lista->anterior debe apuntar a nodo
-
8/3/2019 Material Didactico Programacion II
35/83
Unidad II.- Listas Enlazadas Simples, Dobles y Circulares
Recopilado por: Docentes del rea de Programacin / Trayecto I / Trimestre IIIMdulo: Programacin II Pgina 34
3. Insercin de un elemento en la ltima posicin de la lista:
1) nodo->siguiente debe apuntar a Lista->siguiente (NULL).
2) Lista->siguiente debe apuntar a nodo.
3) nodo->anterior apuntar a Lista.
4. Insercin de un elemento a continuacin de un nodo cualquiera dela lista:
1) Hacemos que nodo->siguiente apunte a lista->siguiente.
2) Hacemos que Lista->siguiente apunte a nodo.
3) Hacemos que nodo->anterior apunte a lista.
4) Hacemos que nodo->siguiente->anterior apunte a nodo.
-
8/3/2019 Material Didactico Programacion II
36/83
Unidad II.- Listas Enlazadas Simples, Dobles y Circulares
Recopilado por: Docentes del rea de Programacin / Trayecto I / Trimestre IIIMdulo: Programacin II Pgina 35
p=Lista->siguiente, entonces p->anterior debe apuntar a nodo, peronodo->siguiente ya apunta a nodo, por tanto simplificando nos queda
nodo->siguiente->anterior apunte a nodo
Insercin de elementos.- Procedimiento General:
1) Si lista est vaca hacemos que Lista apunte a nodo. Y nodo-
>anterior y nodo->siguiente a NULL.
2) Si lista no est vaca, hacemos que nodo->siguiente apunte a
Lista->siguiente.
3) Despus que Lista->siguiente apunte a nodo.
4) Hacemos que nodo->anterior apunte a Lista.
5) Si nodo->siguiente no es NULL, entonces hacemos que nodo-
>siguiente->anterior apunte a nodo.
Paso 1: Insercin de un elemento partiendo de una lista vaca
Pasos 2 y 3: Insercin en una Lista Enlazada Corriente
Pasos 4 y 5: insercin equivalente en donde el recorrido es inverso
Buscar o Localizar elementos:
a.- Retrocedemos hasta el comienzo de la lista, asignamos a lista el
valor de lista->anterior mientras lista->anterior no sea NULL.
-
8/3/2019 Material Didactico Programacion II
37/83
Unidad II.- Listas Enlazadas Simples, Dobles y Circulares
Recopilado por: Docentes del rea de Programacin / Trayecto I / Trimestre IIIMdulo: Programacin II Pgina 36
b.- Abriremos un bucle que al menos debe tener una condicin, que
el ndice no sea NULL.
c.- Dentro del bucle asignaremos a lista el valor del nodo siguiente
al actual.
Eliminar elementos:
Casos a tomar en cuenta:
1.- Eliminar el nico nodo de una lista doblemente
enlazada.2.- Eliminar el primer nodo.
3.- Eliminar el ltimo nodo.
4.- Eliminar un nodo intermedio.
1.- Eliminar el nico nodo de una lista doblemente enlazada.
1) Eliminamos el nodo.
2) Hacemos que Lista apunte a NULL.
2.- Eliminar el primer nodo.
1) Si nodo apunta a Lista, hacemos que Lista apunte a Lista-
>siguiente.
2) Hacemos que nodo->siguiente->anterior apunte a NULL
-
8/3/2019 Material Didactico Programacion II
38/83
Unidad II.- Listas Enlazadas Simples, Dobles y Circulares
Recopilado por: Docentes del rea de Programacin / Trayecto I / Trimestre IIIMdulo: Programacin II Pgina 37
3) Borramos el nodo apuntado por nodo.
3.- Eliminar el ltimo nodo.
1) Si nodo apunta a Lista, hacemos que Lista apunte a Lista-
>anterior.
2) Hacemos que nodo->anterior->siguiente apunte a NULL
3) Borramos el nodo apuntado por nodo.
4.- Eliminar un nodo intermedio.
1) Si nodo apunta a Lista, hacemos que Lista apunte a Lista->anterior (o Lista->siguiente).
2) Hacemos que nodo->anterior->siguiente apunte a nodo-
>siguiente.
-
8/3/2019 Material Didactico Programacion II
39/83
Unidad II.- Listas Enlazadas Simples, Dobles y Circulares
Recopilado por: Docentes del rea de Programacin / Trayecto I / Trimestre IIIMdulo: Programacin II Pgina 38
3) Hacemos que nodo->siguiente->anterior apunte a nodo-
>anterior.
4) Borramos el nodo apuntado por nodo.
Eliminacin de elementos.- Procedimiento General:
1) Si nodo apunta a Lista:
* Si Lista->anterior no es NULL hacemos que Lista apuntea Lista->anterior.
* Si Lista->siguiente no es NULL hacemos que Lista apunte
a Lista->siguiente.
* Si ambos son NULL, hacemos que Lista sea NULL.
2) Si nodo->anterior no es NULL, hacemos que nodo->anterior->siguiente apunte a nodo->siguiente.
3) Si nodo->siguiente no es NULL, hacemos que nodo->siguiente-
>anterior apunte a nodo->anterior.
4) Borramos el nodo apuntado por nodo.
-
8/3/2019 Material Didactico Programacion II
40/83
Unidad II.- Listas Enlazadas Simples, Dobles y Circulares
Recopilado por: Docentes del rea de Programacin / Trayecto I / Trimestre IIIMdulo: Programacin II Pgina 39
Ejemplo
#include
#define ASCENDENTE 1
#define DESCENDENTE 0
typedef struct _nodo {
int valor;
struct _nodo *siguiente;
struct _nodo *anterior;
} tipoNodo;
typedef tipoNodo *pNodo;
typedef tipoNodo *Lista;
/* Funciones con listas: */void Insertar(Lista *l, int v);
void Borrar(Lista *l, int v);
void BorrarLista(Lista *);
void MostrarLista(Lista l, int orden);
int main() {
Lista lista = NULL;
pNodo p;
Insertar(&lista, 20);
Insertar(&lista, 10);
Insertar(&lista, 40);
Insertar(&lista, 30);
MostrarLista(lista, ASCENDENTE);
MostrarLista(lista, DESCENDENTE);
Borrar(&lista, 10);
Borrar(&lista, 15);
Borrar(&lista, 45);
Borrar(&lista, 30);
MostrarLista(lista, ASCENDENTE);
MostrarLista(lista, DESCENDENTE);
BorrarLista(&lista);
getchar();
return 0;
}
void Insertar(Lista *lista, int v) {
pNodo nuevo, actual;
/* Crear un nodo nuevo */
nuevo = (pNodo)malloc(sizeof(tipoNodo));
nuevo->valor = v;
-
8/3/2019 Material Didactico Programacion II
41/83
Unidad II.- Listas Enlazadas Simples, Dobles y Circulares
Recopilado por: Docentes del rea de Programacin / Trayecto I / Trimestre IIIMdulo: Programacin II Pgina 40
/* Colocamos actual en la primera posicin de la lista */
actual = *lista;
if(actual) while(actual->anterior) actual = actual->anterior;/* Si la lista est vaca o el primer miembro es mayor que el nuevo */
if(!actual || actual->valor > v) {
/* Aadimos la lista a continuacin del nuevo nodo */
nuevo->siguiente = actual;
nuevo->anterior = NULL;
if(actual) actual->anterior = nuevo;
if(!*lista) *lista = nuevo;
}
else {
/* Avanzamos hasta el ltimo elemento o hasta que el siguiente
tenga
un valor mayor que v */
while(actual->siguiente &&actual->siguiente->valor siguiente;
/* Insertamos el nuevo nodo despus del nodo anterior */
nuevo->siguiente = actual->siguiente;
actual->siguiente = nuevo;
nuevo->anterior = actual;
if(nuevo->siguiente) nuevo->siguiente->anterior = nuevo;
}
}
void Borrar(Lista *lista, int v) {
pNodo nodo;
/* Buscar el nodo de valor v */
nodo = *lista;while(nodo && nodo->valor < v) nodo = nodo->siguiente;
while(nodo && nodo->valor > v) nodo = nodo->anterior;
/* El valor v no est en la lista */
if(!nodo || nodo->valor != v) return;
/* Borrar el nodo */
/* Si lista apunta al nodo que queremos borrar, apuntar a otro */
if(nodo == *lista)
if(nodo->anterior) *lista = nodo->anterior;
else *lista = nodo->siguiente;
if(nodo->anterior) /* no es el primer elemento */
nodo->anterior->siguiente = nodo->siguiente;
if(nodo->siguiente) /* no es el ltimo nodo */
nodo->siguiente->anterior = nodo->anterior;
free(nodo);
}
void BorrarLista(Lista *lista) {
pNodo nodo, actual;
actual = *lista;
while(actual->anterior) actual = actual->anterior;
-
8/3/2019 Material Didactico Programacion II
42/83
Unidad II.- Listas Enlazadas Simples, Dobles y Circulares
Recopilado por: Docentes del rea de Programacin / Trayecto I / Trimestre IIIMdulo: Programacin II Pgina 41
while(actual) {
nodo = actual;
actual = actual->siguiente;
free(nodo);}
*lista = NULL;
}
void MostrarLista(Lista lista, int orden) {
pNodo nodo = lista;
if(!lista) printf("Lista vaca");
nodo = lista;
if(orden == ASCENDENTE) {
while(nodo->anterior) nodo = nodo->anterior;
printf("Orden ascendente: ");
while(nodo) {
printf("%d -> ", nodo->valor);
nodo = nodo->siguiente;
}
}
else {
while(nodo->siguiente) nodo = nodo->siguiente;
printf("Orden descendente: ");
while(nodo) {
printf("%d -> ", nodo->valor);
nodo = nodo->anterior;
}
}
printf("\n");
}
-
8/3/2019 Material Didactico Programacion II
43/83
Unidad II.- Listas Enlazadas Simples, Dobles y Circulares
Recopilado por: Docentes del rea de Programacin / Trayecto I / Trimestre IIIMdulo: Programacin II Pgina 42
Listas Enlazadas Circulares
Definicin de Listas Enlazadas Circulares: Una lista circular es una listalineal en la que el ltimo nodo a punta al primero. Las listas circulares
evitan excepciones en las operaciones que se realicen sobre ellas. No
existen casos especiales, cada nodo siempre tiene uno anterior y uno
siguiente. En algunas listas circulares se aade un nodo especial de
cabecera, de ese modo se evita la nica excepcin posible, la de que
la lista est vaca.
Operaciones: Declaracin Aadir o Insertar elementos Buscar o localizar elementos Borrar elementos
Declaracin
Sintaxis:
typedef struct _nodo{
int dato;struct _nodo *siguiente;
} tipoNodo;typedef tipoNodo *pNodo;
typedef tipoNodo *Lista;
-
8/3/2019 Material Didactico Programacion II
44/83
Unidad II.- Listas Enlazadas Simples, Dobles y Circulares
Recopilado por: Docentes del rea de Programacin / Trayecto I / Trimestre IIIMdulo: Programacin II Pgina 43
Aadir o Insertar elementos
1.- Insercin de un elemento a una lista circularmente enlazadaVaca:
1) lista apunta a nodo.
2) lista->siguiente apunte a nodo.
2.- Insercin de un elemento en una lista circular no vaca:
1) Hacemos que nodo->siguiente apunte a lista->siguiente.
2) Despus que lista->siguiente apunte a nodo
-
8/3/2019 Material Didactico Programacion II
45/83
Unidad II.- Listas Enlazadas Simples, Dobles y Circulares
Recopilado por: Docentes del rea de Programacin / Trayecto I / Trimestre IIIMdulo: Programacin II Pgina 44
3.- Insercin de un elemento en una lista circular caso general:
Para generalizar los dos casos anteriores, slo necesitamos aadir
una operacin:
1) lista est vaca hacemos que lista apunte a nodo.
2) Si lista no est vaca, hacemos que nodo->siguiente apunte a
lista->siguiente.
3) Despus que lista->siguiente apunte a nodo
Buscar o Localizar elementos:
A la hora de buscar elementos en una lista circular slo hay que
tener una precaucin, es necesario almacenar el puntero del nodo en que
se empez la bsqueda, para poder detectar el caso en que no exista el
valor que se busca. Por lo dems, la bsqueda es igual que en el caso de
las listas abiertas, salvo que podemos empezar en cualquier punto de lalista.
Eliminar elementos:
Casos a tomar en cuenta:
1.- Eliminar un nodo cualquiera, que no sea el apuntado por
lista.
2.- Eliminar el nodo apuntado por lista, y que no sea el nico
nodo.
3.- Eliminar el nico nodo de la lista.
1.- Eliminar un nodo en una lista circular con ms de un
elemento:
-
8/3/2019 Material Didactico Programacion II
46/83
Unidad II.- Listas Enlazadas Simples, Dobles y Circulares
Recopilado por: Docentes del rea de Programacin / Trayecto I / Trimestre IIIMdulo: Programacin II Pgina 45
1) El primer paso es conseguir que lista apunte al nodo anterior
al que queremos eliminar. Esto se consigue haciendo que lista valga lista-
>siguiente mientras lista->siguiente sea distinto de nodo.
2) Hacemos que lista->siguiente apunte a nodo->siguiente.
3) Eliminamos el nodo.
2.- Eliminar el nico nodo de una lista circular:
1) Borramos el nodo apuntado por lista.
2) Hacemos que lista valga NULL.
3.- Otro algoritmo para borrar nodos:
1) Copiamos el contenido del nodo->siguiente sobre el
contenido de nodo.
-
8/3/2019 Material Didactico Programacion II
47/83
Unidad II.- Listas Enlazadas Simples, Dobles y Circulares
Recopilado por: Docentes del rea de Programacin / Trayecto I / Trimestre IIIMdulo: Programacin II Pgina 46
2) Hacemos que nodo->siguiente apunte a nodo->siguiente-
>siguiente.
3) Eliminamos nodo->siguiente.
4) Si lista es el nodo->siguiente, hacemos lista = nodo.
Ejemplo
#include
typedef struct _nodo {
int valor;
struct _nodo *siguiente;} tipoNodo;
typedef tipoNodo *pNodo;
typedef tipoNodo *Lista;
// Funciones con listas:
void Insertar(Lista *l, int v);
void Borrar(Lista *l, int v);
void BorrarLista(Lista *);
void MostrarLista(Lista l);
int main() {
Lista lista = NULL;
pNodo p;
Insertar(&lista, 10);
Insertar(&lista, 40);
Insertar(&lista, 30);
Insertar(&lista, 20);
Insertar(&lista, 50);
MostrarLista(lista);
Borrar(&lista, 30);
-
8/3/2019 Material Didactico Programacion II
48/83
Unidad II.- Listas Enlazadas Simples, Dobles y Circulares
Recopilado por: Docentes del rea de Programacin / Trayecto I / Trimestre IIIMdulo: Programacin II Pgina 47
Borrar(&lista, 50);
MostrarLista(lista);
BorrarLista(&lista);
getchar();
return 0;
}
void Insertar(Lista *lista, int v) {
pNodo nodo;
// Creamos un nodo para el nuvo valor a insertar
nodo = (pNodo)malloc(sizeof(tipoNodo));
nodo->valor = v;
// Si la lista est vaca, la lista ser el nuevo nodo
// Si no lo est, insertamos el nuevo nodo a continuacin del apuntado
// por lista
if(*lista == NULL) *lista = nodo;
else nodo->siguiente = (*lista)->siguiente;
// En cualquier caso, cerramos la lista circular
(*lista)->siguiente = nodo;
}
void Borrar(Lista *lista, int v) {
pNodo nodo;
nodo = *lista;
// Hacer que lista apunte al nodo anterior al de valor vdo {
if((*lista)->siguiente->valor != v) *lista = (*lista)->siguiente;
} while((*lista)->siguiente->valor != v && *lista != nodo);
// Si existe un nodo con el valor v:
if((*lista)->siguiente->valor == v) {
// Y si la lista slo tiene un nodo
if(*lista == (*lista)->siguiente) {
// Borrar toda la lista
free(*lista);
*lista = NULL;
}
else {
// Si la lista tiene ms de un nodo, borrar el nodo de valor v
nodo = (*lista)->siguiente;
(*lista)->siguiente = nodo->siguiente;
free(nodo);
}
}
}
void BorrarLista(Lista *lista) {
pNodo nodo;
// Mientras la lista tenga ms de un nodo
while((*lista)->siguiente != *lista) {
-
8/3/2019 Material Didactico Programacion II
49/83
Unidad II.- Listas Enlazadas Simples, Dobles y Circulares
Recopilado por: Docentes del rea de Programacin / Trayecto I / Trimestre IIIMdulo: Programacin II Pgina 48
// Borrar el nodo siguiente al apuntado por lista
nodo = (*lista)->siguiente;
(*lista)->siguiente = nodo->siguiente;
free(nodo);}
// Y borrar el ltimo nodo
free(*lista);
*lista = NULL;
}
void MostrarLista(Lista lista) {
pNodo nodo = lista;
do {
printf("%d -> ", nodo->valor);
nodo = nodo->siguiente;
} while(nodo != lista);
printf("\n");
}
-
8/3/2019 Material Didactico Programacion II
50/83
Unidad III.- Pilas y Colas
Recopilado por: Docentes del rea de Programacin / Trayecto I / Trimestre IIIMdulo: Programacin II Pgina 49
Cuando tenemos casos especiales de Listas Enlazadas Simples que
se manejan de acuerdo a criterios muy especficos, estn se convierten en
TAD diferentes y por tanto con un grado de independencia que permiten
convertirse en una solucin viable para determinados problemas.
Aqu desarrollaremos los siguientes tems:
Pilas Conformacin de una Pila Operaciones a realizar en una Pila Colas Conformacin de una Cola Operaciones a realizar en una Cola
-
8/3/2019 Material Didactico Programacion II
51/83
Unidad III.- Pilas y Colas
Recopilado por: Docentes del rea de Programacin / Trayecto I / Trimestre IIIMdulo: Programacin II Pgina 50
Pilas
Definicin de Pilas: Una pila es un tipo especial de lista abierta en laque slo se pueden insertar y eliminar nodos en uno de los extremos
de la lista. Estas operaciones se conocen como "push" y "pop",
respectivamente "empujar" y "tirar". Adems, las escrituras de datos
siempre son inserciones de nodos, y las lecturas siempre eliminan el
nodo ledo. Estas caractersticas implican un comportamiento de lista
LIFO (Last In First Out), el ltimo en entrar es el primero en salir. El smil
del que deriva el nombre de la estructura es una pila de platos. Slo
es posible aadir platos en la parte superior de la pila, y slo pueden
tomarse del mismo extremo.
Operaciones: Declaracin Push (Insertar elementos) Pop (Leer y Eliminar Elementos)
Declaracin
Sintaxis:
typedef struct _nodo{
int dato;
struct _nodo *siguiente;
} tipoNodo;typedef tipoNodo *pNodo;typedef tipoNodo *Pila
-
8/3/2019 Material Didactico Programacion II
52/83
Unidad III.- Pilas y Colas
Recopilado por: Docentes del rea de Programacin / Trayecto I / Trimestre IIIMdulo: Programacin II Pgina 51
Push (Insertar elementos)
Esta funcin lo que permite es insertar elementos al final de la Pila
5. Push en una Pila Vaca:1) nodo->siguiente apunte a NULL.
2) Pila apunte a nodo.
6. Push en una Pila no Vaca:1) Hacemos que nodo->siguiente apunte a Pila.
2) Hacemos que Pila apunte a nodo.
Pop: Leer y Eliminar
1) Hacemos que nodo apunte al primer elemento de la pila, es
decir a Pila.
-
8/3/2019 Material Didactico Programacion II
53/83
Unidad III.- Pilas y Colas
Recopilado por: Docentes del rea de Programacin / Trayecto I / Trimestre IIIMdulo: Programacin II Pgina 52
2) Asignamos a Pila la direccin del segundo nodo de la pila:
Pila->siguiente.
3) Guardamos el contenido del nodo para devolverlo como
retorno, recuerda que la operacin pop equivale a leer y borrar.
4) Liberamos la memoria asignada al primer nodo, el que
queremos eliminar.
Ejemplo
#include
#include
typedef struct _nodo {
int valor;
struct _nodo *siguiente;
} tipoNodo;
typedef tipoNodo *pNodo;
typedef tipoNodo *Pila;
/* Funciones con pilas: */void Push(Pila *l, int v);
int Pop(Pila *l);
int main() {
Pila pila = NULL;
Push(&pila, 20);
Push(&pila, 10);
printf("%d, ", Pop(&pila));
Push(&pila, 40);
Push(&pila, 30);
-
8/3/2019 Material Didactico Programacion II
54/83
Unidad III.- Pilas y Colas
Recopilado por: Docentes del rea de Programacin / Trayecto I / Trimestre IIIMdulo: Programacin II Pgina 53
printf("%d, ", Pop(&pila));
printf("%d, ", Pop(&pila));
Push(&pila, 90);printf("%d, ", Pop(&pila));
printf("%d\n", Pop(&pila));
getchar();
return 0;
}
void Push(Pila *pila, int v) {
pNodo nuevo;
/* Crear un nodo nuevo */
nuevo = (pNodo)malloc(sizeof(tipoNodo));
nuevo->valor = v;
/* Aadimos la pila a continuacin del nuevo nodo */
nuevo->siguiente = *pila;
/* Ahora, el comienzo de nuestra pila es en nuevo nodo */
*pila = nuevo;
}
int Pop(Pila *pila) {
pNodo nodo; /* variable auxiliar para manipular nodo */
int v; /* variable auxiliar para retorno */
/* Nodo apunta al primer elemento de la pila */
nodo = *pila;
if(!nodo) return 0; /* Si no hay nodos en la pila retornamos 0 *//* Asignamos a pila toda la pila menos el primer elemento */
*pila = nodo->siguiente;
/* Guardamos el valor de retorno */
v = nodo->valor;
/* Borrar el nodo */
free(nodo);
return v;
}
-
8/3/2019 Material Didactico Programacion II
55/83
Unidad III.- Pilas y Colas
Recopilado por: Docentes del rea de Programacin / Trayecto I / Trimestre IIIMdulo: Programacin II Pgina 54
Colas
Definicin de Colas: Una cola es un tipo especial de lista abierta enla que slo se pueden insertar nodos en uno de los extremos de la lista y
slo se pueden eliminar nodos en el otro. Adems, como sucede con las
pilas, las escrituras de datos siempre son inserciones de nodos, y las
lecturas siempre eliminan el nodo ledo. Este tipo de lista es conocido
como lista FIFO (First In First Out), el primero en entrar es el primero en
salir. El smil cotidiano es una cola para comprar, por ejemplo, las
entradas del cine. Los nuevos compradores slo pueden colocarse al
final de la cola, y slo el primero de la cola puede comprar la entrada.
Operaciones: Declaracin Aadir o Insertar elementos Leer y Eliminar elementos
Declaracin
Sintaxis:
typedef struct _nodo{
int dato;struct _nodo *siguiente;
} tipoNodo;typedef tipoNodo *pNodo;typedef tipoNodo *Cola;
-
8/3/2019 Material Didactico Programacion II
56/83
Unidad III.- Pilas y Colas
Recopilado por: Docentes del rea de Programacin / Trayecto I / Trimestre IIIMdulo: Programacin II Pgina 55
Aadir o Insertar elementos
1.- Aadir en una Cola Vaca:
1) nodo->siguiente apunte a NULL.
2) Y que los punteros primero y ltimo apunten a nodo.
2.- Aadir en una Cola no Vaca:
1) Hacemos que nodo->siguiente apunte a NULL.
2) Despus que ultimo->siguiente apunte a nodo.
3) Y actualizamos ultimo, haciendo que apunte a nodo.
-
8/3/2019 Material Didactico Programacion II
57/83
Unidad III.- Pilas y Colas
Recopilado por: Docentes del rea de Programacin / Trayecto I / Trimestre IIIMdulo: Programacin II Pgina 56
Leer y Eliminar elementos:
1.- Leer y Eliminar en una Cola que tiene ya un elemento por lo
menos:
1) Hacemos que nodo apunte al primer elemento de la cola, es
decir a primero.
2) Asignamos a primero la direccin del segundo nodo de la
cola: primero->siguiente.
3) Guardamos el contenido del nodo para devolverlo como
retorno, recuerda que la operacin de lectura en colas implican
tambin borrar.
4) Liberamos la memoria asignada al primer nodo, el que
queremos eliminar.
-
8/3/2019 Material Didactico Programacion II
58/83
Unidad III.- Pilas y Colas
Recopilado por: Docentes del rea de Programacin / Trayecto I / Trimestre IIIMdulo: Programacin II Pgina 57
Ejemplo
#include
typedef struct _nodo {
int valor;
struct _nodo *siguiente;
} tipoNodo;
typedef tipoNodo *pNodo;
/* Funciones con colas: */
void Anadir(pNodo *primero, pNodo *ultimo, int v);
int Leer(pNodo *primero, pNodo *ultimo);
int main() {
pNodo primero = NULL, ultimo = NULL;
Anadir(&primero, &ultimo, 20);
printf("Aadir(20)\n");
Anadir(&primero, &ultimo, 10);
printf("Aadir(10)\n");
printf("Leer: %d\n", Leer(&primero, &ultimo));
Anadir(&primero, &ultimo, 40);
printf("Aadir(40)\n");
Anadir(&primero, &ultimo, 30);
printf("Aadir(30)\n");
printf("Leer: %d\n", Leer(&primero, &ultimo));
printf("Leer: %d\n", Leer(&primero, &ultimo));
Anadir(&primero, &ultimo, 90);
printf("Aadir(90)\n");printf("Leer: %d\n", Leer(&primero, &ultimo));
printf("Leer: %d\n", Leer(&primero, &ultimo));
getchar();
return 0;
}
void Anadir(pNodo *primero, pNodo *ultimo, int v) {
pNodo nuevo;
/* Crear un nodo nuevo */
nuevo = (pNodo)malloc(sizeof(tipoNodo));
nuevo->valor = v;
/* Este ser el ltimo nodo, no debe tener siguiente */
nuevo->siguiente = NULL;
/* Si la cola no estaba vaca, aadimos el nuevo a continuacin de
ultimo */
if(*ultimo) (*ultimo)->siguiente = nuevo;
/* Ahora, el ltimo elemento de la cola es el nuevo nodo */
*ultimo = nuevo;
/* Si primero es NULL, la cola estaba vaca, ahora primero apuntar
tambin al nuevo nodo */
if(!*primero) *primero = nuevo;
}
-
8/3/2019 Material Didactico Programacion II
59/83
Unidad III.- Pilas y Colas
Recopilado por: Docentes del rea de Programacin / Trayecto I / Trimestre IIIMdulo: Programacin II Pgina 58
int Leer(pNodo *primero, pNodo *ultimo) {
pNodo nodo; /* variable auxiliar para manipular nodo */
int v; /* variable auxiliar para retorno */
/* Nodo apunta al primer elemento de la pila */
nodo = *primero;
if(!nodo) return 0; /* Si no hay nodos en la pila retornamos 0 */
/* Asignamos a primero la direccin del segundo nodo */
*primero = nodo->siguiente;
/* Guardamos el valor de retorno */
v = nodo->valor;
/* Borrar el nodo */
free(nodo);
/* Si la cola qued vaca, ultimo debe ser NULL tambin*/
if(!*primero) *ultimo = NULL;
return v;
}
-
8/3/2019 Material Didactico Programacion II
60/83
Unidad IV.- rboles
Recopilado por: Docentes del rea de Programacin / Trayecto I / Trimestre IIIMdulo: Programacin II Pgina 59
Las estructuras dinmicas vistas hasta ahora son lineales (listas
enlazadas, pilas, colas). Estas estructuras tienen grandes ventajas en
cuanto a flexibilidad sobre las representaciones contiguas, pero tienen un
punto dbil: son listas secuenciales, es decir, estn dispuestas de forma que
es necesario recorrer cada posicin al menos una vez (cada elemento
tiene un sucesor). Mediante los rboles binarios se introduce el concepto
de estructura de bifurcacin, donde cada elemento puede tener ms de
un posible 'siguiente', con lo cual es posible resolver algunos problemas de
difcil solucin cuando se usan estructuras dinmicas lineales. El rbol es
una estructura muy usada en todos los mbitos de la informtica ya que se
adapta a la representacin natural de informaciones homogneas
organizadas y de una gran comodidad y rapidez de manipulacin. Las
estructuras tipo rbol se usan para representar datos con una relacin
jerrquica entre sus elementos, como son rboles genealgicos, tablas,
etc.
Aqu desarrollaremos los siguientes tems:
Definicin de rbol Conceptos Bsicos a manejar Recorridos rboles Ordenados rboles Binarios de Bsqueda (ABB) Operaciones a realizar en los rboles Binarios de Bsqueda
(ABB)
-
8/3/2019 Material Didactico Programacion II
61/83
Unidad IV.- rboles
Recopilado por: Docentes del rea de Programacin / Trayecto I / Trimestre IIIMdulo: Programacin II Pgina 60
Definicin de rbol
Un rbol es una estructura no lineal en la que cada nodo puede
apuntar a uno o varios nodos. Tambin se suele dar una definicin
recursiva: un rbol es una estructura en compuesta por un dato y varios
rboles. Esto son definiciones simples. Pero las caractersticas que
implican no lo son tanto.
Conceptos Bsicos a Manejar
1. En relacin con otros nodosa. Nodo hijo: cualquiera de los nodos apuntados por uno
de los nodos del rbol. En el ejemplo, 'L' y 'M' son hijos de
'G'.
b. Nodo padre: nodo que contiene un puntero al nodoactual. En el ejemplo, el nodo 'A' es padre de 'B', 'C' y 'D'.
-
8/3/2019 Material Didactico Programacion II
62/83
Unidad IV.- rboles
Recopilado por: Docentes del rea de Programacin / Trayecto I / Trimestre IIIMdulo: Programacin II Pgina 61
2. En cuanto a la posicin dentro del rbol
a.- Nodo raz: nodo que no tiene padre. Este es el nodo que
usaremos para referirnos al rbol. En el ejemplo, ese nodo es el 'A'.
b.- Nodo hoja: nodo que no tiene hijos. En el ejemplo hay varios:
'F', 'H', 'I', 'K', 'L', 'M', 'N' y 'O'.
c.- Nodo rama: aunque esta definicin apenas la usaremos,
estos son los nodos que no pertenecen a ninguna de las dos
categoras anteriores. En el ejemplo: 'B', 'C', 'D', 'E', 'G' y 'J'.
3. Otros conceptos:
-
8/3/2019 Material Didactico Programacion II
63/83
Unidad IV.- rboles
Recopilado por: Docentes del rea de Programacin / Trayecto I / Trimestre IIIMdulo: Programacin II Pgina 62
a.- Un rbol en el que en cada nodo o bien todos o ninguno de los
hijos existe, se llama rbol completo.
b.- Orden: es el nmero potencial de hijos que puede tener cada
elemento de rbol. De este modo, diremos que un rbol en el que
cada nodo puede apuntar a otros dos es de orden dos, si puede
apuntar a tres ser de orden tres, etc.
c.- Grado: el nmero de hijos que tiene el elemento con ms hijos
dentro del rbol. En el rbol del ejemplo, el grado es tres, ya que
tanto 'A' como 'D' tienen tres hijos, y no existen elementos con ms
de tres hijos.
d.- Nivel: se define para cada elemento del rbol como la distancia
a la raz, medida en nodos. El nivel de la raz es cero y el de sus
hijos uno. As sucesivamente. En el ejemplo, el nodo 'D' tiene nivel 1,
el nodo 'G' tiene nivel 2, y el nodo 'N', nivel 3.
e.- Altura: la altura de un rbol se define como el nivel del nodo de
mayor nivel. Como cada nodo de un rbol puede considerarse a su
vez como la raz de un rbol, tambin podemos hablar de altura de
ramas. El rbol del ejemplo tiene altura 3, la rama 'B' tiene altura 2, la
rama 'G' tiene altura 1, la 'H' cero,
Recorridos
El modo evidente de moverse a travs de las ramas de un rbol es
siguiendo los punteros, del mismo modo en que nos movamos a travs
de las listas. Esos recorridos dependen en gran medida del tipo y
-
8/3/2019 Material Didactico Programacion II
64/83
Unidad IV.- rboles
Recopilado por: Docentes del rea de Programacin / Trayecto I / Trimestre IIIMdulo: Programacin II Pgina 63
propsito del rbol, pero hay ciertos recorridos que usaremos
frecuentemente. Se trata de aquellos recorridos que incluyen todo el
rbol. Hay tres formas de recorrer un rbol completo, y las tres se suelen
implementar mediante recursividad. En los tres casos se sigue siempre a
partir de cada nodo todas las ramas una por una.
Lo que diferencia los distintos mtodos de recorrer el rbol no es el
sistema de hacerlo, sino el momento que elegimos para procesar el
valor de cada nodo con relacin a los recorridos de cada una de las
ramas.
a.- Pre-orden: En este tipo de recorrido, el valor del nodo se procesa
antes de recorrer las ramas. Si seguimos el rbol del ejemplo en pre-
orden, y el proceso de los datos es sencillamente mostrarlos por
pantalla, obtendremos algo as: A B E K F C G L M D H I J N O
b.- In-orden: En este tipo de recorrido, el valor del nodo se procesa
despus de recorrer la primera rama y antes de recorrer la ltima.
Esto tiene ms sentido en el caso de rboles binarios, y tambin
cuando existen ORDEN-1 datos, en cuyo caso procesaremos cada
dato entre el recorrido de cada dos ramas (este es el caso de los
rboles-b). Si seguimos el rbol del ejemplo en in-orden, y el proceso
-
8/3/2019 Material Didactico Programacion II
65/83
Unidad IV.- rboles
Recopilado por: Docentes del rea de Programacin / Trayecto I / Trimestre IIIMdulo: Programacin II Pgina 64
de los datos es sencillamente mostrarlos por pantalla, obtendremos
algo as: K E B F A L G M C H D I N J O
c.- Post-orden: En este tipo de recorrido, el valor del nodo se
procesa despus de recorrer todas las ramas. Si seguimos el rbol del
ejemplo en post-orden, y el proceso de los datos es sencillamente
mostrarlos por pantalla, obtendremos algo as: K E F B L M G C H I N O
J D A
rboles Ordenados
Un rbol ordenado, en general, es aquel a partir del cual se puede
obtener una secuencia ordenada siguiendo uno de los recorridos posibles
del rbol: inorden, preorden o postorden.
-
8/3/2019 Material Didactico Programacion II
66/83
Unidad IV.- rboles
Recopilado por: Docentes del rea de Programacin / Trayecto I / Trimestre IIIMdulo: Programacin II Pgina 65
En estos rboles es importante que la secuencia se mantenga
ordenada aunque se aadan o se eliminen nodos.
Existen varios tipos de rboles ordenados, que veremos a
continuacin:
a.- rboles Binarios de Bsqueda (ABB): son rboles de orden 2 que
mantienen una secuencia ordenada si se recorren en inorden.
b.- rboles AVL: son rboles binarios de bsqueda equilibrados, es
decir, los niveles de cada rama para cualquier nodo no difieren en ms de
1.
c.- rboles Perfectamente Equilibrados: son rboles binarios de
bsqueda en los que el nmero de nodos de cada rama para cualquier
nodo no difieren en ms de 1. Son por lo tanto rboles AVL tambin.
d.- rboles 2-3:son rboles de orden 3, que contienen dos claves encada nodo y que estn tambin equilibrados. Tambin generan
secuencias ordenadas al recorrerlos en inorden.
e.- rboles-B: caso general de rboles 2-3, que para un orden M,
contienen M-1 claves.
-
8/3/2019 Material Didactico Programacion II
67/83
Unidad IV.- rboles
Recopilado por: Docentes del rea de Programacin / Trayecto I / Trimestre IIIMdulo: Programacin II Pgina 66
rboles Binarios de Bsqueda (ABB)
Se trata de rboles de orden 2 en los que se cumple que paracada nodo, el valor de la clave de la raz del subrbol izquierdo es
menor que el valor de la clave del nodo y que el valor de la clave
raz del subrbol derecho es mayor que el valor de la clave del nodo.
Operaciones:
1. Declaracin2. Bsqueda3. Insercin4. Eliminacin5. Movimientos:
Izquierda Derecha Raz
6. Informacin: Comprobar si el rbol est vaco Calcular el nmero de nodos Comprobacin si un nodo es hoja Clculo de la altura de un nodo y de un rbol
-
8/3/2019 Material Didactico Programacion II
68/83
Unidad IV.- rboles
Recopilado por: Docentes del rea de Programacin / Trayecto I / Trimestre IIIMdulo: Programacin II Pgina 67
Declaracin
Sintaxis:
typedef struct _nodo{
int dato;struct _nodo *rama[ORDEN];
} tipoNodo;typedef tipoNodo *pNodo;typedef tipoNodo *Arbol;
Bsqueda
Partiendo siempre del nodo raz, el modo de buscar un elemento se
define de forma recursiva.
Si el rbol est vaco, terminamos la bsqueda: el elemento no est
en el rbol.
Si el valor del nodo raz es igual que el del elemento que buscamos,
terminamos la bsqueda con xito.
Si el valor del nodo raz es mayor que el elemento que buscamos,
continuaremos la bsqueda en el rbol izquierdo.
Si el valor del nodo raz es menor que el elemento que buscamos,
continuaremos la bsqueda en el rbol derecho.
El valor de retorno de una funcin de bsqueda en un ABB puede ser
un puntero al nodo encontrado, o NULL, si no se ha encontrado.
-
8/3/2019 Material Didactico Programacion II
69/83
Unidad IV.- rboles
Recopilado por: Docentes del rea de Programacin / Trayecto I / Trimestre IIIMdulo: Programacin II Pgina 68
Insercin de un elemento
Para insertar un elemento nos basamos en el algoritmo de bsqueda.Si el elemento est en el rbol no lo insertaremos. Si no lo est, lo
insertaremos a continuacin del ltimo nodo visitado.
Necesitamos un puntero auxiliar para conservar una referencia al
padre del nodo raz actual. El valor inicial para ese puntero es NULL.
Padre = NULL
nodo = Raiz
Bucle: mientras actual no sea un rbol vaco o hasta que se
encuentre el elemento.
Si el valor del nodo raz es mayor que el elemento que buscamos,
continuaremos la bsqueda en el rbol izquierdo: Padre=nodo,
nodo=nodo->izquierdo.
Si el valor del nodo raz es menor que el elemento que buscamos,
continuaremos la bsqueda en el rbol derecho: Padre=nodo,
nodo=nodo->derecho.
Si Padre es NULL, el rbol estaba vaco, por lo tanto, el nuevo rbol
slo contendr el nuevo elemento, que ser la raz del rbol.
Si el elemento es menor que el Padre, entonces insertamos el nuevo
elemento como un nuevo rbol izquierdo de Padre.
Si el elemento es mayor que el Padre, entonces insertamos el nuevo
elemento como un nuevo rbol derecho de Padre.
-
8/3/2019 Material Didactico Programacion II
70/83
Unidad IV.- rboles
Recopilado por: Docentes del rea de Programacin / Trayecto I / Trimestre IIIMdulo: Programacin II Pgina 69
Este modo de actuar asegura que el rbol sigue siendo ABB.
Eliminacin de un elemento
Para borrar un elemento tambin nos basamos en el algoritmo de
bsqueda. Si el elemento no est en el rbol no lo podremos borrar. Si est,
hay dos casos posibles:
a.- Se trata de un nodo hoja: en ese caso lo borraremos
directamente.
b.- Se trata de un nodo rama: en ese caso no podemos eliminarlo,
puesto que perderamos todos los elementos del rbol de que el nodo
actual es padre. En su lugar buscamos el nodo ms a la izquierda del
subrbol derecho, o el ms a la derecha del subrbol izquierdo e
intercambiamos sus valores. A continuacin eliminamos el nodo hoja.
Necesitamos un puntero auxiliar para conservar una referencia alpadre del nodo raz actual. El valor inicial para ese puntero es NULL.
Padre = NULL
Si el rbol est vaco: el elemento no est en el rbol, por lo tanto
salimos sin eliminar ningn elemento.
Si el valor del nodo raz es igual que el del elemento que buscamos,estamos ante uno de los siguientes casos:
El nodo raz es un nodo hoja:
1. Si 'Padre' es NULL, el nodo raz es el nico del rbol, por lo tantoel puntero al rbol debe ser NULL.
-
8/3/2019 Material Didactico Programacion II
71/83
Unidad IV.- rboles
Recopilado por: Docentes del rea de Programacin / Trayecto I / Trimestre IIIMdulo: Programacin II Pgina 70
2. Si raz es la rama derecha de 'Padre', hacemos que esa ramaapunte a NULL.
3. Si raz es la rama izquierda de 'Padre', hacemos que esa ramaapunte a NULL.
4. Eliminamos el nodo, y salimos.El nodo no es un nodo hoja:
1. Buscamos el 'nodo' ms a la izquierda del rbol derecho de raz o elms a la derecha del rbol izquierdo. Hay que tener en cuenta quepuede que slo exista uno de esos rboles. Al mismo tiempo,
actualizamos 'Padre' para que apunte al padre de 'nodo'.
2. Intercambiamos los elementos de los nodos raz y 'nodo'.3. Borramos el nodo 'nodo'. Esto significa volver a (1), ya que puede
suceder que 'nodo' no sea un nodo hoja. (Ver ejemplo 3)
Si el valor del nodo raz es mayor que el elemento que buscamos,
continuaremos la bsqueda en el rbol izquierdo.
Si el valor del nodo raz es menor que el elemento que buscamos,
continuaremos la bsqueda en el rbol derecho.
Eliminacin de un nodo hoja
En el rbol de ejemplo, borrar el nodo 3.
1.- Localizamos el nodo a borrar, al tiempo que mantenemos un
puntero a 'Padre'.
2.- Hacemos que el puntero de 'Padre' que apuntaba a 'nodo',
ahora apunte a NULL.
-
8/3/2019 Material Didactico Programacion II
72/83
Unidad IV.- rboles
Recopilado por: Docentes del rea de Programacin / Trayecto I / Trimestre IIIMdulo: Programacin II Pgina 71
3.- Borramos el 'nodo'.
Eliminacin de un Nodo Rama con un Intercambio de un Nodo Hoja:
En el rbol de ejemplo, borrar el nodo 4.
1.- Localizamos el nodo a borrar ('raz').
2.- Buscamos el nodo ms a la derecha del rbol izquierdo de
'raz', en este caso el 3, al tiempo que mantenemos un puntero
a 'Padre' a 'nodo'.
3.- Intercambiamos los elementos 3 y 4.
4.- Hacemos que el puntero de 'Padre' que apuntaba a 'nodo',
ahora apunte a NULL.
5.- Borramos el 'nodo'.
-
8/3/2019 Material Didactico Programacion II
73/83
Unidad IV.- rboles
Recopilado por: Docentes del rea de Programacin / Trayecto I / Trimestre IIIMdulo: Programacin II Pgina 72
Eliminacin de un Nodo Rama con un Intercambio de un Nodo Rama:
Para este ejemplo usaremos otro rbol. En ste borraremos el
elemento 6.
1.- Localizamos el nodo a borrar ('raz').
2.- Buscamos el nodo ms a la izquierda del rbol derecho de 'raz',
en este caso el 12, ya que el rbol derecho no tiene nodos a su izquierda, si
optamos por la rama izquierda, estaremos en un caso anlogo. Al mismo
tiempo que mantenemos un puntero a 'Padre' a 'nodo'.
3.- Intercambiamos los elementos 6 y 12.
4.- Ahora tenemos que repetir el bucle para el nodo 6 de nuevo, ya
que no podemos eliminarlo
5.- Localizamos de nuevo el nodo a borrar ('raz').
6.- Buscamos el nodo ms a la izquierda del rbol derecho de 'raz',
en este caso el 16, al mismo tiempo que mantenemos un puntero a 'Padre'
a 'nodo'.
7.- Intercambiamos los elementos 6 y 16.
-
8/3/2019 Material Didactico Programacion II
74/83
Unidad IV.- rboles
Recopilado por: Docentes del rea de Programacin / Trayecto I / Trimestre IIIMdulo: Programacin II Pgina 73
8.- Hacemos que el puntero de 'Padre' que apuntaba a 'nodo',
ahora apunte a NULL.
9.- Borramos el 'nodo'.
Movimientos a travs del rbol
No hay mucho que contar. Nuestra estructura se referenciar
siempre mediante un puntero al nodo Raiz, este puntero no debe perderse
nunca.
Para movernos a travs del rbol usaremos punteros auxiliares, de
modo que desde cualqu