繁体   English   中英

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

[英]C - deleting node in doubly 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;
}

一个显而易见突出的问题:你真的希望这样做:

 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()创建列表时。


除此之外我建议在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;
}

是的,没错,你通过循环每次都将i设置为0 因此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;
}

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

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

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM