Search code examples
cstructlinked-listdoubly-linked-listfunction-definition

Deleting element from linked list in C


I am trying to write a function, which is deleting a specific element from my linked list, but it crash with segmentation fault when I reach the element. Here is a part of my code

typedef struct dlist_t {
    int data;
    struct dlist_t *prev, *next;
} dlist_t;

typedef struct list_t {
    dlist_t *head, *tail;
} list_t;

int delElement(list_t *list, int elem) {
    while (list) {
        if ((list->head)->data == elem) {
            list->head->next = list->head->prev;
            list->head->prev = list->head->next;
            free(list);
            return 1;
        }
        list = list->head->next;
    }
    return 0;
}

Solution

  • Your function definition does not make sense. For example in this assignment statement

    list = list->head->next;
    

    there are used objects of different types in the left hand side of the assignment (the type is list_t) and in the right hand side of the assignment (the type is dlist_t).

    Or this call

    free(list);
    

    tries to free the list instead of only its one node. And so on.

    The function can look the following way as it is shown in thje demonstrative program below.

    #include <stdio.h>
    #include <stdlib.h>
    
    typedef struct dlist_t 
    {
        int data;
        struct dlist_t *prev, *next;
    } dlist_t;
    
    typedef struct list_t 
    {
        dlist_t *head, *tail;
    } list_t;
    
    int delElement( list_t* list, int elem )
    {
        dlist_t **current = &list->head;
    
        while ( *current != NULL && ( *current )->data != elem )
        {
            current = &( *current )->next;
        }
    
        int success = *current != NULL;
    
        if ( success )
        {
            dlist_t *tmp = *current;
    
            if ( ( *current )->next != NULL )
            {
                ( *current )->next->prev  = ( *current )->prev;
            }
            else
            {
                list->tail = ( *current )->prev;
            }
    
            *current = ( *current )->next; 
    
            free( tmp );
        }
    
        return success;
    }
    
    int pushFront( list_t *list, int elem )
    {
        dlist_t *new_node = malloc( sizeof( dlist_t ) );
        int success = new_node != NULL;
    
        if ( success )
        {
            new_node->next = list->head;
            new_node->prev = NULL;
            new_node->data = elem;
    
            if ( list->head != NULL )
            {
                list->head->prev = new_node;
            }
            else
            {
                list->tail = new_node;
            }
    
            list->head = new_node;
        }
    
        return success;
    }
    
    int pushBack( list_t *list, int elem )
    {
        dlist_t *new_node = malloc( sizeof( dlist_t ) );
        int success = new_node != NULL;
    
        if ( success )
        {
            new_node->prev = list->tail;
            new_node->next = NULL;
            new_node->data = elem;
    
            if ( list->tail != NULL )
            {
                list->tail->next = new_node;
            }
            else
            {
                list->head = new_node;
            }
    
            list->tail = new_node;
        }
    
        return success;
    }
    
    void printList( list_t *list )
    {
        for ( dlist_t *current = list->head; current != NULL; current = current->next )
        {
            printf( "%d -> ", current->data );
        }
    
        puts( "null" );
    }
    
    
    void printReverseList( list_t *list )
    {
        for ( dlist_t *current = list->tail; current != NULL; current = current->prev )
        {
            printf( "%d -> ", current->data );
        }
    
        puts( "null" );
    }
    
    int main(void) 
    {
        list_t list = { .head = NULL, .tail = NULL };
    
        const int N = 10;
    
        for ( int i = 0; i < N; i++ )
        {
            if ( i % 2 == 0 ) pushFront( &list, N / 2 - i / 2 - 1 );
            else pushBack( &list, N / 2 + i / 2 );
        }
    
        printList( &list );
        printReverseList( &list );
    
        putchar( '\n' );
    
        for ( size_t i = 0; i < N; i++ )
        {
            if ( i % 2 == 0 ) delElement( &list, i / 2 );
            else delElement( &list, N - i / 2 - 1 );
    
            printList( &list );
            printReverseList( &list );
    
            putchar( '\n' );
        }       
    
        return 0;
    }
    

    The program output is

    0 -> 1 -> 2 -> 3 -> 4 -> 5 -> 6 -> 7 -> 8 -> 9 -> null
    9 -> 8 -> 7 -> 6 -> 5 -> 4 -> 3 -> 2 -> 1 -> 0 -> null
    
    1 -> 2 -> 3 -> 4 -> 5 -> 6 -> 7 -> 8 -> 9 -> null
    9 -> 8 -> 7 -> 6 -> 5 -> 4 -> 3 -> 2 -> 1 -> null
    
    1 -> 2 -> 3 -> 4 -> 5 -> 6 -> 7 -> 8 -> null
    8 -> 7 -> 6 -> 5 -> 4 -> 3 -> 2 -> 1 -> null
    
    2 -> 3 -> 4 -> 5 -> 6 -> 7 -> 8 -> null
    8 -> 7 -> 6 -> 5 -> 4 -> 3 -> 2 -> null
    
    2 -> 3 -> 4 -> 5 -> 6 -> 7 -> null
    7 -> 6 -> 5 -> 4 -> 3 -> 2 -> null
    
    3 -> 4 -> 5 -> 6 -> 7 -> null
    7 -> 6 -> 5 -> 4 -> 3 -> null
    
    3 -> 4 -> 5 -> 6 -> null
    6 -> 5 -> 4 -> 3 -> null
    
    4 -> 5 -> 6 -> null
    6 -> 5 -> 4 -> null
    
    4 -> 5 -> null
    5 -> 4 -> null
    
    5 -> null
    5 -> null
    
    null
    null
    

    Play with the program and playing investigate it.

    Do not forget to write yourself the function that frees all allocated nodes in the list.