Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/c/64.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
如何在C中仅释放链表中的单个节点?_C - Fatal编程技术网

如何在C中仅释放链表中的单个节点?

如何在C中仅释放链表中的单个节点?,c,C,如何仅释放链接列表中的单个节点?下面将释放整个链接列表,但我只想释放链接列表中的一个节点 //Here's my code for delete while(headPtr!=NULL) { temp = headPtr; headPtr = headPtr->next; if(strcmp(temp->fname, stdfname) ==0 && strcmp(temp->sname, stdsname) ==0

如何仅释放链接列表中的单个节点?下面将释放整个链接列表,但我只想释放链接列表中的一个节点

//Here's my code for delete

while(headPtr!=NULL)
{
    temp = headPtr;
    headPtr = headPtr->next;
    if(strcmp(temp->fname, stdfname) ==0 && 
       strcmp(temp->sname, stdsname) ==0  )
    {
        free(temp);
    }
}

除非要删除的节点是列表的头,否则列表的头永远不会更改。您应该在列表中向下移动临时指针。删除节点时还需要修复链接,请注意,有三种情况需要注意,其中第一个节点需要特殊处理。我将为您提供代码的框架,但由于我不知道您的列表是单链接还是双链接,因此我将把指针更新留给您

temp = headPtr;
prev = NULL;
while (temp != NULL)
{
     if (strcmp(temp->fname, stdfname) == 0)
         && strcmp(temp->sname, stdsname) == 0)
     {
         if (prev == NULL) { // head node
            ...
         }
         else if (temp->next == NULL) { // tail node
            ...
         }
         else {  // interior node
            ...
         }
         break;  // stop when done
     }
     prev = temp;
     temp = temp->next;
}

您首先需要知道上一个节点。因此,您需要迭代,直到找到要删除的节点。在这个过程中,您需要记住上一个节点。然后需要连接上一个和下一个节点,从而“断开”要删除的节点

currentNode = headNode;
previousNode = NULL;
while (currentNode != NULL) {
    if (currentNode != nodeToDelete) {
        // Not the node we want to delete yet,
        // go on to next node.
        previousNode = currentNode;
        currentNode = currentNode->next;
        continue;
    }

    // We've now hit the node to delete and know the
    // previous node. Fix the structure.
    if (previousNode) {
        previousNode->next = nodeToDelete->next;
    } else {
        // No previous node means it's the head node.
        headNode = nodeToDelete->next;
    }

    // The node is now delinked from list. Delete it.
    free(nodeToDelete);
    // Stop the loop.
    break;
}
就性能而言,这是相当糟糕的,这就是为什么会有双链接列表。在这里,整个操作如下所示:

if (nodeToDelete->previous) {
    nodeToDelete->previous->next = nodeToDelete->next;
}
if (nodeToDelete->next) {
    nodeToDelete->next->previous = nodeToDelete->previous;
}
if (nodeToDelete == headNode) {
    headNode = nodeToDelete->next;
}
free(nodeToDelete);
如您所见,这里不需要迭代,因为每个节点都知道其上一个和下一个节点


顺便说一句,要解决这些问题(它们非常基本),在一张纸上画一个简短的链表是有帮助的。绘制框,在每个框中写下成员名称(如
previous
next
),并从这些成员到相应的其他框绘制线条。然后考虑删除节点需要做什么。它确实有助于您理解这是如何工作的。

注意,您可以将它们缩进四个空格。编辑器工具栏中的“{}”按钮可执行此操作。这次是Radek帮你做的,但下次你问问题时自己试试看。单击编辑器工具栏中的橙色问号,了解有关格式设置的更多信息和提示。此外,当您选择此选项时,正文应该比您原来对问题有更好的描述。最后,这是吗?谢谢,这是小费。对不起,我刚刚接触这个网站,所以我还不熟悉这个网站的功能。不用担心。总有东西要学。浏览这个网站,你会发现各种有趣的花絮。谢谢,先生,这会很有帮助。谢谢,先生,这会很有帮助。我不同意你对单个链接列表的性能成本的看法。除了在堆栈上还需要一个指针之外,在这两种情况下执行的迭代次数相同@桂13:不,你不做同样的操作。当您拥有指向双链接列表元素的指针时,您可以立即删除该元素,而无需了解关于该列表的任何其他信息,因为该元素具有所有必要的信息。对于单链接列表,您需要遍历列表,直到到达要删除的元素,记住上一个元素,以便将上一个元素与下一个元素连接起来。双链接列表元素的
previous
指针完全消除了此列表遍历的需要,从而解决了
O(1)
@Gui13中的问题:我认为,如果您通过索引而不是节点访问列表,您是对的。在这种情况下,您需要遍历列表,直到到达元素,无论是单链还是双链列表。但是,对于单链表,您还需要跟踪上一个节点,这是双链表中不需要的操作,所以双链表在这里也便宜一点。这就是我的意思。您通常以存储方式使用列表,因此您不会访问节点本身,而是访问它们存储的数据。在这种情况下,删除一个节点将涉及两种情况下相同的行走-标识节点-删除节点(双链接列表或单链表)。不同之处在于,对于简单链表,您在tmp变量中保留上一个元素,而直接在双链表中访问它。