material didactico programacion ii

Upload: sergio-guevara

Post on 07-Apr-2018

218 views

Category:

Documents


0 download

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(&reg);

    // Insertar al final:

    fseek(fa, 0, SEEK_END);

    fwrite(&reg, 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(&reg, sizeof(struct stRegistro), 1, fa);

    Mostrar(&reg);

    break;

    case '3': // Eliminar registro

    clrscr();

    printf("Eliminar registro: ");

    numero = LeeNumero();

    fseek(fa, numero*sizeof(struct stRegistro), SEEK_SET);

    fread(&reg, sizeof(struct stRegistro), 1, fa);

    reg.valido = 'N';

    fseek(fa, numero*sizeof(struct stRegistro), SEEK_SET);

    fwrite(&reg, sizeof(struct stRegistro), 1, fa);break;

    case '4': // Mostrar todo

    rewind(fa);

    numero = 0;

    clrscr();

    printf("Nombre Datos\n");

    while(fread(&reg, sizeof(struct stRegistro), 1, fa))

    Listar(numero++, &reg);

    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(&reg, sizeof(struct stRegistro), 1, *fa))

    if(reg.valido == 'S')

    fwrite(&reg, 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