首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
社区首页 >问答首页 >实现链接列表

实现链接列表
EN

Code Review用户
提问于 2014-10-04 23:57:53
回答 1查看 219关注 0票数 3

我目前正在研究数据结构,所以在我检查实现数组列表之后,我想看看在C中实现链接列表是否有什么问题。

报头

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
#ifndef _LINKEDLIST_H
#define _LINKEDLIST_H

#include <stddef.h> /* size_t */
#include <stdbool.h> /* _Bool */
#define _LINKEDLIST_DEFAULT_SIZE (1)

typedef struct _linkedlist _LinkedList;
typedef const unsigned int Index;

#define LinkedList _LinkedList *

LinkedList LinkedList_create();

int LinkedList_add(LinkedList, void *);
int LinkedList_get_val_index(LinkedList, void *);
int LinkedList_get_list_index(LinkedList, const LinkedList *);
int LinkedList_remove(LinkedList, const _Bool, const _Bool);

void LinkedList_set_data(LinkedList, void **, const _Bool, const size_t max);
void LinkedList_clear(LinkedList, const _Bool);
void LinkedList_destroy(LinkedList *, const _Bool);

void *LinkedList_get_value(const LinkedList);

LinkedList LinkedList_get(LinkedList, Index);

LinkedList *LinkedList_get_next(LinkedList);
LinkedList *LinkedList_get_previous(LinkedList);
LinkedList *LinkedList_get_pointer(LinkedList *, Index);

inline size_t LinkedList_get_size_of(const LinkedList);
inline size_t LinkedList_get_size(const LinkedList);

#endif /* _LINKEDLIST_H */

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
#include <stdlib.h>
#include "LinkedList.h"

#define VALID_LINKEDLIST_CODE (245)
#define _LinkedList_check(l) \
    if ((l) == NULL || (l)->_Valid != VALID_LINKEDLIST_CODE) \
        abort();

struct _linkedlist {
    size_t depth;
    int _Valid;
    void * value;
    struct _linkedlist *next;
    struct _linkedlist *previous;
};

struct _linkedlist *LinkedList_create(void * initial_value)
{ /* Allocate Memory */
    struct _linkedlist *list = malloc(sizeof(struct _linkedlist));

    if(list == NULL)
        return NULL;

    list->depth = 1;
    list->next = NULL;
    list->previous = NULL;
    list->value = initial_value;
    list->_Valid = VALID_LINKEDLIST_CODE;
    return list;
}

void LinkedList_set_data(struct _linkedlist * list, void ** data, const _Bool freeval, const size_t max)
{ /* Sets the internal array of the arraylist */
    _LinkedList_check(list);
    int length;
    for(length = 0; data[length]; ++length);
    if (length < max || max == 0)
        abort();
    LinkedList_clear(list, freeval);
    list->value = data[0];
    for(unsigned int i = 1; i < max; ++i)
        LinkedList_add(list, data[i]);
    list->depth = max;
}

int LinkedList_add(struct _linkedlist *list, void *elem)
{ /* Adds one linked list to the chain with elem as value */
    _LinkedList_check(list);
    ++list->depth;
    struct _linkedlist ** l;
    for(l = &list->next; ( *l != NULL ); l = &(*l)->next)
        ++(*l)->depth;
    (*l) = LinkedList_create(elem);
    (*l)->previous = *l;
    return ((*l)->next == NULL);
}

struct _linkedlist *LinkedList_get(struct _linkedlist *list, const unsigned int index)
{ /* Gets the index'th linked list in the chain */
    _LinkedList_check(list);
    if (index >= list->depth)
        return NULL;
    for(unsigned int i = 0; i < index; list = list->next, i++);
    return list;
}

struct _linkedlist **LinkedList_get_pointer(struct _linkedlist ** list, const unsigned int index)
{ /* Gets the index'th linked list in the chain as a pointer */
    _LinkedList_check(*list);
    if (index >= (*list)->depth)
        return NULL;
    for(unsigned int i = 0; i < index; list = &(*list)->next);
    return list;
}

inline size_t LinkedList_get_size_of(const struct _linkedlist *list)
{ /* Returns the size of the chain of lists in memory */
    _LinkedList_check(list);
    return (sizeof(struct _linkedlist) * list->depth);
}

inline size_t LinkedList_get_size(const struct _linkedlist *list)
{ /* Returns the number of elements in the arraylist */
    _LinkedList_check(list);
    return list->depth;
}

int LinkedList_remove(struct _linkedlist * list, const _Bool index, const _Bool freeval)
{ /* Removes one element at a chain index */
    _LinkedList_check(list);
    if (index >= list->depth)
        return 2;

    LinkedList_clear(LinkedList_get(list, index), freeval);
    --list->depth;
    return 0;
}

void LinkedList_clear(struct _linkedlist * list, const _Bool freeval)
{ /* Clears the list chain */
    _LinkedList_check(list);
    struct _linkedlist * l, * n;
    for( l = list->next; l; l = n) {
        if (freeval)
            free(l->value);
        n = l->next;
        free(l);
    }
    list->next = NULL;
}

void LinkedList_destroy(struct _linkedlist ** list, const _Bool freeval)
{ /* De-allocates the list and its chains from memory
    No usage of list is allowed after this function call */
    _LinkedList_check(*list);
    LinkedList_clear(*list, freeval);
    free(*list);
    *list = NULL;
}

int LinkedList_get_val_index(struct _linkedlist *list, void *elem)
{ /* Looks for elem in list and returns the index or -1 if not found */
    _LinkedList_check(list);
    for(unsigned int i = 0; i < list->depth; ++i)
        if (elem == (LinkedList_get(list, i)->value))
            return i;
    return -1;
}

int LinkedList_get_list_index(struct _linkedlist *list, const struct _linkedlist ** elem)
{
    _LinkedList_check(list);
    for(unsigned int i = 0; i < list->depth; ++i)
        if (*elem == LinkedList_get(list, i))
            return i;
    return -1;
}

void *LinkedList_get_value(const struct _linkedlist *list)
{ /* Return the list's essence, the value */
    return list->value;
}

struct _linkedlist **LinkedList_get_next(struct _linkedlist *list)
{ /* Return the next list in the chain */
    return &list->next;
}

struct _linkedlist **LinkedList_get_previous(struct _linkedlist *list)
{ /* Return the previous line in the chain */
    return &list->previous;
}

在与val差制检查之后,我发现我没有内存泄漏,没有读/写错误,也没有函数或逻辑错误(测试后)。

我想知道代码中是否存在可用性或性能问题。

EN

回答 1

Code Review用户

回答已采纳

发布于 2014-10-05 11:21:38

您的列表有点不寻常,因为它在每个列表节点中都包含一个depth字段和一个有效性检查字段。我从来没有见过这个,并认为深度,特别是一个错误。您的函数必须遍历整个列表,随时调整每个项的depth字段。同样,当删除项目时,您必须遍历其余的项。这意味着列表在扩展时会变慢。这不是一个好的设计。

我认为最好从每个节点中删除depth,并可能使列表头成为一个不同的结构,其中包含指向列表末尾的指针。

其他一些意见:

  • 您的linkedlist_check宏应该大写,并且应该使用do {...} while(0),而不是以分号结尾。
  • 避免使用前导下划线。它的用途是保留的。它不会给你的代码增加任何东西。
  • 通常认为最好将单行条件语句或循环括在大括号中:如果(length < max < max 000-max == 0) { abort();}在这方面没有一致意见,但它确实有助于防止如果省略大括号可能发生的一类错误。另外,如果这样编码,空循环通常会被认为更好: for(length = 0;data长度;++length) { /* nothing */ }
  • LinkedList_set_data中,第一个for -循环似乎在数据数组中搜索空指针。如果找不到,它将不确定地重复(进入未定义的内存)。我不知道为什么这个功能会有必要。
  • LinkedList_add不测试对LinkedList_create的调用是否失败。函数还使用双指针编写,这是丑陋和不必要的。
  • 我不认为LinkedList_getLinkedList_get_pointer都有意义。另外,后者不增加i
  • 我认为LinkedList_get_size_of没有用。调用方为什么要知道非连续(不透明)节点占用的内存量?返回节点数可能有更多的用途(LinkedList_get_size)。
  • LinkedList_remove应该只删除一个节点,但在该节点之后“清除”列表。它似乎改变了列表头的深度计数器,而没有更改其他节点的深度计数器。

..。我没有走得更远。

票数 4
EN
页面原文内容由Code Review提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://codereview.stackexchange.com/questions/64772

复制
相关文章
[快学Python3]INI文件读写
概述 ini是我们常见到的配置文件格式之一。 ini是微软Windows操作系统中的文件扩展名(也常用在其他系统)。 ini“初始化(Initial)”的缩写。正如该术语所表示的,INI文件被用来对操作系统或特定程序初始化或进行参数设置。 其基本组成形式如下: [section_1] key1 = value1 key2 = value2 key3 = value3 key4 = value4 [section_2] key1 = value1 key2 = value2 key3 = value3 ke
苦叶子
2018/04/09
2.3K0
[快学Python3]INI文件读写
概述 ini是我们常见到的配置文件格式之一。 ini是微软Windows操作系统中的文件扩展名(也常用在其他系统)。 ini“初始化(Initial)”的缩写。正如该术语所表示的,INI文件被用来对操作系统或特定程序初始化或进行参数设置。 其基本组成形式如下: [section_1] key1 = value1 key2 = value2 key3 = value3 key4 = value4 [section_2] key1 = value1 key2 = value2 key3 = value3 ke
苦叶子
2018/04/09
1.3K0
[快学Python3]INI文件读写
概述 ini是我们常见到的配置文件格式之一。 ini是微软Windows操作系统中的文件扩展名(也常用在其他系统)。 ini“初始化(Initial)”的缩写。正如该术语所表示的,INI文件被用来对操作系统或特定程序初始化或进行参数设置。 其基本组成形式如下: [section_1] key1 = value1 key2 = value2 key3 = value3 key4 = value4 [section_2] key1 = value1 key2 = value2 key3 = value3 ke
苦叶子
2018/04/09
1.4K0
ini配置文件以及利用python管理ini文件
在python里面有一个叫做configparser的module,可以用来操作ini文件,从而方便进行配置文件的管理工作.
qsjs
2021/03/04
1.7K0
python 读写ini文件
如果某个section已经存在了,在写入的时候不能够再使用config.add_section(‘Title1’)这个函数了,这样会报错,所以,我们需要进行判断,先判断Title1是否存在,然后再进行操作 例子:
matinal
2023/10/14
2240
ini 文件操作指南
  ini 类型文件通常作为程序的初始化文件。不同于我们常见的配置文件通篇 key-value 的键值对形式,ini 文件在键值对的基础之上还有分类节点,比如我们常见的 Mysql 数据库的初始化配置文件 my.cnf或my.ini,其内容格式通常是如下这样的:
用户1615728
2019/10/19
2K0
ini 文件操作指南
#PY小贴士# 我的文件为何无法写入
1. 搞错了当前目录,自以为是在某个目录下,其实不是。此情况易发于使用 IDE 的时候,因为 IDE 的执行目录并不一定是当前 py 文件所在目录。可以通过 print(os.getcwd()) 来查看当前路径。
Crossin先生
2019/12/18
1.6K0
执行py文件需要可执行权限吗?
这个问题描述起来有点违反直觉,要执行一个文件难道不应该需要可执行权限吗?让我们先来看一个例子:
DechinPhy
2021/05/21
1.7K0
pytest测试框架系列(4)-pytest.ini和conftest.py文件
pytest测试框架的比较重要的两个文件就不得不说下pytes.ini和conftest.py文件。
搁浅同学
2022/07/21
9820
pytest测试框架系列(4)-pytest.ini和conftest.py文件
Pytest(十一) pytest ini文件
我们在执行的时候,可以不增加这些参数,addopts就是我们运行的时候所最近的命令
雷子
2022/04/06
1.5K0
Pytest(十一) pytest ini文件
【vbs】vbs写ini文件
这两天在折腾给一个项目打安装包,第一次接触软件打包,用的Advanced Installer(以下简称AI),应该说如果安装过程没有特殊动作(常规动作指释放文件、写注册表、建快捷方式等)的话,倒挺傻瓜的,按照向导和界面操作就能打好一个包。但我的安装动作包括:
AhDung
2018/09/13
1.8K0
C# 读写Ini文件
ini文件在Win95以前比较盛行,之后由于出册表等技术的出现,ini技术主键退居二线,不过对于一些小项目,读写ini文件还是很适用的。
用户9127601
2021/11/01
1.7K0
宝塔面板php.ini配置文件在哪里?php.ini文件路径
php.ini配置文件是站长经常会用到的,那么宝塔面板的php.ini配置文件在哪里?分享宝塔php.ini文件路径:
Z4
2020/04/21
4K0
文件上传之.user.ini文件漏洞利用
.user.ini。它比.htaccess用的更广,不管是nginx/apache/IIS,只要是以fastcgi运行的php都可以用这个方法。我的nginx服务器全部是fpm/fastcgi,我的IIS php5.3以上的全部用的fastcgi/cgi,我win下的apache上也用的fcgi,可谓很广,不像.htaccess有局限性。
网e渗透安全部
2023/02/25
1.8K0
文件上传之.user.ini文件漏洞利用
Pycharm 运行py文件[通俗易懂]
2. 打开pycharm,如果已经有文件了,就点击File->close project,回到主界面
全栈程序员站长
2022/09/27
4.2K0
Pycharm 运行py文件[通俗易懂]
怎么新建pytest的ini文件_pytest.ini配置
pytest配置文件可以改变pytest的运行方式,它是一个固定的文件pytest.ini文件,读取配置信息,按指定的方式去运行
全栈程序员站长
2022/09/16
1.3K0
.user.ini文件的坑
最后查到问题出在php的配置上,主要是因为配置了open_basedir项目,但是找遍了php.ini和php-fpm.conf也没有找到哪里设置了这个配置项,最后在看一个回答的时候,发现项目根目录可以放一个.user.ini文件来设置允许php访问的目录。
ianzhi
2019/07/31
1.5K0
py文件的运行
1,运行第一段python代码。 在d盘下创建一个t1.py文件内容是: 打开windows命令行输入cmd,确定后 写入代码python d:t1.py 
全栈程序员站长
2022/07/21
2.3K0
py文件的运行
每日一库:ini文件读取
在 Go 语言开发中,读取和解析配置文件是一个常见的任务。INI 格式是一种简单而常见的配置文件格式,它由多个部分组成,每个部分包含键值对,用于配置应用程序的各种属性。本文将介绍如何在 Go 语言中使用 INI 格式的配置文件。
孟斯特
2023/10/19
4180
每日一库:ini文件读取
QSettings读写ini配置文件
Qt中使用QSettings类读取ini后缀的配置文件非常简单,使用该类也可以很简单的操作Windows注册表。以前也使用过MFC中的WritePrivateProfileString()和GetPrivateProfileString()这两个API操作ini配置文件。
ccf19881030
2020/03/02
8210

相似问题

c++:类X没有名为Y的成员

20

C++:类"X“没有名为"Y”的成员

15

python如果文件名为"blah“和"blah”

20

Ember.JS:没有名为blah的路由

11

C++类错误“‘const class Number”没有名为“intValue”的成员

123
添加站长 进交流群

领取专属 10元无门槛券

AI混元助手 在线答疑

扫码加入开发者社群
关注 腾讯云开发者公众号

洞察 腾讯核心技术

剖析业界实践案例

扫码关注腾讯云开发者公众号
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档
查看详情【社区公告】 技术创作特训营有奖征文