【问题标题】:Singly Linked List Implementation in C using 3 different typedefs使用 3 种不同 typedef 在 C 中实现单链表
【发布时间】:2021-06-18 14:22:12
【问题描述】:

所以,我的任务是在C 中编写Singly Linked List 的完整实现。

我在实现stackdynamic vector 之前写过,但是这一次,由于使用了3​​ 个不同的typedef,链表让我有点困惑。

我很高兴收到您对我的代码的评论和提示。

我会像往常一样制作一个测试文件,但由于void * 的所有转换,我很难编写一个。

我不会添加所有 14 个函数,我只会添加我最不确定的函数。

所以我们必须遵循以下typedefs 和给定的prototypes。所以它们都不能改变。

我还必须添加一个 "dummy node" 作为最后一个节点,这意味着总会有一个 "dummy node" 表明之前的那个它,是列表中“真实”的最后一个节点。这是说明的一部分。

typedef struct slist slist_ty;

typedef struct slist_node slist_node_ty;

typedef slist_node_ty *slist_iter_ty;

这是我对结构的实现: 他们要求我们在理论上允许节点中的任何类型的数据,这就是我写void *的原因。

struct slist
{
    slist_iter_ty head;
    slist_iter_ty end;
};

struct slist_node
{
    void *data;
    slist_iter_ty next;
};

这些是功能:

/* Creates an empty single-linked list and returns pointer to the head */
/* returns NULL on failure*/
/* Complexity: O(1) */
slist_ty *SlistCreate(void)
{
    slist_ty *new_list = (slist_ty *)malloc(sizeof(slist_ty));
    if (NULL == new_list)
    {
        fprintf(stderr, "Failed to allocate memory\n");
        return(NULL);
    }
    
    new_list->head = NULL;
    /* create a dummy node that will represent the end of the list */
    new_list->end = (slist_node *)malloc(sizeof(slist_node));
    if (NULL == new_list->end)
    {
        fprintf(stderr, "Failed to allocate memory\n");
        free(new_list);
        return(NULL);
    }
    
    new_list->end->data = NULL;
    new_list->end->next = NULL;
    
    return(new_list->head);
}

/* Deletes entire List */
/* Complexity: O(n) */
void SlistDestroy(slist_ty *slist)
{
    slist_iter_ty temp = NULL;
    
    assert(slist);
    
    while(NULL != slist->head)
    {
        tmp = slist->head;
        slist->head = temp;
        free(temp);
    }
    
    free(slist->end);
    slist->end = NULL;
    
    free(slist);
    slist = NULL;
}

/* Insters the element after the iterator, returns iterator to the new node */
/* TODO Undefined behaviour if iter is slist_END */
/* Complexity: O(1) */
slist_iter_ty SlistInsert(slist_iter_ty iter, void *data)
{
    slist_iter_ty new_node = NULL;
    
    assert(iter);
    assert(iter->next);
    assert(data);
    
    new_node->data = data;
    new_node->next = iter->next;
    iter->next = new_node;
    
    return(new_node);
}
    
    
    /* Returns iterator to end of the list */
    /* Complexity: O(1) */
    slist_iter_ty SlistIteratorEnd(const slist_ty *slist)
    {
        slist_iter_ty iterator = slist->head;
        
        assert (slist);
        
        if (NULL == slist->head)
        {
            return(NULL);
        }
        
        while (NULL != iterator->next->data)
        {
            iterator = iterator->next;
        }
        
        return(iterator);
    }

我请求获得反馈的问题是:

我应该 free 制作任何新的 slist_iter_ty 吗? 例如,我在最后一个函数中做了一个slist_iter_ty 类型的iterator,以帮助我遍历列表。但是我无法释放迭代器,因为我需要将它作为返回值返回。

我还在SlistInsert函数中做了一个new_node

它会作为SlistDestroy 函数的一部分被释放吗?

谢谢。

【问题讨论】:

    标签: c pointers data-structures linked-list singly-linked-list


    【解决方案1】:

    slist - 是列表。当你创建这个列表时你使用 malloc 所以当你想销毁它时你需要释放这个列表。

    还 - 您每次使用插入时都使用了 malloc。所以当你想销毁列表时,你需要从所有节点中清空它 - 所以你需要一个节点一个节点地释放它

    我可以看到您在 slist 插入中没有使用 malloc - 如何在不使用 malloc 的情况下保留数据?

    在销毁函数中

     while(NULL != slist->head)
    {
        tmp = slist->head;
        slist->head = temp;
        free(temp);
    }
    

    我想你的意思是:

    while(NULL != slist->head)
    {
        tmp = slist->head;
        slist->head = slist->head->next;
        free(tmp);
    }
    

    在插入函数中

    slist_iter_ty new_node = NULL;
    

    你应该写什么:

    new_node = (slist_iter_ty) malloc(sizeof(slist_node));
    

    在 slist 结束函数中

    slist_iter_ty SlistIteratorEnd(const slist_ty *slist)
    

    你可以直接返回(在你断言之后:)):

    return (slist->end);
    

    (否则它不会是 O(1) 它将是 O(n))

    【讨论】:

    • 我知道我需要逐个节点地free,您可以查看我对SlistDestory 的实现。我的问题是实施是否正确?哦,您对Insert 的看法是正确的。所以我认为正确的做法是在函数开头添加slist_iter_ty new_node = (slist_node *)malloc(sizeof(slist_node));而不是new_node = NULL
    • 感谢您的帮助。 slist->head = slist->head->next; 呢?你写了这个,但是这样一来,我什至不需要任何temp 变量?我的意思是我可以写这行。
    • 不,如果您释放它,您将无法访问head->next。如果你到达head->next,你将无法释放它
    • 哦,明白了!无法真正得到的一件事是为什么我们只需要释放node 本身,而不需要释放位于其中的数据?我的意思是,数据也存储在分配的内存中,那么为什么我们不会在每次迭代中释放它呢?
    • 自己尝试一下 :) 如果它不会顺利发布新问题的新问题 :) 祝你好运
    猜你喜欢
    • 2012-09-17
    • 2013-12-03
    • 1970-01-01
    • 2019-09-02
    • 1970-01-01
    • 2023-03-02
    • 2015-08-18
    • 1970-01-01
    • 2012-05-24
    相关资源
    最近更新 更多