Implementación de Listas Secuenciales en C

Una lista secuencial es una estructura de datos lineal que almacena elementos en posiciones de memoria contiguas. Esta estructura permite un acceso rápido a cualquier elemento mediante su índice, pero tiene desventajas en operaciones de inserción y eliminación que requieren movimiento de elementos. A continuación, exploraremos su implementación en C.

Estructuras de Datos Fundamentales

Lista Estática

Utiliza un arreglo de tamaño fijo definido en tiempo de compilación. Su principal limitación es que no permite redimensionamiento dinámico.

#define MAX_ELEMENTOS 50
typedef int TipoDato;

typedef struct {
    TipoDato datos[MAX_ELEMENTOS];
    int contador;
} ListaEstatica;

Lista Dinámica

Emplea memoria asignaad dinámicamente, lo que permite ajustar el tamaño según las necesidades durante la ejecución.

typedef int TipoDato;

typedef struct {
    TipoDato* elementos;
    int longitud;
    int capacidad;
} ListaDinamica;

Operaciones Fundamentales

Inicialización

Prepara la estructura para su uso estableciendo punteros a NULL y contadores a cero.

#include <stdio.h>
#include <stdlib.h>

void inicializarLista(ListaDinamica* lista) {
    lista->elementos = NULL;
    lista->longitud = 0;
    lista->capacidad = 0;
}

Gestión de Memoria

Controla la expansión automática cuando se requiere más espacio de almacenamiento.

void verificarCapacidad(ListaDinamica* lista) {
    if (lista->longitud == lista->capacidad) {
        int nuevaCapacidad = lista->capacidad == 0 ? 4 : lista->capacidad * 2;
        TipoDato* nuevoArreglo = realloc(lista->elementos, nuevaCapacidad * sizeof(TipoDato));
        
        if (nuevoArreglo == NULL) {
            fprintf(stderr, "Error en la asignación de memoria\n");
            exit(EXIT_FAILURE);
        }
        
        lista->elementos = nuevoArreglo;
        lista->capacidad = nuevaCapacidad;
    }
}

Inserción en Posición Específica

Desplaza los elementos existentes para crear espacio en la posición deseada.

void insertarEnPosicion(ListaDinamica* lista, int posicion, TipoDato valor) {
    if (posicion < 0 || posicion > lista->longitud) {
        fprintf(stderr, "Posición fuera de rango\n");
        return;
    }
    
    verificarCapacidad(lista);
    
    for (int i = lista->longitud; i > posicion; i--) {
        lista->elementos[i] = lista->elementos[i-1];
    }
    
    lista->elementos[posicion] = valor;
    lista->longitud++;
}

Eliminación de Elementos

Remueve un elemento y reorganiza la estructura manteniendo la continuidad.

void eliminarDePosicion(ListaDinamica* lista, int posicion) {
    if (posicion < 0 || posicion >= lista->longitud) {
        fprintf(stderr, "Índice no válido\n");
        return;
    }
    
    for (int i = posicion; i < lista->longitud - 1; i++) {
        lista->elementos[i] = lista->elementos[i+1];
    }
    
    lista->longitud--;
}

Búsqueda de Elementos

Recorre secuencialmente la estructura hasta encontrar el elemento buscado.

int buscarElemento(ListaDinamica* lista, TipoDato objetivo) {
    for (int idx = 0; idx < lista->longitud; idx++) {
        if (lista->elementos[idx] == objetivo) {
            return idx;
        }
    }
    return -1;
}

Operaciones de Extremos

Inserción al Final

Añade un nuevo elemento incrementando el contador de elementos.

void agregarAlFinal(ListaDinamica* lista, TipoDato nuevoValor) {
    verificarCapacidad(lista);
    lista->elementos[lista->longitud] = nuevoValor;
    lista->longitud++;
}

Eliminación del Final

Reduce el contador de elementos sin necesidad de desplazar datos.

void removerUltimo(ListaDinamica* lista) {
    if (lista->longitud > 0) {
        lista->longitud--;
    }
}

Visualización del Contenido

Muestra todos los elementos almacenados en formato legible.

void mostrarLista(ListaDinamica* lista) {
    printf("Contenido: ");
    for (int pos = 0; pos < lista->longitud; pos++) {
        printf("%d ", lista->elementos[pos]);
    }
    printf("\n");
}

Código Completo Integrado

#include <stdio.h>
#include <stdlib.h>
#include <assert.h>

typedef int TipoDato;

typedef struct {
    TipoDato* elementos;
    int longitud;
    int capacidad;
} ListaDinamica;

void inicializarLista(ListaDinamica* lista);
void verificarCapacidad(ListaDinamica* lista);
void insertarEnPosicion(ListaDinamica* lista, int posicion, TipoDato valor);
void eliminarDePosicion(ListaDinamica* lista, int posicion);
int buscarElemento(ListaDinamica* lista, TipoDato objetivo);
void agregarAlFinal(ListaDinamica* lista, TipoDato nuevoValor);
void removerUltimo(ListaDinamica* lista);
void mostrarLista(ListaDinamica* lista);
void liberarLista(ListaDinamica* lista);

void inicializarLista(ListaDinamica* lista) {
    lista->elementos = NULL;
    lista->longitud = 0;
    lista->capacidad = 0;
}

void verificarCapacidad(ListaDinamica* lista) {
    if (lista->longitud == lista->capacidad) {
        int nuevaCapacidad = lista->capacidad == 0 ? 4 : lista->capacidad * 2;
        TipoDato* nuevoArreglo = realloc(lista->elementos, nuevaCapacidad * sizeof(TipoDato));
        
        if (nuevoArreglo == NULL) {
            fprintf(stderr, "Error en asignación de memoria\n");
            exit(EXIT_FAILURE);
        }
        
        lista->elementos = nuevoArreglo;
        lista->capacidad = nuevaCapacidad;
    }
}

void insertarEnPosicion(ListaDinamica* lista, int posicion, TipoDato valor) {
    assert(posicion >= 0 && posicion <= lista->longitud);
    verificarCapacidad(lista);
    
    for (int i = lista->longitud; i > posicion; i--) {
        lista->elementos[i] = lista->elementos[i-1];
    }
    
    lista->elementos[posicion] = valor;
    lista->longitud++;
}

void eliminarDePosicion(ListaDinamica* lista, int posicion) {
    assert(posicion >= 0 && posicion < lista->longitud);
    
    for (int i = posicion; i < lista->longitud - 1; i++) {
        lista->elementos[i] = lista->elementos[i+1];
    }
    
    lista->longitud--;
}

int buscarElemento(ListaDinamica* lista, TipoDato objetivo) {
    for (int idx = 0; idx < lista->longitud; idx++) {
        if (lista->elementos[idx] == objetivo) {
            return idx;
        }
    }
    return -1;
}

void agregarAlFinal(ListaDinamica* lista, TipoDato nuevoValor) {
    verificarCapacidad(lista);
    lista->elementos[lista->longitud] = nuevoValor;
    lista->longitud++;
}

void removerUltimo(ListaDinamica* lista) {
    assert(lista->longitud > 0);
    lista->longitud--;
}

void mostrarLista(ListaDinamica* lista) {
    printf("Contenido: ");
    for (int pos = 0; pos < lista->longitud; pos++) {
        printf("%d ", lista->elementos[pos]);
    }
    printf("\n");
}

void liberarLista(ListaDinamica* lista) {
    free(lista->elementos);
    lista->elementos = NULL;
    lista->longitud = 0;
    lista->capacidad = 0;
}

Ejemplo de Prueba

int main() {
    ListaDinamica miLista;
    inicializarLista(&miLista);
    
    agregarAlFinal(&miLista, 10);
    agregarAlFinal(&miLista, 20);
    agregarAlFinal(&miLista, 30);
    mostrarLista(&miLista);
    
    insertarEnPosicion(&miLista, 1, 15);
    mostrarLista(&miLista);
    
    eliminarDePosicion(&miLista, 0);
    mostrarLista(&miLista);
    
    int indice = buscarElemento(&miLista, 20);
    printf("Encontrado en posición: %d\n", indice);
    
    liberarLista(&miLista);
    return 0;
}

Etiquetas: C estructuras-de-datos memoria-dinámica algoritmos

Publicado el 6-20 22:21