Thread: Cleaning up the logic on linked list deletion

  1. #1
    Registered User
    Join Date
    Jun 2009
    Posts
    486

    Cleaning up the logic on linked list deletion

    I have a doubly linked list from which I need to occasionally delete elements (any elements that have a type value different from 0). The function I have seems to work, but looking at it, I think I could probably make the logic cleaner. If anyone has some suggestions for cutting down on redundant code to make this more readable, I would appreciate it.

    The structs in questions are declared here, with irrelevent variabled omitted:

    Code:
    struct Event
    {
        //...
        int type;
        //...
        struct Event *next;
        struct Event *prev;
    };
    typedef struct Event event;
    Code:
    event *delete_bad_events(event *head)
    {
        event *newhead;
        event *current;
        event *tempnext;
        event *tempprev;
        event *temp;
        current = head;
        newhead = head;
        while (current)
        {
            if (current->type != 0)
            {
               tempnext = current->next;
               tempprev = current->prev;
               temp = current;
               current = current->next;
               free_single_event(temp);
               if (tempprev && tempnext)
               {
                   tempprev->next = tempnext;
                   tempnext->prev = tempprev;
               }
               else if (!tempprev && tempnext) //head of the list
               {
                   newhead = tempnext;
                   tempnext->prev = NULL;
               }
               else if (tempprev && !tempnext) //end of the list
               {
                   tempprev->next = NULL;
               }
               else if (!tempprev && !tempnext) //singleton list, odd case
               {
                   newhead = NULL;
               }
            }
            else
            {
                current = current->next;
            }
        }
        return newhead;
    }
    C is fun

  2. #2
    C++ Witch laserlight's Avatar
    Join Date
    Oct 2003
    Location
    Singapore
    Posts
    28,413
    Why not create a "new" list that does not have any such events? While doing this, you can call free_single_event on those elements found to be bad events.

    EDIT:
    Oh, but since this is doubly linked, perhaps the idea isn't that great since you need to link to the previous too, and if there are few bad events, the cost could be relatively high.
    Quote Originally Posted by Bjarne Stroustrup (2000-10-14)
    I get maybe two dozen requests for help with some sort of programming or design problem every day. Most have more sense than to send me hundreds of lines of code. If they do, I ask them to find the smallest example that exhibits the problem and send me that. Mostly, they then find the error themselves. "Finding the smallest program that demonstrates the error" is a powerful debugging tool.
    Look up a C++ Reference and learn How To Ask Questions The Smart Way

  3. #3
    Registered User
    Join Date
    Jun 2009
    Posts
    486
    Yea, you can certainly make that work, but my pseudocode attempt on paper didn't look much cleaner. The special case of finding the new head when the head is a bad event makes it a bit ugly.

    I was mostly just wondering if there was some glaring redundancy in my temporary variables, or a way to compress a few of those if cases into one. Seems like there should be, but maybe it's just an ugly problem.
    C is fun

  4. #4
    Registered User
    Join Date
    Nov 2010
    Location
    Long Beach, CA
    Posts
    5,909
    It wouldn't clean up the logic much, but you could make a few small changes:

    1. Immediately in the while loop (before you check != 0), declare temp and set it to current, then increment current = current->next
    2. Drop tempprev and tempnext, use temp->prev and temp->next instead (so, tempprev->next becomes temp->prev->next, etc)
    3. Move the free single event to after the if/else blocks that do the pointer manipulation for node removal
    4. Drop the final else that increments current when event type is 0.


    This produces the following, which I think is equivalent and slightly cleaner and shorter. But it's untested, so you'll have to try it out.
    Code:
    event *delete_bad_events(event *head)
    {
        event *newhead;
        event *current;
        current = head;
        newhead = head;
        while (current)
        {
            event *temp = current;
            current = current->next;
            if (temp->type != 0)
            {
               if (temp->prev && temp->next)
               {
                   temp->prev->next = temp->next;
                   temp->next->prev = temp->prev;
               }
               else if (!temp->prev && temp->next) //head of the list
               {
                   newhead = temp->next;
                   temp->next->prev = NULL;
               }
               else if (temp->prev && temp->next) //end of the list
               {
                   temp->prev->next = NULL;
               }
               else if (!temp->prev && !temp->next) //singleton list, odd case
               {
                   newhead = NULL;
               }
               free_single_event(temp);
            }
        }
        return newhead;
    }

  5. #5
    Registered User
    Join Date
    Jun 2009
    Posts
    486
    alright, thanks for the suggestions - your suggested changes work as described. It always just bugs me to see code with lots of corner cases, but I guess I'll have to live with this one
    C is fun

  6. #6
    Registered User
    Join Date
    Jun 2009
    Posts
    486
    Actually, a potential problem with freeing after the if block:

    Code:
    if (temp->prev && temp->next)
               {
                   temp->prev->next = temp->next;
                   temp->next->prev = temp->prev;
               }
               else if (!temp->prev && temp->next) //head of the list
               {
                   newhead = temp->next;
                   temp->next->prev = NULL;
               }
               else if (temp->prev && temp->next) //end of the list
               {
                   temp->prev->next = NULL;
               }
               else if (!temp->prev && !temp->next) //singleton list, odd case
               {
                   newhead = NULL;
               }
               free_single_event(temp);
    that line just sets temp = NULL, which I then call free on, which does nothing. So isn't that a memory leak if I don't free before the block?
    C is fun

  7. #7
    Registered User
    Join Date
    Nov 2010
    Location
    Long Beach, CA
    Posts
    5,909
    Quote Originally Posted by KBriggs View Post
    Actually, a potential problem with freeing after the if block:
    Code:
    ...
                   temp->next->prev = NULL;
    ...
    that line just sets temp = NULL, which I then call free on, which does nothing. So isn't that a memory leak if I don't free before the block?
    No it doesn't. It set's the prev member of the node after temp, to point to NULL. You can verify by printf'ing the value of temp right after:
    Code:
    printf("After temp->next->prev = NULL, temp points to %p\n", (void *) temp);
    EDIT: Or better yet, just use a debugger and put a breakpoint on that line. Step through it and check the value of temp.

  8. #8
    Registered User
    Join Date
    Jun 2009
    Posts
    486
    Interesting, I had misunderstood something basic about pointer assignment apparently. Thanks for the help!
    C is fun

Popular pages Recent additions subscribe to a feed

Similar Threads

  1. A question about node deletion in a linked list
    By nonlinearly in forum C Programming
    Replies: 2
    Last Post: 11-16-2011, 03:19 AM
  2. Mass deletion from linked list
    By budala in forum C Programming
    Replies: 3
    Last Post: 04-27-2010, 05:43 AM
  3. Linked list / Octree deletion
    By DrSnuggles in forum C++ Programming
    Replies: 2
    Last Post: 08-03-2008, 05:57 AM
  4. Deletion in linked list
    By jeya in forum C Programming
    Replies: 1
    Last Post: 07-24-2008, 12:36 AM
  5. Linked List Deletion
    By MasterAchilles in forum C Programming
    Replies: 1
    Last Post: 04-20-2008, 05:27 AM