-
Uma lista encadeada simples em C é uma estrutura de dados que consiste em nós ligados em uma sequência, onde cada nó contém dois campos: um campo de dados para armazenar informações e um ponteiro que aponta para o próximo nó na lista.
-
Chamos cada elemento da lista de nó, e um conjunto de nós é chamado de lista encadeada.
struct lista
{
int info;
struct lista *prox;
};
-
Info: Representa o dado armazenado na lista, que, no exemplo acima, é um valor inteiro. No entanto, pode ser utilizado para armazenar qualquer tipo de dado, inclusive estruturas (como a struct aluno, por exemplo).
-
Prox: Armazena o endereço do próximo elemento da lista. Em outras palavras, cada nó mantém um ponteiro para o próximo elemento usando este campo.
-
Alocação Dinâmica de Memória: Permite a alocação dinâmica de memória, facilitando a adição e remoção de elementos conforme necessário.
-
Inserção e Exclusão Eficientes: Inserir ou excluir elementos no início é eficiente, minimizando a necessidade de deslocamento de dados.
-
Redimensionamento Dinâmico: A lista pode crescer ou encolher conforme necessário, adequando-se a tamanhos variáveis de dados.
-
Acesso direto ineficiente: O acesso a um elemento específico requer percorrer a lista, o que é menos eficiente que arrays para acesso direto por índice.
-
Gasto de memória extra por elemento: Cada nó requer espaço extra para o ponteiro, aumentando o consumo de memória em comparação com arrays.
-
Complexidade de implementação: Implementar operações pode ser mais complexo devido à gestão de ponteiros e alocação dinâmica de memória.
-
Reutilização de Código: Uma vez que as operações da lista estão encapsuladas no TAD Lista, elas podem ser reutilizadas em diferentes partes do código ou em projetos diferentes sem a necessidade de reimplementação. Isso economiza tempo e esforço.
-
Encapsulamento: O TAD Lista permite encapsular a implementação da lista. Isso significa que você pode mudar a implementação interna da lista sem afetar o código que a utiliza.
-
Ocultação de Complexidade: A implementação de estruturas de dados como listas encadeadas pode ser complexa, envolvendo alocação de memória, gerenciamento de ponteiros e manipulação de nós. O TAD Lista oculta essa complexidade, tornando mais fácil para outros desenvolvedores usar a lista sem se preocupar com os detalhes complicados.
-
Padronização: O TAD Lista estabelece um conjunto padrão de operações e nomes para trabalhar com listas. Isso torna o código mais consistente e fácil de entender para qualquer desenvolvedor.
-
Facilita a Depuração: Se ocorrer um erro em uma operação da lista, é mais fácil depurar(Achar o erro) quando você tem uma interface clara e bem definida para a lista. Você pode isolar o problema mais facilmente.
-
Documentação: O TAD Lista serve como documentação clara das operações suportadas pela lista. Isso ajuda a vocês (desenvolvedores) a entender como usar a lista corretamente.
- Descrição: Cria uma lista encadeada vazia.
Lista *lst_cria(void)
{
return NULL;
}
- Uso:
Lista *lista = lst_cria();
- Descrição: Insere um novo elemento no início da lista.
Lista *lst_insere(Lista *l, int v)
{
Lista *novo = (Lista *)malloc(sizeof(Lista));
if (novo == NULL)
{
printf("[ERRO] Memória insuficiente!");
exit(1);
}
novo->info = v;
novo->prox = l;
return novo;
}
- Uso:
lista = lst_insere(lista, 42);
- Descrição: Verifica se a lista está vazia.
int lst_vazia(Lista *l)
{
return (l == NULL);
}
- Uso:
if (lst_vazia(lista)) {
printf("A lista está vazia.\n");
}
- Descrição: Imprime os elementos da lista.
void lst_imprime(Lista *l)
{
Lista *p;
for (p = l; p != NULL; p = p->prox)
{
printf(" Info = %d \n", p->info);
}
}
- Uso:
lst_imprime(lista);
- Descrição: Busca por um elemento na lista.
Lista *lst_busca(int elemento, Lista *l)
{
Lista *p;
for (p = l; p != NULL; p = p->prox)
{
if (p->info == elemento)
return p;
}
return NULL;
}
- Uso:
Lista *resultado = lst_busca(42, lista);
- Descrição: Remove um elemento da lista.
Lista *lst_retira(Lista *l, int v)
{
Lista *ant = NULL;
Lista *p = l;
while (p->info != v)
{
if (p == NULL)
return l;
ant = p;
p = p->prox;
}
if (ant == NULL)
l = p->prox;
else
ant->prox = p->prox;
free(p);
return l;
}
- Uso:
lista = lst_retira(lista, 42);
- Descrição: Libera a memória ocupada pela lista.
void lst_libera(Lista *l)
{
Lista *p = l;
Lista *t;
while (p != NULL)
{
t = p->prox;
free(p);
p = t;
}
}
- Uso:
lst_libera(lista);
- Descrição: Insere um elemento de forma ordenada na lista.
Lista *lst_insere_ordenada(Lista *l, int v)
{
Lista *novo;
Lista *ant = NULL;
Lista *p = l;
while (p != NULL && p->info < v)
{
ant = p;
p = p->prox;
}
novo = (Lista *)malloc(sizeof(Lista));
novo->info = v;
if (ant == NULL)
{
novo->prox = l;
l = novo;
}
else
{
novo->prox = ant->prox;
ant->prox = novo;
}
return l;
}
- Uso:
lista = lst_insere_ordenada(lista, 42);
- Descrição: Lê valores de um arquivo e insere na lista.
Lista *lst_ler_arquivo(char *nome_arquivo)
{
FILE *arquivo;
int valor;
Lista *l = lst_cria();
arquivo = fopen(nome_arquivo, "r");
if (arquivo == NULL)
{
printf("Erro ao abrir o arquivo!\n");
exit(1);
}
while (fscanf(arquivo, "%d", &valor) != EOF)
{
l = lst_insere(l, valor);
}
fclose(arquivo);
return l;
}
- Uso:
lista = lst_ler_arquivo("dados.txt");