C - 删除双向链表中的节点

时间:2014-03-10 03:55:17

标签: c linked-list

当我尝试使用deleteinst方法删除列表中的每个其他元素时,该方法对链表没有任何作用,并且没有错误。我真的不确定为什么它不起作用我已经看到了在不同程序中使用的相同deleteinst方法。也许它与指针有关。如果我运行deleteInst(track.prev,& head);如果没有while循环,列表仍保持不变。

如果您有任何想法或需要更多信息,请与我们联系。感谢您的时间。

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;
}

2 个答案:

答案 0 :(得分:2)

一个明显的明显问题:你真的想要这样做:

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

您释放该节点的那一刻,您将失去访问其成员的权利。首先保存,然后在删除后恢复:

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

我要检查的另一件事是列表结构是正确的,例如(仅在调试期间):

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);
}

使用checkList (head)调用该代码将验证您的链接列表是否符合所有有效性前提条件,因为您可能在其他地方有错误代码,例如在ReadNodeList()中创建列表时。< / p>


超越我建议在ReadNodeList()之后单独执行IDE或调试器中的代码,看看它实际上在做什么。并且,如果您没有IDE /调试器,请使用以下许多行来创建源代码:

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

然后检查调试语句的输出以分析程序中的流程。


现在,如果你真的要做那个调试练习,你可能会惊讶地发现deleteInst似乎永远不会被调用,因为i似乎总是设置为0 }。

这个小问题的错误在于:

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

    //delete every other node

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

是的,没错,您在循环中每次都设置i0 因此i % 2永远不会相等到1。您需要在循环之前初始化i (并且还会删除访问释放内存的未定义行为):

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;
}

答案 1 :(得分:0)

如果在列表初始化期间将尾部放在列表上,则双链表更容易使用。这消除了大多数令人头脑麻木的角落案件。

#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 );
}