Implementação de uma Lista Sequencial Dinâmica em C

O modelo básico consiste em uma estrutura de cabeçalho que contém um ponteiro para os dados, a capacidade máxima e o comprimento atual. O ponteiro aponta para uma área de memória alocada dinamicamente para armaznear os elementos. Quando o comprimento atinge a capacidade, a lista é expandida para acomodar mais itens.

Implementação em C

A seguir, apresenta-se uma implementação dividida em três arquivos: um cabeçalho e dois arquivos de código-fonte.

Arquivo de cabeçalho: lista_seq.h


typedef int tipo_elemento;

typedef struct {
    tipo_elemento *dados;
    int capacidade;
    int comprimento;
} ListaSequencial;

void inicializar_lista(ListaSequencial *ls, int tam);
void liberar_lista(ListaSequencial *ls);
void inserir_no_fim(ListaSequencial *ls, tipo_elemento valor);
void inserir_em_posicao(ListaSequencial *ls, int pos, tipo_elemento valor);
void exibir_lista(const ListaSequencial *ls);
int buscar_elemento(const ListaSequencial *ls, tipo_elemento valor);
void remover_por_valor(ListaSequencial *ls, tipo_elemento valor);

ListaSequencial *criar_lista(int tam);
void destruir_lista(ListaSequencial *ls);

Arquivo de implementação: lista_seq.c


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

void inicializar_lista(ListaSequencial *ls, int tam) {
    ls->dados = (tipo_elemento *)malloc(sizeof(tipo_elemento) * tam);
    if (ls->dados == NULL) {
        ls->capacidade = 0;
        return;
    }
    ls->capacidade = tam;
    ls->comprimento = 0;
}

void liberar_lista(ListaSequencial *ls) {
    if (ls->dados != NULL) {
        free(ls->dados);
        ls->dados = NULL;
    }
    ls->capacidade = 0;
    ls->comprimento = 0;
}

static int expandir_lista(ListaSequencial *ls) {
    int nova_capacidade = ls->capacidade * 2;
    tipo_elemento *temp = (tipo_elemento *)malloc(sizeof(tipo_elemento) * nova_capacidade);
    if (temp == NULL) {
        return -1;
    }
    for (int i = 0; i < ls->comprimento; ++i) {
        temp[i] = ls->dados[i];
    }
    free(ls->dados);
    ls->dados = temp;
    ls->capacidade = nova_capacidade;
    printf("Lista expandida com sucesso!\n");
    return 0;
}

void inserir_no_fim(ListaSequencial *ls, tipo_elemento valor) {
    if (ls->comprimento >= ls->capacidade && expandir_lista(ls) != 0) {
        printf("Falha ao expandir a lista!\n");
        return;
    }
    ls->dados[ls->comprimento] = valor;
    ++ls->comprimento;
}

void inserir_em_posicao(ListaSequencial *ls, int pos, tipo_elemento valor) {
    if (pos < 0 || pos > ls->comprimento) {
        printf("Posição inválida!\n");
        return;
    }
    if (ls->comprimento >= ls->capacidade && expandir_lista(ls) != 0) {
        return;
    }
    for (int i = ls->comprimento - 1; i >= pos; --i) {
        ls->dados[i + 1] = ls->dados[i];
    }
    ls->dados[pos] = valor;
    ++ls->comprimento;
}

void exibir_lista(const ListaSequencial *ls) {
    for (int i = 0; i < ls->comprimento; ++i) {
        printf("%d\t", ls->dados[i]);
    }
    printf("\n");
}

int buscar_elemento(const ListaSequencial *ls, tipo_elemento valor) {
    for (int i = 0; i < ls->comprimento; ++i) {
        if (ls->dados[i] == valor) {
            return i;
        }
    }
    return -1;
}

void remover_por_valor(ListaSequencial *ls, tipo_elemento valor) {
    int pos = buscar_elemento(ls, valor);
    if (pos == -1) {
        printf("Elemento não encontrado!\n");
        return;
    }
    for (int i = pos + 1; i < ls->comprimento; ++i) {
        ls->dados[i - 1] = ls->dados[i];
    }
    --ls->comprimento;
}

ListaSequencial *criar_lista(int tam) {
    ListaSequencial *ls = (ListaSequencial *)malloc(sizeof(ListaSequencial));
    if (ls == NULL) {
        return NULL;
    }
    inicializar_lista(ls, tam);
    return ls;
}

void destruir_lista(ListaSequencial *ls) {
    liberar_lista(ls);
    free(ls);
}

Arquivo de teste: teste.c


#include "lista_seq.h"
#include <stdio.h>

void testar_operacoes(ListaSequencial *ls) {
    for (int i = 0; i < 5; i++) {
        inserir_no_fim(ls, 200 + i);
    }
    exibir_lista(ls);
    inserir_no_fim(ls, 400);
    exibir_lista(ls);
    inserir_em_posicao(ls, 1, 500);
    exibir_lista(ls);
    remover_por_valor(ls, 400);
    exibir_lista(ls);
}

void teste_com_variavel_local() {
    ListaSequencial ls;
    inicializar_lista(&ls, 10);
    testar_operacoes(&ls);
    liberar_lista(&ls);
}

void teste_com_ponteiro() {
    ListaSequencial *ls = criar_lista(10);
    if (ls != NULL) {
        testar_operacoes(ls);
        destruir_lista(ls);
    }
}

int main() {
    teste_com_variavel_local();
    printf("===\n");
    teste_com_ponteiro();
    return 0;
}

As operações de inserção e expansão requerem cuidado com as condições de contorno, especialmente para evitar acessos fora dos limites e garantir o gerenciamento correto da memória.

Tags: C lista sequencial estrutura de dados Alocação Dinâmica Memória

Publicado em 6-27 01:22