Listas encadeadas - remoção

Considere uma lista encadeada com nó cabeça le definida por células

typedef struct celula {
   int dado;
   struct celula *prox;
} celula;

Sua tarefa nesse exercício é implementar a operação de remoção da lista encadeada encabeçada por le. Para tanto, você deve submeter um arquivo contendo apenas:

  1. Os #include necessários para execução das instruções utilizadas no seu código.

  2. A definição da struct celula.

  3. Uma função que remove o elemento imediatamente seguinte do ponteiro pp, com protótipo
int remove_depois (celula *p);

Sua função deve ser capaz de lidar com o(s) caso(s) em que não seja possível remover o elemento seguinte a pp.

  1. Uma função que remove a primeira ocorrência de xx da lista encadeada, cujo protótipo é
void remove_elemento (celula *le, int x);
  1. Uma função que remove todas as ocorrências de xx da lista encadeada, cujo protótipo é
void remove_todos_elementos (celula *le, int x);