【问题标题】:Regarding deleting a node in a linked list关于删除链表中的节点
【发布时间】:2014-02-19 06:31:51
【问题描述】:

以下代码无法编译(代码是部分/修改过的代码,原因很明显)

    typedef struct l_list{
           int value;
           struct l_list *next;
    }list; // given

    void delete(list **head, int value){ //given
         ...         
         free(current); // segmentation fault
         ...
     }

    int main() /// given for testcase
    {  
               list listg[2];

              // initialized 2 struct  and link them with each other using next pointer one after another (think like arrayed linked list)

               delete(&listg, 3);
    } 

error: cannot convert list (*)[2] {aka l_list (*)[2]} to list** {aka l_list**} for argument 1 to void delete(list**, int)

问题1:编译帮助。请指教!

问题2:如果我们必须像上面那样实现delete,在函数中如何释放数组列表中的指针? (如何消除分段错误?)

【问题讨论】:

  • 对于 Q1:将 list listg[5]; 更改为 list *listg;
  • 指向某事物的指针的指针与指向某事物数组的指针相同。如果你稍微搜索一下,就会有很多重复。
  • @herohuyongtao 这是我编译的,我列出 *listg = malloc(sizeof(list) * 5);
  • 完全不相关,但你不应该有带前导下划线的全局名称,这些是 C 标准规范保留的。
  • 如果保证这样,free不是第一个的地址是不可能通过的。 free 可以单独是单独保护的情况。

标签: c linked-list


【解决方案1】:

考虑listg 是一个list 的数组
那么,&listg 是一个指向list 数组的指针

delete() 在第一个参数中期望 指向指向 list 的指针。所以,你有一个类型不匹配,因此编译器错误。这可以通过实际传递指向list 的指针的地址来纠正。

list listg[5] = {
    { 1, &listg[1] },
    { 2, &listg[2] },
    { 3, &listg[3] },
    { 4, &listg[4] },
    { 5, 0 } };
list *listp = listg;
delete(&listp, 3);

您不能在malloc()(或其兄弟之一)未返回的指针值上调用free()。这意味着您不能在自动或静态内存或动态分配中间的地址上调用free()。但是,您可以从列表中删除与3 关联的节点。

节点删除通常是通过将要删除的节点之前的节点的next 指针从其当前值移向要删除的节点之后的节点来实现的。您将需要代码(可能是某种循环)来识别要删除的节点以及完成此操作的前一个节点。如果您需要删除列表的第一个元素,可以通过将列表的头部更改为列表中的下一项来完成。

【讨论】:

  • 我知道如何实现删除。但是在正常删除中,您链接 previous->next = current->next; // 在哪里找到 current 节点,然后释放 current。但是在这里释放电流会导致分段错误
  • listg[5] = malloc(sizeof(list) * 5) // 仍然存在分段错误
  • 对不起,犯了这么多错误。列表 listg* = malloc(sizeof(list) * 5); // 释放时存在分段错误
  • 我对@9​​87654334@s限制的解释更明确了。
【解决方案2】:

这个:

list listg[5];

不是由next 指针串在一起的 5 个节点的列表。这是一个由五个列表组成的数组。 (并且“list”对于该结构来说是一个非常容易引起误解的名称——“node”会更好。)我不知道你期望delete 对它做什么(因为你没有向我们展示delete()) ,但该函数的签名与您给它的签名不匹配。

我不知道你所说的“数组列表”是什么意思。你的意思是一个列表数组吗? “数组列表中的指针”是否意味着指向此类数组元素的指针?以及释放这样一个指针是什么意思?

【讨论】:

  • 是的,节点数组,相互链接。当你删除这样一个数组链表中的一个节点时,你将如何释放那个未链接的节点?
  • 我必须实现删除,所以对链表使用标准删除。
  • @codeymodey 因为你有一个“节点”数组,你不能一个一个地释放它们。当数组超出范围时,它们将自动释放。您应该做的只是 unlink 列表中的节点。
  • @JoachimPileborg 对于第一季度:更改列表列表 [5];列出 *listg;对吗?
  • @codeymodey:很抱歉不得不告诉你这个,但你似乎对链表是什么有很深的误解。该数组中的节点通过它们的next 指针链接在一起;你可以把它们联系起来,但你没有。他们的next 指针未初始化并指向某个地方或其他地方,可能指向有效的内存地址(包含谁知道什么),也可能不是。短语“数组链表”没有意义。你必须回去查阅教科书。您还可以验证“免费”是否意味着您认为它的作用。
【解决方案3】:

修复样本(数组版本)

#include <stdio.h>
#include <stdlib.h>

typedef struct l_list{
    int value;
    struct l_list *next;
}list;

void delete(list **head, int value){
    list *current, *previous = NULL;

    for (current = *head; current != NULL; previous = current, current = current->next){
        if (current->value == value){
            break;
        }
    }

    if (current != NULL){
        if (previous == NULL){
            *head = current->next;
        } else{
            previous->next = current->next;
        }
    }
    return;
}

void print(list *head){
    while(head){
        printf("%d ", head->value);
        head = head->next;
    }
    printf("\n");
}

int main() { 
    list listg[5];
    listg[0].value = 1;
    listg[0].next = listg + 1;
    listg[1].value = 3;
    listg[1].next = NULL;

    list *head = &listg[0];
    print(head);
    delete(&head, 3);
    print(head);
    return 0;
}

【讨论】:

    猜你喜欢
    • 2020-09-10
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多