Fácil C
Inserir no final
Enunciado
Escreva uma função inserir_fim que adiciona um novo nó com um valor inteiro no final da lista encadeada. A função deve retornar o ponteiro para o início da lista (que pode ser NULL se a lista estiver vazia).
Requisitos
- A função deve alocar memória para o novo nó.
- Se a lista estiver vazia, o novo nó se torna a cabeça.
- Caso contrário, percorra até o último nó e ajuste o ponteiro
prox.
Código inicial
#include <stdio.h>
#include <stdlib.h>
typedef struct No {
int valor;
struct No *prox;
} No;
No* inserir_fim(No *head, int valor) {
// TODO: implemente
}
void imprimir(No *head) {
for (No *p = head; p; p = p->prox)
printf("%d -> ", p->valor);
printf("NULL\n");
}
int main(void) {
No *lista = NULL;
lista = inserir_fim(lista, 10);
lista = inserir_fim(lista, 20);
lista = inserir_fim(lista, 30);
imprimir(lista);
// liberar memória...
return 0;
}
Saída esperada
10 -> 20 -> 30 -> NULL
Ver dica
Crie um novo nó, se a lista estiver vazia retorne o novo nó. Senão, use um ponteiro auxiliar para chegar ao último nó e faça ultimo->prox = novo.
Mostrar solução
#include <stdio.h>
#include <stdlib.h>
typedef struct No {
int valor;
struct No *prox;
} No;
No* inserir_fim(No *head, int valor) {
No *novo = malloc(sizeof(No));
if (!novo) { perror("malloc"); exit(1); }
novo->valor = valor;
novo->prox = NULL;
if (head == NULL) {
return novo; // lista vazia: novo é a cabeça
}
No *atual = head;
while (atual->prox != NULL) {
atual = atual->prox;
}
atual->prox = novo; // liga o último ao novo
return head;
}
void imprimir(No *head) {
for (No *p = head; p; p = p->prox)
printf("%d -> ", p->valor);
printf("NULL\n");
}
void liberar(No *head) {
while (head) {
No *prox = head->prox;
free(head);
head = prox;
}
}
int main(void) {
No *lista = NULL;
lista = inserir_fim(lista, 10);
lista = inserir_fim(lista, 20);
lista = inserir_fim(lista, 30);
imprimir(lista);
liberar(lista);
return 0;
}
Passo a passo
- Alocamos um novo nó com
malloce definimos seu valor eprox = NULL. - Se a lista está vazia (
head == NULL), retornamos o novo nó como nova cabeça. - Caso contrário, usamos
atualpara percorrer a lista até o último nó (quandoatual->prox == NULL). - Ligamos o último nó ao novo:
atual->prox = novo. - Retornamos
head(a cabeça não mudou). - No
main, chamamosinserir_fimtrês vezes e imprimimos. - Por fim, liberamos a memória com
liberar.
Por que funciona
A função percorre a lista até o final e conecta o novo nó ao último, mantendo a cabeça inalterada. Isso garante que a lista permaneça encadeada corretamente. A alocação dinâmica permite que a lista cresça em tempo de execução.
Erros comuns
- Esquecer de inicializar
novo->prox = NULL: se não fizer, o último nó pode apontar para lixo, causando comportamento indefinido na impressão. - Não tratar lista vazia: se
headforNULLe você tentaratual->prox, ocorre erro de segmentação. - Não retornar a cabeça: em listas vazias, a nova cabeça é o novo nó; esquecer de retornar
novofaz a lista se perder. - Vazamento de memória: não liberar os nós ao final do programa.
Outra forma de resolver
Usar um ponteiro para ponteiro (No **head) para modificar a cabeça diretamente, evitando retorno. Exemplo:
void inserir_fim(No **head, int valor) {
No *novo = malloc(sizeof(No));
novo->valor = valor;
novo->prox = NULL;
No **pp = head;
while (*pp) pp = &(*pp)->prox;
*pp = novo;
}
Essa abordagem é preferível quando se deseja modificar a lista sem retornar o novo ponteiro.
Saída esperada
10 -> 20 -> 30 -> NULL