Removal of element at the beginning of the list chained in C

0

In this program in C, I'm trying to create a function that removes the first element from a linked dynamic list ...

#include <stdio.h>
#include <stdlib.h>

struct no {
    int dado;
    struct no *prox;
};

The functions of the simply linked list that I have implemented are as follows:

Print List

void imprimir(struct no *prim){
    struct no * atual;
    atual = prim;
    system("clear");
    printf("\nLista: ");

    while(atual != (struct no*)NULL)
    {
        printf("%d-> ",atual -> dado);
        atual = atual -> prox;
    }
}

Insert element at the beginning.

struct no * insere_inicio(struct no *prim){
    int num;
    struct no *novo;

    printf("\nInsira o elemento no inicio da lista: ");
    scanf("%d", &num);

    novo = (struct no*) malloc(sizeof(struct no*));
    novo -> dado = num;
    novo -> prox = prim;

    prim = novo;

    return prim;
}

Remove element from the beginning. Here is my problem, because instead of releasing memory and decrementing an element the function is just deleting the data from memory and returning the first node as 0 (zero).

Does anyone know what's wrong?

The rest of the code works.

struct no * remove_inicio(struct no *prim){

    struct no *aux = prim;

    if(prim == NULL){
        printf("Lista Vaia!");
    }

    prim = prim -> prox;
    free(aux);

    return prim;
}

Insert element at end.

struct no * insere_final(struct no *prim){
    int num;
    struct no *novo;
    struct no *atual;

    printf("Insira o elemento no final da lista: ");
    scanf("%d",&num);

    novo = (struct no*) malloc(sizeof(struct no*));
    novo -> dado = num;
    novo -> prox = NULL;

    atual = prim;

    while(atual -> prox != NULL){
        atual = atual -> prox;
    }

    atual -> prox = novo;
}

Remove element at the end.

struct no * remove_fim(struct no *prim){
    struct no *atual = prim;
    struct no *anterior;

    if(prim == NULL){
        printf("Lista Vaia!");
    }

    if(prim -> prox == NULL){
        prim = NULL;
        free(atual);
        printf("Removido do final!");
    }else{
        while(atual -> prox != NULL){
            anterior = atual;
            atual = atual -> prox;
        }
        anterior -> prox = NULL;
        free(atual);
        printf("Removido do final!");
    }
}

Function main .

int main(){
    int op;
    struct no *prim;
    prim = (struct no*) NULL;

    do{
        system("clear");
        printf("\n<1> - Inserir no inicio");
        printf("\n<2> - Inserir no final");
        printf("\n<3> - Remover no inicio");
        printf("\n<4> - Remover no final");
        printf("\n<5> - Imprimir");
        printf("\n<10> - Sair do programa\n\n");
        printf("Digite sua opcao: ");
        scanf("%d",&op);

        switch (op)
        {
            case 1 : prim = insere_inicio(prim);
            break;

            case 2 : insere_final(prim);
            break;

            case 3 : remove_inicio(prim);
            break;

            case 4 : remove_fim(prim);
            break;

            case 5 : imprimir(prim);
            break;

        };
    }while(op != 10);

    return 0;

}
    
asked by anonymous 17.12.2017 / 22:51

1 answer

0

I've reviewed your code. Follow below:

#include <stdio.h>
#include <stdlib.h>

struct no {
    int dado;
    struct no *prox;
};

void imprimir(struct no *prim) {
    struct no *atual = prim;
    system("clear");
    printf("\nLista: ");

    while (atual != NULL) {
        printf("%d -> ", atual->dado);
        atual = atual->prox;
    }
    printf("NULL");
}

struct no *insere_inicio(struct no *prim) {
    int num;

    printf("\nInsira o elemento no inicio da lista: ");
    scanf("%d", &num);

    struct no *novo = (struct no *) malloc(sizeof(struct no *));
    novo->dado = num;
    novo->prox = prim;

    return novo;
}

struct no *insere_final(struct no *prim) {
    int num;

    printf("Insira o elemento no final da lista: ");
    scanf("%d", &num);

    struct no *novo = (struct no *) malloc(sizeof(struct no *));
    novo->dado = num;
    novo->prox = NULL;

    if (prim == NULL) return novo;

    struct no *ultimo = prim;

    while (ultimo->prox != NULL) {
        ultimo = ultimo->prox;
    }

    ultimo->prox = novo;
    return prim;
}

struct no *remove_fim(struct no *prim) {
    if (prim == NULL) {
        printf("Lista Vazia!");
        return NULL;
    }
    if (prim->prox == NULL) {
        printf("Removido do final!");
        free(prim);
        return NULL;
    }

    struct no *penultimo = prim;
    struct no *ultimo = prim->prox;

    while (ultimo->prox != NULL) {
        penultimo = ultimo;
        ultimo = ultimo->prox;
    }

    penultimo->prox = NULL;
    free(ultimo);
    printf("Removido do final!");
    return prim;
}

int main() {
    int op;
    struct no *prim = NULL;

    do {
        system("clear");
        printf("\n<1> - Inserir no inicio");
        printf("\n<2> - Inserir no final");
        printf("\n<3> - Remover no inicio");
        printf("\n<4> - Remover no final");
        printf("\n<5> - Imprimir");
        printf("\n<10> - Sair do programa\n\n");
        printf("Digite sua opcao: ");
        scanf("%d", &op);

        switch (op) {
            case 1:
                prim = insere_inicio(prim);
                break;

            case 2:
                prim = insere_final(prim);
                break;

            case 3:
                prim = remove_inicio(prim);
                break;

            case 4:
                prim = remove_fim(prim);
                break;

            case 5:
                imprimir(prim);
                break;
        }
    } while (op != 10);

    return 0;
}

The changes I made were:

  • Never forget to assign the result of the functions to prim . Therefore, use prim = remove_fim(prim); instead of just remove_fim(prim); .

  • Its functions remove_fim and insere_final were forgetting to return the pointer from the beginning of the list.

  • Its functions remove_inicio , insere_final and remove_fim would not work if prim is NULL . Especially in the case of insere_final and remove_fim , you even detect the condition, but let it proceed in the same way.

  • The function remove_fim was possible to be greatly simplified, but simplified other things as well.

It seems that you think changing the value of the parameter pointer will be reflected in a change of the value of the pointer passed in the function. This is not true. The fact that you change the address pointed by prim within the calling function will not make the prim out (in main ) change. The change is only reflected when you change something in the value or structure that is pointed out, not in the pointer itself. So another possible solution to this would be to use pointers for pointers (which dispenses with the need to assign pointers returned in main ):

#include <stdio.h>
#include <stdlib.h>

struct no {
    int dado;
    struct no *prox;
};

void imprimir(struct no *prim) {
    struct no *atual = prim;
    system("clear");
    printf("\nLista: ");

    while (atual != NULL) {
        printf("%d -> ", atual->dado);
        atual = atual->prox;
    }
    printf("NULL");
}

void insere_inicio(struct no **prim) {
    int num;

    printf("\nInsira o elemento no inicio da lista: ");
    scanf("%d", &num);

    struct no *novo = (struct no *) malloc(sizeof(struct no *));
    novo->dado = num;
    novo->prox = *prim;
    *prim = novo;
}

void insere_final(struct no **prim) {
    int num;

    printf("Insira o elemento no final da lista: ");
    scanf("%d", &num);

    struct no *novo = (struct no *) malloc(sizeof(struct no *));
    novo->dado = num;
    novo->prox = NULL;

    if (*prim == NULL) {
        *prim = novo;
        return;
    }

    struct no *ultimo = *prim;

    while (ultimo->prox != NULL) {
        ultimo = ultimo->prox;
    }

    ultimo->prox = novo;
}

void remove_fim(struct no **prim) {
    if (*prim == NULL) {
        printf("Lista Vazia!");
        return;
    }
    if ((*prim)->prox == NULL) {
        printf("Removido do final!");
        free(*prim);
        *prim = NULL;
        return;
    }

    struct no *penultimo = *prim;
    struct no *ultimo = (*prim)->prox;

    while (ultimo->prox != NULL) {
        penultimo = ultimo;
        ultimo = ultimo->prox;
    }

    penultimo->prox = NULL;
    free(ultimo);
    printf("Removido do final!");
}

int main() {
    int op;
    struct no *prim = NULL;

    do {
        system("clear");
        printf("\n<1> - Inserir no inicio");
        printf("\n<2> - Inserir no final");
        printf("\n<3> - Remover no inicio");
        printf("\n<4> - Remover no final");
        printf("\n<5> - Imprimir");
        printf("\n<10> - Sair do programa\n\n");
        printf("Digite sua opcao: ");
        scanf("%d", &op);

        switch (op) {
            case 1:
                insere_inicio(&prim);
                break;

            case 2:
                insere_final(&prim);
                break;

            case 3:
                remove_inicio(&prim);
                break;

            case 4:
                remove_fim(&prim);
                break;

            case 5:
                imprimir(prim);
                break;
        }
    } while (op != 10);

    return 0;
}

Finally, I recommend that you review the name of some things, for the sake of consistency. You have insere_final and remove_fim instead of insere_final and remove_final or insere_fim and remove_fim .

    
18.12.2017 / 00:13