C - deleting node in doubly linked list

醉酒当歌 提交于 2020-01-17 03:22:18

问题


When I try to delete every other element in the list using the deleteinst method the method does nothing to the linked list and there are no errors. I'm really not sure why it's not working I've seen the same deleteinst method used in a different program. Maybe it has something to do with the pointers. If I run deleteInst(track.prev, &head); without the while loop the list still remains unchanged.

Please let me know if you have any idea or need more info. Thank you for your time.

int main()
{
node *head;
node *track;
head = ReadNodeList(stdin);

track = LastNode(head); //goes to last node.

while(track != NULL){ 
    int i=0;
            //delete every other node
    if(i%2 == 1){
        deleteInst(track, &head);
    }
i++;
track = track->prev;
    }
}

void deleteInst(Instruction *victim, Instruction **head){

  if(*head == NULL || victim == NULL)
    return;

  if(*head == victim)
    *head = victim->next;

  if(victim->next != NULL)
    victim->next->prev = victim->prev;

  if(victim->prev != NULL)
    victim->prev->next = victim->next;     

  free(victim);
  return;
}

回答1:


One immediately obvious glaring problem: you really don't want to do this:

 deleteInst(track, &head);
 track = track->prev;

The instant you free that node, you lose the right to access its members. Save it first then recover after the delete:

 node *save_prev = track->prev;
 deleteInst(track, &head);
 track = save_prev;

Another thing I'd check is that the list structure is correct, with something like (only during debug):

static void checkList (node *curr) {
    int count = 0;

    // PreCon: head->prev must be null.

    if (curr != NULL) {
        if (curr->prev != NULL) {
            puts ("Linked list structure error A!");
            exit (1);
        }
    }

    // Check all nodes.

    while (curr != NULL) {
        // PreCon: curr->prev->next must be curr.

        if (curr->prev != NULL) {
            if (curr->prev->next != curr) {
                puts ("Linked list structure error B!");
                exit (1);
            }
        }

        // PreCon: curr->next->prev must be curr.

        if (curr->next != NULL) {
            if (curr->next->prev != curr) {
                puts ("Linked list structure error C!");
                exit (1);
            }
        }

        // Move to next and keep count.
        curr = curr->next;
        count++;
    }

    // All okay, output success message with size.

    printf ("Linked list structure okay, size = %d\n", count);
}

Calling that with checkList (head) will validate that your linked list meets all the validity preconditions, on the off-chance that you may have buggy code elsewhere, such as when creating the list in ReadNodeList().


Beyond that, I suggest single stepping the code in your IDE or debugger after ReadNodeList() to see what it's actually doing. And, if you don't have an IDE/debugger, pepper your source code with lots of lines like:

printf ("DEBUG %d: track = %p\n", __LINE__, track);

and then examine the output of the debug statements to analyse the flow through your program.


Now, if you were to actually do that debugging exercise, it may surprise you to find out that deleteInst never appears to be called, because i seems to be always set to 0.

And the fault of that little problem lies here:

while (track != NULL) { 
    int i = 0; // <<<<<<<

    //delete every other node

    if (i%2 == 1) {
        deleteInst (track, &head);
    }
    i++;
    track = track->prev;
}

Yes, that's right, you are setting i to 0 every single time through the loop, hence i % 2 will never be equal to 1. You need to initialise i before the loop (and with the undefined behaviour of accessing freed memory removed as well):

int i = 0;
while (track != NULL) { 
    node *save_prev = track->prev;

    //delete every other node

    if (i%2 == 1)
        deleteInst (track, &head);
    i++;
    track = save_prev;
}



回答2:


Doubly linked lists are a whole lot easier to work with if you put a tail on the list during the list initialization. This eliminates most of the mind-numbing corner cases.

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

typedef struct node
{
    struct node *next;
    struct node *prev;
    int data;
}
    node;

void ShowList( node *head );
void AppendNodeWithData( node *tail, int data );
void RemoveNode( node *item );

int main( void )
{
    int i;
    node *head, *tail, *item, *temp;

    // allocate and initialize the doubly linked list
    head = malloc( sizeof(node) );
    tail = malloc( sizeof(node) );
    if ( !head || !tail )
        exit( 1 );

    head->next = tail;
    head->prev = NULL;
    tail->next = NULL;
    tail->prev = head;

    // add some items to the list
    for ( i = 0; i < 20; i++ )
        AppendNodeWithData( tail, i );

    ShowList( head );

    // remove every other item
    for ( item = tail->prev; item != NULL && item->prev != NULL; item = temp )
    {
        temp = item->prev->prev;
        RemoveNode( item );
    }

    ShowList( head );
}

void ShowList( node *head )
{
    node *item;

    for ( item = head->next; item->next != NULL; item = item->next )
        printf( "  %d", item->data );
    printf( "\n" );
}

void AppendNodeWithData( node *tail, int data )
{
    node *item;

    if ( (item = malloc( sizeof(node) )) == NULL )
        exit( 1 );

    item->data = data;

    item->prev = tail->prev;
    item->next = tail;

    tail->prev->next = item;
    tail->prev = item;
}

void RemoveNode( node *item )
{
    item->next->prev = item->prev;
    item->prev->next = item->next;
    free( item );
}


来源:https://stackoverflow.com/questions/22291826/c-deleting-node-in-doubly-linked-list

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!