aula 250

Como remover um nó da estrutura lista simplesmente encadeada?

Dando continuidade ao nosso Curso de Programação C e ao estudo da estrutura lista encadeada, vamos nesta aula aprender como remover um nó da estrutura lista simplesmente encadeada. Nesta primeira versão não utilizaremos a estrutura Lista, apenas a estrutura Nó.

Para remover um nó é necessário realizar uma busca, descobrir onde se encontra o elemento que desejamos remover. Assim como na inserção ordenada, teremos aqui ao menos duas possibilidades, remover o primeiro nó ou remover um nó no meio da lista.

Para remover o primeiro nó precisamos criar um ponteiro auxiliar para o mesmo e, em seguida, fazer o início da lista apontar para o próximo nó do nó que será removido. Para o retorno ha diversas possibilidades e a escolha vai depender do problema que você está resolvendo com uma lista encadeada. A primeira possibilidade é não retornar, liberando a memória do nó a ser removido. A segunda possibilidade é retornar apenas a informação do nó, neste caso um número inteiro. Por fim, podemos também retornar o ponteiro para o nó que está sendo removido. Aqui irei adotar esta terceira opção.

/*
     remoção do primeiro nó da lista
     num = valor a ser removido da lista
*/

    No *remover = NULL;

    if(*lista){
        if((*lista)->valor == num){
            remover = *lista;
            *lista = remover->proximo;
        }
        else{
            ...
        }
    }
    return remover;

Se o valor a ser removido não for o valor do primeiro nó, então precisamos percorrer a lista em busca deste valor que pode ou não existir. Criamos um ponteiro auxiliar para percorrer a lista enquanto o próximo for diferente de nulo e seu valor for diferente do valor procurado.

Esta repetição pode finalizar por dois motivos: ou porque encontramos o nó a ser removido ou porque chegamos ao final da fila. Se chegamos ao final da fila então o próximo será nulo e não faremos nada. Contudo, se o próximo for diferente de nulo, então é ele que iremos remover fazendo as devidas manipulações dos ponteiros.

/*
      função completa para remover um nó da lista
*/
No* remover(No **lista, int num){
    No *aux, *remover = NULL;

    if(*lista){
        if((*lista)->valor == num){
            remover = *lista;
            *lista = remover->proximo;
        }
        else{
            aux = *lista;
            while(aux->proximo && aux->proximo->valor != num)
                aux = aux->proximo;
            if(aux->proximo){
                remover = aux->proximo;
                aux->proximo = remover->proximo;
            }
        }
    }
    return remover;
}

Código completo em C para remover da Lista Simplesmente Encadeada

/*
            Código escrito por Wagner Gaspar
            Agosto de 2021

            Aula 250: Lista Simplesmente Encadeada
            Como remover SEM a estrutura lista?
*/

typedef struct no{
    int valor;
    struct no *proximo;
}No;

// procedimento para inserir no início
void inserir_no_inicio(No **lista, int num){
    No *novo = malloc(sizeof(No));

    if(novo){
        novo->valor = num;
        novo->proximo = *lista;
        *lista = novo;
    }
    else
        printf("Erro ao alocar memoria!\n");
}

// procedimento para inserir no fim
void inserir_no_fim(No **lista, int num){
    No *aux, *novo = malloc(sizeof(No));

    if(novo){
        novo->valor = num;
        novo->proximo = NULL;

        // é o primeiro?
        if(*lista == NULL)
            *lista = novo;
        else{
            aux = *lista;
            while(aux->proximo)
                aux = aux->proximo;
            aux->proximo = novo;
        }
    }
    else
        printf("Erro ao alocar memoria!\n");
}

// procedimento para inserir no meio
void inserir_no_meio(No **lista, int num, int ant){
    No *aux, *novo = malloc(sizeof(No));

    if(novo){
        novo->valor = num;
        // é o primeiro?
        if(*lista == NULL){
            novo->proximo = NULL;
            *lista = novo;
        }
        else{
            aux = *lista;
            while(aux->valor != ant && aux->proximo)
                aux = aux->proximo;
            novo->proximo = aux->proximo;
            aux->proximo = novo;
        }
    }
    else
        printf("Erro ao alocar memoria!\n");
}

// procedimento para inserir ordenado
void inserir_ordenado(No **lista, int num){
    No *aux, *novo = malloc(sizeof(No));

    if(novo){
        novo->valor = num;
        // a lista está vazia?
        if(*lista == NULL){
            novo->proximo = NULL;
            *lista = novo;
        } // é o menor?
        else if(novo->valor < (*lista)->valor){
            novo->proximo = *lista;
            *lista = novo;
        }
        else{
            aux = *lista;
            while(aux->proximo && novo->valor > aux->proximo->valor)
                aux = aux->proximo;
            novo->proximo = aux->proximo;
            aux->proximo = novo;
        }
    }
    else
        printf("Erro ao alocar memoria!\n");
}

// função para remover um nó da lista
No* remover(No **lista, int num){
    No *aux, *remover = NULL;

    if(*lista){
        if((*lista)->valor == num){
            remover = *lista;
            *lista = remover->proximo;
        }
        else{
            aux = *lista;
            while(aux->proximo && aux->proximo->valor != num)
                aux = aux->proximo;
            if(aux->proximo){
                remover = aux->proximo;
                aux->proximo = remover->proximo;
            }
        }
    }
    return remover;
}

void imprimir(No *no){
    printf("\n\tLista: ");
    while(no){
        printf("%d ", no->valor);
        no = no->proximo;
    }
    printf("\n\n");
}

int main(){

    int opcao, valor, anterior;
    No *removido, *lista = NULL;

    do{
        printf("\n\t0 - Sair\n\t1 - InserirI\n\t2 - inserirF\n\t3 - InserirM\n\t4 - InserirO\n\t5 - Remover\n\t6 - Imprimir\n");
        scanf("%d", &opcao);

        switch(opcao){
        case 1:
            printf("Digite um valor: ");
            scanf("%d", &valor);
            inserir_no_inicio(&lista, valor);
            break;
        case 2:
            printf("Digite um valor: ");
            scanf("%d", &valor);
            inserir_no_fim(&lista, valor);
            break;
        case 3:
            printf("Digite um valor e o valor de referencia: ");
            scanf("%d%d", &valor, &anterior);
            inserir_no_meio(&lista, valor, anterior);
            break;
        case 4:
            printf("Digite um valor: ");
            scanf("%d", &valor);
            inserir_ordenado(&lista, valor);
            break;
        case 5:
            printf("Digite um valor a ser removido: ");
            scanf("%d", &valor);
            removido = remover(&lista, valor);
            if(removido){
                printf("Elemento a ser removido: %d\n", removido->valor);
                free(removido);
            }
            else
                printf("Elemento inexistente!\n");
            break;
        case 6:
            imprimir(lista);
            break;
        default:
            if(opcao != 0)
                printf("Opcao invalida!\n");
        }

    }while(opcao != 0);

    return 0;
}

Deixe um comentário

13 − 3 =

Wagner Gaspar

Capixaba de São Gabriel da Palha, Espírito Santo. Bacharel em Ciência da Computação pela Universidade Federal do Amazonas e mestre em informática pela Universidade Federal do Espírito Santo.