C-删除双向链表中的节点 [英] C - deleting node in doubly linked list

查看:52
本文介绍了C-删除双向链表中的节点的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

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

推荐答案

一个显而易见的明显问题:您真的想要这样做:

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

使用 checkList(头)进行调用将验证您的链表是否满足所有有效性先决条件,而在其他地方(例如在 ReadNodeList().

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().

除了 ,我建议在 ReadNodeList()之后单步执行IDE或调试器中的代码,以查看其实际作用.而且,如果您没有IDE/调试器,请在源代码中添加很多代码,例如:

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.

现在,如果您实际上要进行该调试练习,可能会惊讶地发现 deleteInst 似乎从未被调用,因为 i 似乎总是设置为 0 .

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

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

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

这篇关于C-删除双向链表中的节点的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆