Programación en C: Implementación de Listas Enlazadas, Pilas y Gestión de Ficheros

Enviado por Programa Chuletas y clasificado en Informática y Telecomunicaciones

Escrito el en español con un tamaño de 11 KB

Conceptos de Recorrido (Árboles)

Estos términos se refieren comúnmente a los órdenes de recorrido en estructuras de datos tipo árbol:

  • PreOrden (Raíz-Izquierda-Derecha): RID
  • InOrden (Izquierda-Raíz-Derecha): IRD
  • PostOrden (Izquierda-Derecha-Raíz): IDR

Lista Lineal Simplemente Enlazada en C

Este apartado presenta la implementación de una lista lineal simplemente enlazada en C, incluyendo funciones básicas para su gestión.

Declaraciones Globales y Estructura del Elemento

typedef struct s // Declaración del tipo struct, elemento de la cadena
{
    int num1;
    float num2;
    struct s *siguiente;
} elemento;

elemento *lista = NULL; // Declaración del puntero maestro global

Prototipos de Funciones

void insertar(int x, float y);
void imprimir(void);
void borrar(void);

Función Principal (main)

main()
{
    int x;
    float y;
    printf("Introduzca datos:\n");
    while (1)
    {
        printf("x = ");
        if (scanf("%d", &x) != 1) break;
        printf("y = ");
        if (scanf("%f", &y) != 1) break;
        insertar(x, y);
    }
    printf("\nLos datos introducidos son:\n");
    imprimir();
    borrar();
}

Implementación de Funciones de la Lista

Insertar un Nuevo Elemento al Principio de la Lista

void insertar(int x, float y) // Introducir nuevo elemento al principio de la lista
{
    elemento *q = (elemento *)malloc(sizeof(elemento));
    if (q == NULL)
    {
        printf("Falta memoria");
        // getch(); // getch() es específico de algunas librerías, se omite o se reemplaza si no es estándar.
    }
    else
    {
        q->num1 = x;
        q->num2 = y;
        q->siguiente = lista;
        lista = q;
    }
}

Mostrar Todos los Elementos de la Lista

void imprimir(void) // Escribir todos los elementos de la lista
{
    elemento *q = lista;
    while (q != NULL)
    {
        printf("x = %d, y = %g\n", q->num1, q->num2);
        q = q->siguiente;
    }
}

Eliminar Todos los Elementos de la Lista

void borrar(void) // Borrar todos los elementos de la lista
{
    elemento *q = lista;
    while (q != NULL)
    {
        lista = lista->siguiente;
        free(q);
        q = lista;
    }
}

Inserción de Elementos Adicionales en la Lista

Insertar un Nuevo Elemento Después de uno Dado por el Puntero p

// Insertar un nuevo elemento después de uno dado por el puntero "p"
void insertarsig(elemento *p, int x, float y)
{
    elemento *q = NuevoElemento();
    if (q != NULL)
    {
        q->num1 = x;
        q->num2 = y;
        q->siguiente = p->siguiente;
        p->siguiente = q;
    }
}

Insertar un Nuevo Elemento Antes de uno Dado por el Puntero p

// Insertar un nuevo elemento antes de uno dado por el puntero "p"
void insertarant(elemento *p, int x, float y)
{
    elemento *q = NuevoElemento();
    if (q) // Equivalente a (q != NULL)
    {
        *q = *p;
        p->num1 = x;
        p->num2 = y;
        p->siguiente = q;
    }
}

Creación de un Nuevo Elemento de la Lista

// Crear nuevo elemento de la lista
elemento *NuevoElemento(void)
{
    elemento *q = (elemento *)malloc(sizeof(elemento));
    if (q == NULL)
    {
        printf("Falta memoria");
        // getch(); // getch() es específico de algunas librerías, se omite o se reemplaza si no es estándar.
    }
    return q;
}

Eliminación de Elementos de la Lista

Eliminar un Elemento Dado (si no es el último de la lista)

// Eliminar un elemento dado, si no es el último de la lista
void eliminar(elemento *p)
{
    elemento *q = p->siguiente;
    if (q != NULL)
    {
        *p = *q;
        free(q);
    }
}

Eliminar el Elemento Siguiente a uno Dado

// Eliminar el elemento siguiente a uno dado
void eliminarsig(elemento *p)
{
    elemento *q = p->siguiente;
    if (q) // Equivalente a (q != NULL)
    {
        p->siguiente = q->siguiente;
        free(q);
    }
}

Búsqueda de Elementos en la Lista

Buscar un Elemento Específico en la Lista

// Buscar un elemento de la lista
void buscar(void)
{
    int num;
    elemento *q = lista;
    printf("Ingrese el valor de X a buscar:");
    if (scanf("%d", &num) != 1) return;
    while (q != NULL && q->num1 != num) q = q->siguiente;
    if (q == NULL) printf("Dato no encontrado.\n");
    else printf("El valor de Y asociado a X=%d es: %g\n", num, q->num2);
}

Ejercicio: Función de Búsqueda en Lista Enlazada

La función fun busca un elemento en una lista lineal enlazada, en la que cada elemento tiene el siguiente tipo de datos: typedef struct nodo

typedef struct nodo
{
    int dato;
    struct nodo *sig;
} lista;

El primer parámetro p es un puntero al primer elemento de la lista y el segundo parámetro num es el número que se busca. La función fun ha de devolver la dirección del elemento de la lista, si encuentra el número a buscar, y devuelve NULL si no se encuentra el número en la lista.

lista *fun(lista *p, int num)
{
    int sw = 0;
    /* Código a completar */
    while ((p != NULL) && (sw == 0))
    {
        if (p->dato == num) sw = 1;
        else p = p->sig;
    }
    if (sw) return (p);
    else return NULL;
}

Ejercicio: Función para Suprimir Elemento de una Pila

La pila de la figura es controlada mediante el puntero de ámbito global pi. El puntero pi apunta al último elemento que se introdujo en la pila. Se quiere realizar una función llamada fun, que permita suprimir un elemento de la pila y lo imprima.

/* Suponiendo la estructura de la pila y 'nom' y 'pt' declarados */
void fun_suprimir_pila(/* parámetros si los hubiera, o si 'pi' es global */)
{
    /* Código a completar */
    // Las líneas proporcionadas para completar la función son:
    // strcpy(nom, pi->nombre); // 'nom' y 'pi->nombre' deben estar definidos
    // printf("%s\n ", nom);
    // pt = pi; // 'pt' debe estar definido
    // pi = pi->sig;
    // free(pt); // Se debería liberar la memoria del elemento suprimido
}

Las líneas proporcionadas para completar la función son:

strcpy(nom, pi->nombre);
printf("%s\n ", nom);
pt = pi;
pi = pi->sig;

Nota: Para una implementación completa, se necesitaría la definición de la estructura de la pila y las declaraciones de nom (como un array de caracteres) y pt (como un puntero del mismo tipo que pi). Además, se debería liberar la memoria del elemento suprimido con free(pt).

Ejercicio: Modificación de Registro en Fichero

Suponiendo un fichero abierto para lectura y escritura y referenciado por pf, que almacena estructuras de la forma: struct alumn { char nombre[40]; float nota; };

Indicar qué sentencias hay que sustituir por el comentario, para que la función fun permita cambiar la nota, poniendo un 5.0 en el registro referenciado por el parámetro p. La función devuelve el registro modificado.

struct alumn fun(FILE *pf, int p)
{
    struct alumn a;
    /* Código a completar */
    fseek(pf, (long)p * sizeof(a), SEEK_SET); // Posicionar al inicio del registro 'p'
    fread(&a, sizeof(a), 1, pf);             // Leer el registro
    a.nota = 5.0;                            // Modificar la nota
    fseek(pf, (long)p * sizeof(a), SEEK_SET); // Volver a posicionar para escribir
    fwrite(&a, sizeof(a), 1, pf);            // Escribir el registro modificado
    return (a);
}

Las líneas proporcionadas para completar la función son:

fseek(pf, (long)p * sizeof(a), 0); // 0 es SEEK_SET
fread(&a, sizeof(a), 1, pf);
a.nota = 5.0;
fseek(pf, (long)p * sizeof(a), 0); // 0 es SEEK_SET
fwrite(&a, sizeof(a), 1, pf);

Conceptos de Pila: Push y Pop

  • Push: Operación para insertar un elemento en la pila.
  • Pop: Operación para extraer un elemento de la pila.

Ejercicio: Intercambio de Registros en Fichero

Un fichero de estructuras llamado alumnos contiene estructuras del tipo struct alu, y está abierto (en modo w+) y apuntado por el puntero pf. Indicar qué sentencias hay que sustituir por el comentario, para que la función fun intercambie el primer registro del fichero por el último registro.

struct alu
{
    char nombre[50];
    double nota;
};

void fun(FILE *pf)
{
    struct alu a, b;
    int n_reg;
    /* Código a completar */
    fseek(pf, 0L, SEEK_END); // Mover al final del fichero
    n_reg = (int)ftell(pf) / sizeof(struct alu); // Calcular número total de registros

    fseek(pf, (long)0 * sizeof(struct alu), SEEK_SET); // Posicionar al primer registro
    fread(&a, sizeof(struct alu), 1, pf);             // Leer el primer registro

    fseek(pf, (long)(n_reg - 1) * sizeof(struct alu), SEEK_SET); // Posicionar al último registro
    fread(&b, sizeof(struct alu), 1, pf);                       // Leer el último registro

    fseek(pf, (long)0 * sizeof(struct alu), SEEK_SET); // Volver a posicionar para escribir el primer registro
    fwrite(&b, sizeof(struct alu), 1, pf);            // Escribir el último registro en la posición del primero

    fseek(pf, (long)(n_reg - 1) * sizeof(struct alu), SEEK_SET); // Volver a posicionar para escribir el último registro
    fwrite(&a, sizeof(struct alu), 1, pf);                      // Escribir el primer registro en la posición del último
}

Las líneas proporcionadas para completar la función son:

fseek(pf, 0L, SEEK_END);
n_reg = (int)ftell(pf) / sizeof(struct alu);
fseek(pf, (long)0 * sizeof(struct alu), 0); // 0 es SEEK_SET
fread(&a, sizeof(struct alu), 1, pf);
fseek(pf, (long)(n_reg - 1) * sizeof(struct alu), 0); // 0 es SEEK_SET
fread(&b, sizeof(struct alu), 1, pf);
fseek(pf, (long)0 * sizeof(struct alu), 0); // 0 es SEEK_SET
fwrite(&b, sizeof(struct alu), 1, pf);
fseek(pf, (long)(n_reg - 1) * sizeof(struct alu), 0); // 0 es SEEK_SET
fwrite(&a, sizeof(struct alu), 1, pf);

Entradas relacionadas: