需要帮助理解C中的链表代码吗

需要帮助理解C中的链表代码吗,c,pointers,linked-list,double-pointer,C,Pointers,Linked List,Double Pointer,下面是我从中获得的代码 有人能帮助理解第6行和第8行吗?如果entry->val==to_remove,则对第6行求值,*pp成为删除后的下一个条目,那么第8行在这之后做什么?当前条目已被删除,如何在第8行中重新使用此条目 另外,我知道*pp是指针pp的值,&entry->next是指针pp的地址,我总是对何时使用*和何时使用&感到困惑。具体而言,第6行可以是: pp = &entry->next; 第8行是: *pp= entry->next; 若否,原因为何 &表

下面是我从中获得的代码

有人能帮助理解第6行和第8行吗?如果entry->val==to_remove,则对第6行求值,*pp成为删除后的下一个条目,那么第8行在这之后做什么?当前条目已被删除,如何在第8行中重新使用此条目

另外,我知道*pp是指针pp的值,&entry->next是指针pp的地址,我总是对何时使用*和何时使用&感到困惑。具体而言,第6行可以是:

pp = &entry->next; 
第8行是:

*pp= entry->next; 

若否,原因为何

&
表示返回某物的地址
*
表示访问指针指向的变量

因此,这些行:

pp = &entry->next;

*pp= entry->next;
它们是不同的

第一个指针设置为包含
entry->next
的地址,而第二个指针将
pp
指向的变量的值设置为等于
entry->next


entry->next
在被“删除”后可以被引用的原因是,当它从链表中删除时,它仍然存在于内存中,并且仍然可以被访问。

在这个示例代码中,pp存储了前一个链的“next”成员的地址,因此,如果当前链标记为要删除,则可以修改前一个链的“下一个”成员,以指向现在要删除的链的“下一个”。通过应用*运算符进行间接修改

第6行和第8行不能根据您的问题进行修改,因为这样代码将无法达到预期效果

  • 保留上一个(或头部)链的“下一个”成员的地址

  • 检查当前链条是否标记为拆卸

  • 如果是,则使用pp引用间接操纵前一个链的“下一个”成员以指向当前链的“下一个”,因此实际上链表将跳过当前链,同时保持其完整性

  • 更新:

    博客中的代码是不完整的,并且假设只有一个元素将被删除,并且不需要免费。如果要删除两个或多个连续元素,则序列中的第二个元素将不会被删除

    正确的代码是,它还假设不必释放节点:

    while (entry) {
        if (entry->val == to_remove)
            *pp = entry->next;           
        else
            pp = &entry->next;  
    
        entry = entry->next;
    } 
    
    如果必须释放节点:

    while (entry) 
    {
        if(entry->value == to_remove  )
        {
            *pp = entry->next;            
            free( entry ) ;
            entry = *pp ;
        }
        else
        {
            pp = &entry->next;               
            entry = entry->next;
        }
    } 
    


    编写整个结构确实有助于理解这一点

    struct Node
    {
        int val ;
        struct Node* next ; //hint, this has an address too.
    
    } ;
    
    诀窍就在声明中

    pp = &entry->next ;
    
    这看起来像是指向下一个节点,但实际上只是获取当前节点指针的地址。差别很大

    所以
    pp=&entry->next几乎等同于
    prev=entry
    从第一个示例中,唯一的区别是您指向当前结构节点的成员
    下一个
    的地址,而不是指向整个当前结构节点

    这里发生了什么:

    list_entry **pp = &head; /* pointer to a pointer */
    list_entry *entry = head;
    
    // we start with entry being head and pp being an address of head
    while (entry) {
    // while there is a list_entry which is not NULL...
        if (entry->val == to_remove)
            // if entry points to value that should be removed, 
            // then store the address of the next entry in whatever pp points to now
            // (which effectively means removing that entry)
            *pp = entry->next;            //6      
        // pp is now an address of the next entry
        pp = &entry->next;                //8   
        // move to the next entry to start the next iteration
        entry = entry->next;
    } 
    
    此代码的作用:它遍历列表并删除所有标记为已删除的条目

    它是如何做到的:

    • 最初,
      pp
      指向头部

    • 从头部开始,它就在列表上方

    • 每当当前条目指向的值标记为“已删除”时,
      pp
      将下一个列表条目的地址存储在当前列表条目的地址中。如果
      pp
      指向头部,则表示头部被丢弃,并开始指向下一个元素。如果<代码> pp指向列表中间的一个元素,则意味着该元素被删除(因为现在的前一个元素将指向删除后的元素)。

    • 完成后,它移动
      条目
      点以检查列表中的下一个值


    entry->next是下一个节点的地址吗?它是否与“当前节点的指针地址”相同?@ericyoung
    &entry->next
    是当前节点下一个指针的地址。我仍然不清楚:如果条目已被删除(并且可能被释放),为什么仍然可以使用当前节点的指针地址&entry->next?供您参考,还有另一个不同的实现:节点未释放意味着节点仍在链表中?你能解释一下为什么*pp=entry->next;和pp=&entry->next;在节点未释放解决方案中按原样使用,而不是按其他方式使用?我总是用错了。很抱歉,我仍然没有理解如果修改第6行和第8行,当前链将如何被跳过。你能详细解释一下吗?谢谢
    list_entry **pp = &head; /* pointer to a pointer */
    list_entry *entry = head;
    
    // we start with entry being head and pp being an address of head
    while (entry) {
    // while there is a list_entry which is not NULL...
        if (entry->val == to_remove)
            // if entry points to value that should be removed, 
            // then store the address of the next entry in whatever pp points to now
            // (which effectively means removing that entry)
            *pp = entry->next;            //6      
        // pp is now an address of the next entry
        pp = &entry->next;                //8   
        // move to the next entry to start the next iteration
        entry = entry->next;
    }