【问题标题】:free(temp) pointer frees head pointer in linked list-How to retain pointer to origin of listfree(temp) 指针释放链表中的头指针-如何保留指向链表原点的指针
【发布时间】:2012-03-21 05:34:26
【问题描述】:

我有一个问题,如果我想从链表中删除一个节点,我这样做: 假设:Head 指向第一个节点。

   deleteFirstNode(struct node * head)
  {
   struct node* temp=head;//this line
   temp->next=head->next->next;
   temp->data=head->next->data;
   free(head);
   head=temp;
  } 

1) 这会删除第一个节点吗?

2) 如果是这样,当我释放 head 时,它不会也释放临时指针吗?因为 temp 和 head 都指向这一行中的相同位置(参见代码中“这一行”中的注释)。 如果以上两者都为真,我将如何保留指向列表开头的指针。 ? 非常感谢你。

【问题讨论】:

    标签: c pointers malloc


    【解决方案1】:

    我会传递一个双指针并在这些行上做一些事情

    deleteFirstNode(struct node ** head) {
      struct node* temp= *head;
      *head = temp->next;
      free(temp);
    } 
    

    【讨论】:

    • 你好 Keety,我不确定指针指向,您能否在下面评估我的答案,谢谢您的支持。
    【解决方案2】:

    你想删除head指向的节点;你有几个问题:

    1) 你传入了head 指针的副本——该函数无法更改调用函数时使用的原始head 指针,所以函数的最后一行head=temp 什么也没做。当函数返回您指向列表中第一个节点的任何内容时,现在将指向已释放的内存。实际上,您已经丢失了列表。

    2) 当您抓取 head->next->data 时,您没有得到您想要的数据项,因为 head->next 已被覆盖。

    3) free(head) 也将释放 temp,因为它指向与 head 相同的东西。 temp 有点无意义。

    代码中的一些注释:

    deleteFirstNode(struct node * head)
    {
        struct node* temp=head;
    
        temp->next=head->next->next;  // note: this overwrites head->next
        temp->data=head->next->data;  //       so this gets what used to be
                                      //         head->next->next->data
    
        free(head);     // this frees `temp` (which is an alias for `head`)
                        //      - so whats the point of `temp`?
    
        head=temp;      // this is pointless in more ways than one
    } 
    

    所以这是deleteFirstNode() 的建议(未经测试)替代版本:

    deleteFirstNode(struct node ** head)
    {
        struct node* temp = *head;      // temp points to the node we want to free
        struct node* next = temp->next; // next points to what will be the new
                                        //  first node
    
        free(temp);
        *head=next;
    } 
    

    您必须通过传入指向头指针的指针来调用该函数:

    struct node* head_pointer;
    
    // ...
    
    deleteFirstNode(&head_pointer);
    

    要考虑的另一件事:

    • 如果您的头指针是NULLdeleteFirstNode() 将不起作用。你应该让它处理这种情况。

    【讨论】:

    • 这真的很有帮助,您能否在下面评估我的最终解决方案。谢谢你。它会起作用吗?
    【解决方案3】:

    这会删除第一个节点吗?

    是的。

    如果是这样,当我释放 head 时,它不会也释放临时指针吗?因为 temp 和 head 都指向该行中的同一位置(请参阅 在代码中的“这一行”中注释)。

    是的,它也会释放temp 指向的内存,因为headtemp 都指向同一个内存。执行该方法后,指针head 将指向无效的内存位置。

    【讨论】:

    • 你好 Asha,那我怎么还能保留对列表起始节点的引用。
    • @Ranjan:例如,您在删除它之前返回一个指向head->next的指针,它将指向删除后的“新头”。
    • @vsz,如果我有return语句,那它会如何执行free语句?
    • 指针头将指向一个无效的内存位置它指向一个有效的内存位置,只是它不属于你,因此你不能假设该地址的内容是有效的。
    • @Ranjan:你只会在最后回来,在你打电话给free()之后。您实际上必须返回您的 temp 变量,因为这是您的新负责人。您需要设置temp = head->next;,然后释放头部,然后返回温度。
    【解决方案4】:

    是的,您有两个指向同一个地址的指针。
    因此,通过在其中任何一个上调用 free() 来释放内存将释放指向的内存。

    编辑:
    为了理解链接列表,请始终将它们绘制在纸上。

    -------------      ------------       ----------- 
    |           |      |          |       |         |
    |   head    |----->|  first   |------>| second  | 
    |           |      |          |       |         |
    -------------      ------------       -----------    
    

    你需要做的步骤是:

    隔离first.
    使head 指向Second
    免费first

    temp = head->next; //temp now points to first
    head = temp->next; //head now points to second
    free(temp);
    

    【讨论】:

    • @Ranjan:顾名思义,deleteFirstNode() 的意图是删除第一个节点。即:head 指向的节点。理想情况下,要做到这一点,您必须使head 指向第一个节点之后的节点,然后删除第一个节点。想法是保持链接列表完整,并且必须首先隔离要删除的节点从列表中释放它。
    • 您能否在下面评估我的答案。感谢你的付出。它有帮助。
    【解决方案5】:

    根据您上面的建议,这是我删除第一个节点并返回指向头节点的指针(这将是列表中的第二个节点)的最终代码。

     struct node* freeFirstNode(struct node* head)
    {
     struct node* temp;
     temp=head//edited after expert's comment
     temp->next=head->next;//please confirm if this is valid and not Bad pointer.
     temp->data=head->data;
     free(head);//how will I fix this? it will free temp too.
     return(temp);
    } 
    

    【讨论】:

    • temp 没有特别指向任何东西(它从未被初始化),所以temp->nexttemp->data 是无效的表达式,如果你走到那一步,return(temp) 将返回垃圾。跨度>
    • @MichaelBurr,谢谢,你能修复我的最终代码吗,这就是我的想法。
    • 你试图做的太多了 - 只需设置temp = head->next。现在temp 指向“未来”的头节点,你可以free(head) 然后返回temp。函数的调用者需要注意他们用返回值替换列表头的想法。我不是这个特殊成语 (stackoverflow.com/a/257264/12711) 的忠实粉丝,但至少它可以工作。
    • @MichaelBurr,终于……!你给了我答案,我今天学到了一些东西,temp=head->next 是 temp=head 的修复。太好了,谢谢。
    • 不,在当前形式 (temp = head;) 中它不好。如果你想返回新的头(head->next),你应该使用 temp=head->next;但是,如果您尝试了解列表的内部工作原理会更好,例如,只需在 next 指向的位置绘制元素并绘制箭头。另一种方法是使用“空头列表”,其中头部本身不携带信息,第一个元素位于头部之后。以 Als 的答案为例。
    猜你喜欢
    • 1970-01-01
    • 2012-08-11
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-07-28
    相关资源
    最近更新 更多