Remove element from a linked list

3

I am implementing a chained list of type "with head". It follows struct referring to the list and creating it in main ()

struct lista{
    int info;
    struct lista *prox;
};
typedef struct lista Lista;


int main ()
{
    Lista *l, *aux;

    l = (Lista*) malloc(sizeof(Lista));

    l->prox = NULL;

    //Trechos de código

    retira_n(l, n);
}

Next follows the function that removes all occurrences of a given number "n" from the list and returns the list

Lista* retira_n(Lista *l, int n)
{
    Lista *atual, *ant, *atual2;
    int flag = 0;

    atual = l->prox;
    ant = l->prox;

    while(atual != NULL)
    {
        if(atual == l->prox && atual->info == n)
        {
            l->prox = atual->prox;
            free(atual);
            atual = l->prox;
            flag++;
            continue;
        }
        else if(atual->info == n)
        {
            ant->prox = atual->prox;
            flag++;
        }

        ant = atual;
        atual = atual->prox;
    }

    if(flag == 0)
    {
        printf("O elemento nao esta na lista");
    }

    return l->prox;
}

The function is working in a partial way, that is, the list elements are not shown when I'm going to "start" the list, however, because I have not been able to deal with the free () function because if I am deallocating using the "current" pointer, for example, I will not be able to use it in other iterations to check the other elements of the list. I wanted a way to deallocate the element I want to delete and not just make the previous one point to the next element in the list.

    
asked by anonymous 21.09.2015 / 14:32

2 answers

2

Creating an additional pointer and causing it to point to the position of atual before atual receives the next you isolate the memory address to be freed, so you can use free normally.

Lista* retira_n(Lista *l, int n)
{
    Lista *atual, *ant, *atual2, *morto;
    int flag = 0;

    atual = l->prox;
    ant = l->prox;

    while(atual != NULL)
    {
        if(atual == l->prox && atual->info == n)
        {
            l->prox = atual->prox;
            morto = atual;
            atual = atual->prox;
            flag++;

        }
        else if(atual->info == n)
        {
            ant->prox = atual->prox;
            morto = atual;
            atual = atual->prox;
            flag++;
        }
        else
        {
            ant = atual;
            atual = atual->prox;
        }
        free(morto);
    }

    if(flag == 0)
    {
        printf("O elemento nao esta na lista");
    }

    return l->prox;
}
    
21.09.2015 / 16:33
2

Your code is confused in some ways - but to answer what you want, just re-type the second if so:

    else if(atual->info == n)
    {
        ant->prox = atual->prox;
        free(atual);
        atual = ant->prox;
        flag++;
    } else {
         ant->prox = atual;
         atual = atual->prox;
    }

Notice that it also changes to only advance the ant if the current node has not been removed - rows outside% w_that change w_th_% and w_th% must not be executed if the node has been removed. if it stays the same and ant advances).

Tip: Avoid using a variable named "l" - it's a difficult symbol to distinguish from "1". Another tip: your variable is a counter or is a flag - if it is a counter, avoid calling it a "flag".

    
21.09.2015 / 16:25