Listas Encadeadas
Na disciplina de Estrutura de Dados, estudamos as listas encadeadas, uma estrutura de dados dinâmica fundamental que organiza elementos de forma sequencial através de ponteiros, permitindo operações eficientes de inserção e remoção.
O que são Listas Encadeadas?
Uma lista encadeada é uma coleção de nós onde cada elemento contém um valor e um ponteiro para o próximo nó da sequência. Diferente dos vetores, as listas encadeadas não exigem alocação contígua de memória.
- Cada elemento é chamado de nó (node)
- O primeiro nó é chamado de cabeça (head)
- O último nó aponta para NULL
- Não possui tamanho fixo - cresce conforme a necessidade
Comparação: Vetores vs Listas Encadeadas
| Vetores (Arrays) | Listas Encadeadas |
|---|---|
| Tamanho fixo | Tamanho dinâmico |
| Alocação contígua de memória | Alocação dispersa na memória |
| Acesso rápido por índice (O(1)) | Acesso sequencial (O(n)) |
| Inserções/remoções custosas no meio | Inserções/remoções eficientes |
Estrutura de um Nó
Em C, cada nó é representado por uma struct que contém:
struct No { int valor; // Dado armazenado struct No *prox; // Ponteiro para o próximo nó };
Visualização de uma lista com 3 nós:
[10 | *] → [20 | *] → [30 | NULL]
Vantagens e Desvantagens
Vantagens:
- Tamanho flexível (cresce/shrink conforme necessidade)
- Inserções e remoções eficientes (O(1) no início)
- Não desperdiça memória com alocação prévia
- Ótima para implementação de pilhas e filas
Desvantagens:
- Acesso sequencial (precisa percorrer para encontrar elementos)
- Maior consumo de memória (armazena ponteiros além dos dados)
- Não permite acesso aleatório eficiente
- Mais complexa de implementar que arrays
Operações Principais
As operações básicas em listas encadeadas incluem:
- Inserção no início - Adiciona um novo nó no começo da lista
- Inserção no fim - Adiciona um novo nó no final da lista
- Remoção - Remove um nó com valor específico
- Busca - Procura um valor na lista
- Percorrer - Visita todos os nós da lista
Inserção no Início
Adiciona um novo elemento no começo da lista, tornando-o o novo head:
struct No* inserirInicio(struct No *head, int novoValor) { struct No *novoNo = (struct No*)malloc(sizeof(struct No)); novoNo->valor = novoValor; novoNo->prox = head; // Novo nó aponta para o antigo head return novoNo; // Retorna o novo nó como novo head }
Complexidade: O(1) - tempo constante
Inserção no Fim
Adiciona um novo elemento no final da lista, exigindo percorrê-la até o último nó:
struct No* inserirFim(struct No *head, int novoValor) { struct No *novoNo = (struct No*)malloc(sizeof(struct No)); novoNo->valor = novoValor; novoNo->prox = NULL;
if (head == NULL) return novoNo;
struct No *atual = head;
while (atual->prox != NULL) {
atual = atual->prox;
}
atual->prox = novoNo;
return head;
}
Complexidade: O(n) - precisa percorrer toda a lista
Remoção de um Elemento
Remove um nó específico da lista, ajustando os ponteiros vizinhos:
struct No* removerElemento(struct No *head, int valor) { if (head == NULL) return NULL;
// Caso especial: remoção do primeiro nó
if (head->valor == valor) {
struct No *temp = head->prox;
free(head);
return temp;
}
struct No *anterior = head;
struct No *atual = head->prox;
while (atual != NULL && atual->valor != valor) {
anterior = atual;
atual = atual->prox;
}
if (atual != NULL) {
anterior->prox = atual->prox;
free(atual);
}
return head;
}
Percorrer a Lista
Visita cada nó da lista sequencialmente, útil para imprimir ou processar elementos:
void imprimirLista(struct No *head) { struct No *atual = head; while (atual != NULL) { printf("%d -> ", atual->valor); atual = atual->prox; } printf("NULL\n"); }
Busca de Elemento
Procura por um valor específico na lista, retornando seu endereço se encontrado:
struct No* buscarElemento(struct No *head, int valor) { struct No *atual = head; while (atual != NULL) { if (atual->valor == valor) { return atual; } atual = atual->prox; } return NULL; }
Aplicações das Listas Encadeadas
As listas encadeadas são fundamentais para implementar:
- Pilhas (Stacks) - LIFO (Last In First Out)
- Filas (Queues) - FIFO (First In First Out)
- Listas duplamente encadeadas - Navegação em ambas direções
- Grafos - Representação de adjacências
- Sistemas de arquivos - Alocação não contígua