# elist **Repository Path**: Createtree/elist ## Basic Information - **Project Name**: elist - **Description**: list lib - **Primary Language**: C - **License**: Apache-2.0 - **Default Branch**: master - **Homepage**: None - **GVP Project**: No ## Statistics - **Stars**: 0 - **Forks**: 0 - **Created**: 2023-03-21 - **Last Updated**: 2024-01-27 ## Categories & Tags **Categories**: Uncategorized **Tags**: None ## README # elist > a list lib for C ## How to use > 这个 `list` 库提供了一些常见的链表操作,包括创建链表、添加节点、删除节点、读写节点数据等等。使用这个库非常简单,只需要按照以下步骤进行操作即可。 ### 引入头文件 将 `list.h` 头文件引入你的代码中,如下所示: ```C #include "list.h" ``` ### 创建链表 使用 `listCreate()` 函数创建一个链表对象,该函数返回指向链表的指针。例如: ```C list_t *myList = listCreate(); ``` 使用 `listStaticCreate(); ` 可以静态创建,例如: ```C static list_t mylist; // 全局定义或在使用时不会释放的地方定义 listStaticCreate(&mylist); // 静态创建链表 ``` > 该方式创建的好处是无需动态内存分配 ### 添加节点 使用 `listPush()` / `listPushh()` / `listPusht()` 函数将一个新的节点添加到链表中。 Example1: ```C int *data = malloc(sizeof(int)); *data = 123; listPush(myList, data, 0); ``` > 这个函数接受三个参数:链表对象、新节点的数据、新节点应该插入的位置。在这个例子中,我们将一个整数的指针添加到链表的开头。 > > tips: 在下次读取data的数据时时应当确保data为有效数据或地址而不是局部变量或已释放内存地址。 Example2: ```C listPusht(myList, data); ``` > 将自动创建node来记录数据并将node插入list的尾部。 > > tips: 将 `listPusht()` 换为 `listPushh()` 可以从链表头部插入。 ### 遍历链表 使用 `listIteratorh()` 或 `listIteratort()` 宏来遍历链表。例如: ```C unsigned int i; listIteratorh(myList, i) { printf("data:%d\n", *(int *)listRead(myList, i)); } ``` > 从引索0处开始遍历链表,打印每个节点的数据。 > > 警告: 请不要在该宏中删除节点,这会导致链表长度发生变化。如果需要删除可以使用 `listIteratort()` 在遍历时读出数据并删除节点可以使用 `listPoph()` 或 `listPopt()` ```C int *pdata; while(pdata = listPoph(myList)) { printf("data:%d\n", *pdata) free(pdata); } ``` > 从链表头部弹出数据,并打印出来。需要注意回收data的内存,因为链表节点已经销毁,不回收可能导致内存泄漏。 > > tips: listPopt为从尾部弹出,listPoph为从头部弹出,listPop可以指定位置。 ### 读写节点数据 使用 `listRead()` 和 `listWrite()` 函数来读取和写入节点数据。例如: ```C int *pdata = (int *)listRead(myList, 0); ``` > 读取链表中的第一个节点的数据 ```C int *myData = malloc(sizeof(int)); listWrite(myList, 0, myData); ``` > 写入一个新数据。 > > 警告:请不要把局部变量的指针传入,这将会导致访问越界。 ### 移除节点和删除节点 使用 `listRemoveNodeAt()` 可以从链表中移除一个指定结点,并将该节点返回。例如: ```C node_t* pnode = listRemoveNodeAt(mylist, 0) // mylist为list_t*指针, 0为index ``` > 移除一个节点并用pnode接收该节点 使用 `listDeleteNodeAt()` 函数删除链表中的节点。例如: ```C listDeleteNodeAt(myList, 0); // mylist为list_t*指针, 0为index ``` > 删除链表中的第一个节点,即从链表中移除并回收该节点内存 ### 销毁链表 使用 `listDestroy()` 函数销毁链表对象。例如: ```C listDestroy(&myList); // mylist为list_t*指针,函数接收的是指向指针的指针 ``` > 销毁链表对象并释放与之关联的内存。这里是List的二级指针 > > 注意: > 销毁链表之后链表数据会丢弃而不是释放,如果node中含有未被释放的内存应当先使用 `listDataFree`或 `listDatasFree`释放,详见test.c中的示例 以上为 `list` 库的基本使用方法。如果需要更详细的说明,请参考源文件中的注释。 ## Update Log ### v1.2 * [X] 新增静态创建链表功能和链表结点操作 * [X] 为list_t加入指向尾部的指针 * [X] 重构代码,通过二分法优化性能 * [X] 新增 `listPop` 和 `listPush` API * [X] 新增节点搜索函数 `listSearchNode` ### v1.1 - [X] 优化迭代器 - [X] 优化类型转换的警告 - [X] 更新函数描述中的错误 - [X] 更新使用方法到README - [X] 增加更新日志到README ### v1.0 * [X] 完成基本操作 * [X] 通过单元测试 * [X] 通过VisualStudio检测内存泄漏