小工具知识网

当前位置: 首页 > 行业知识 > 【嵌入式高级C语言】9:万能型链表懒人手册

行业知识

【嵌入式高级C语言】9:万能型链表懒人手册

2026-11-13 09:07:09 来源:互联网转载

文章目录

  • 序言
  • 单向不循环链表
    • 拼图框架搭建 - `Necessary`
    • 功能拼图块
      • 1 创建链表头信息结构体 - `Necessary`
      • 2 链表头部插入 - `Optional`
      • 3 链表的遍历 - `Optional`
      • 4 链表的销毁 - `Necessary`
      • 5 链表头信息结构体销毁 - `Necessary`
      • 6 获取链表中节点的个数 - `Optional`
      • 7 链表尾部插入 - `Optional`/`Dependent`
      • 8 链表根据索引插入数据 - `Optional`
      • 9 链表根据索引删除数据 - `Optional`/`Dependent`
      • 10 链表根据索引修改数据 - `Optional`/`Dependent`
      • 11 链表根据索引获取数据 - `Optional`/`Dependent`
      • 12 根据关键字寻找匹配索引 - `Optional`/`Dependent`
      • 13 链表根据关键字删除数据 - `Optional`
      • 14 链表根据关键字修改数据 - `Optional`
      • 15 链表根据关键字获取数据 - `Optional`
      • 16 链表根据关键字删除所有匹配的节点 - `Optional`
      • 17 链表根据关键字修改所有匹配的节点 - `Optional`
      • 18 链表根据关键字查找所有的索引 - `Optional`
      • 19 链表的翻转 - `Optional`
      • 测试代码添加模块
        • 1 自定义数据销毁函数 - `Necessary`
        • 2 自定义数据打印函数 - `Necessary`
        • 3 自定义数据比较函数 - `Necessary`
        • 测试代码参考
        • 双向循环链表
          • 拼图框架搭建 - `Necessary`
          • 功能拼图块
            • 1 创建链表头信息结构体 - `Necessary`
            • 2 链表头部插入 - `Optional`/`Dependent`
            • 3 链表尾部插入 - `Optional`/`Dependent`
            • 4 链表的遍历 - `Optional`
            • 5 链表的反向遍历 - `Optional`
            • 6 链表的销毁 - `Necessary`
            • 7 链表头信息结构体销毁 - `Necessary`
            • 8 获取链表中节点的个数 - `Optional`
            • 9 链表根据索引插入数据 - `Optional`
            • 10 链表根据索引删除数据 - `Optional`/`Dependent`
            • 11 链表根据索引修改数据 - `Optional`/`Dependent`
            • 12 链表根据索引获取数据 - `Optional`/`Dependent`
            • 13 根据关键字寻找匹配索引 - `Optional`/`Dependent`
            • 14 链表根据关键字删除数据 - `Optional`
            • 15 链表根据关键字修改数据 - `Optional`
            • 16 链表根据关键字获取数据 - `Optional`
            • 17 链表根据关键字删除所有匹配的节点 - `Optional`
            • 18 链表根据关键字修改所有匹配的节点 - `Optional`
            • 19 链表根据关键字查找所有的索引 - `Optional`
            • 测试代码添加模块
              • 1 自定义数据销毁函数 - `Necessary`
              • 2 自定义数据打印函数 - `Necessary`
              • 3 自定义数据比较函数 - `Necessary`
              • 测试代码分享
              • 附录

                序言

                ���链表篇意在制作所有人都可拿来即用的万能型链表懒人拼装手册,使用门槛低,不需要使用者有很深的语言和数据结构理解,使用简单且有参考代码。如使用本手册进行链表的学习也是一种绝佳的体验,源码注释丰富且逻辑清晰,相信读者可以在轻松愉快的环境下学习掌握。如果全部理解并掌握此手册,相信你对于绝大部分链表及数据操作已然不成问题,借此打下良好的基础便于日后面对更加复杂的挑战。

                万能型链表义如其名,可以存储任何数据类型,只有你想不到的,没有它存不了的,但是需要读者注意其使用技巧(必要时请参考附录)。

                在开始前,本人在这里借用戴尔·卡耐基的一句话祝各位学习路上可以披荆斩棘,乘风破浪,一往直前。

                多数人都拥有自己不了解的能力和机会,都有可能做到未曾梦想的事情。

                ——戴尔·卡耐基

                单向不循环链表

                拼图框架搭建 - Necessary

                .h

                #ifndef ___h__#define ___h__#include #include #include // 匹配成功#define MATCH_SUCCESS 0// 匹配失败#define MATCH_FAIL -3// 调试宏#define DEBUG#define _FILE_DEBUG// 函数功能错误#define FUN_ERROR -1// 参数错误#define PAR_ERROR -2// 类型定义typedef int(*op_t)(void *data);typedef int(*cmp_t)(void *data, void *key);/** * @brief 链表节点定义 */typedef struct _node_t{    void *data;                     // 数据域    struct _node_t *next;           // 指针域}node_t;/** * @brief 链表头信息结构体定义 */typedef struct _uolist_t{    node_t *fstnode_p;              // 指向链表的第一个节点    int size;                       // 存储数据的类型大小    int count;                      // 节点的个数    op_t my_destroy;                // 自定义销毁函数}uolist_t;/********************************** 请在这个区域内添加功能拼图 ***********************************//***********************************************************************************************/#endif

                .c

                #include ".h"/** * @brief           创建节点空间 * @param           链表头信息结构体指针 * @return          节点指针 */static node_t *__node_calloc(uolist_t *uo){    /* 变量定义 */    node_t *p = NULL;    /* 参数检查 */    if (NULL == uo)    {    #ifdef DEBUG        printf("__node_calloc: Parameter error\n");    #elif defined FILE_DEBUG            #endif        goto ERR0;      } /* end of if (NULL == uo) */    /* 创建节点空间 */     p = (node_t *)calloc(1, sizeof(node_t));    if (NULL == p)    {    #ifdef DEBUG        printf("__node_calloc: p calloc error\n");    #elif defined FILE_DEBUG            #endif        goto ERR1;      } /* end of if (NULL == p) */    /* 创建节点中数据空间 */    p->data = (void *)calloc(1, uo->size);    if (NULL == p->data)    {    #ifdef DEBUG        printf("__node_calloc: data calloc error\n");    #elif defined FILE_DEBUG            #endif        goto ERR2;              } /* end of if (NULL == p->data) */    return p;ERR0:    return (void *)PAR_ERROR;ERR2:    free(p);    p = NULL;ERR1:    return (void *)FUN_ERROR;}/****************************************请在下方添加功能块拼图************************************************/

                功能拼图块

                1 创建链表头信息结构体 - Necessary

                .h功能添加区

                /** * @brief           创建链表头信息结构体 * @param           存储数据类型大小 * @param           自定义销毁数据函数 * @return          指向链表头信息结构体的指针 */uolist_t *uolist_create(int size, op_t my_destroy);

                .c功能添加区

                /** * @brief           创建链表头信息结构体 * @param           存储数据类型大小 * @param           自定义销毁数据函数 * @return          指向链表头信息结构体的指针 */uolist_t *uolist_create(int size, op_t my_destroy){    /* 变量定义 */    uolist_t *uo = NULL;    /* 参数检查 */    if (size     #ifdef DEBUG        printf("uolist_create: Parameter error\n");    #elif defined FILE_DEBUG            #endif        goto ERR0;    } /* end of if (size     #ifdef DEBUG        printf("uolist_create: calloc error\n");    #elif defined FILE_DEBUG            #endif        goto ERR1;           } /* end of if (NULL == uo) */    /* 信息输入 */    uo-count = 0;    uo-size = size;    uo->fstnode_p = NULL;    uo->my_destroy = my_destroy;    return uo;ERR0:    return (void *)PAR_ERROR;ERR1:    return (void *)FUN_ERROR;}

                2 链表头部插入 - Optional

                .h功能添加区

                /** * @brief           链表头部插入 * @param           头信息结构体的指针 * @param           插入节点数据 * @return           *      @arg  0:正常 *      @arg  PAR_ERROR:参数错误 *      @arg  FUN_ERROR:函数错误 */int uolist_prepend(uolist_t *uo, void *data);

                .c功能添加区

                /** * @brief           链表头部插入 * @param           头信息结构体的指针 * @param           插入节点数据 * @return           *      @arg  0:正常 *      @arg  PAR_ERROR:参数错误 *      @arg  FUN_ERROR:函数错误 */int uolist_prepend(uolist_t *uo, void *data){    node_t *temp1 = NULL;    node_t *temp2 = NULL;    /* 参数检查 */    if (NULL == uo || NULL == data)    {    #ifdef DEBUG        printf("uolist_prepend: Parameter error\n");    #elif defined FILE_DEBUG            #endif        goto ERR0;            } /* end of if (NULL == uo || NULL == data) */    /* 1.创建一个新的节点 */    temp1 = __node_calloc(uo);    /* 2.节点数据输入 */    temp1->next = NULL;    memcpy(temp1->data, data, uo->size);    /* 3.链表节点头部插入 */    if (NULL == uo->fstnode_p)    {        uo->fstnode_p = temp1;    }    else     {        temp2 = uo->fstnode_p;        uo->fstnode_p = temp1;        temp1->next = temp2;    }    /* 链表头信息更新 */    uo->count++;    return 0;ERR0:    return PAR_ERROR;ERR1:    return FUN_ERROR;}

                3 链表的遍历 - Optional

                .h功能添加区

                /** * @brief           链表的遍历 * @param           头信息结构体的指针 * @param           自定义打印数据函数 * @return           *      @arg  0:正常 *      @arg  PAR_ERROR:参数错误 *      @arg  FUN_ERROR:函数错误 */int uolist_traverse(uolist_t *uo, op_t my_print);

                .c功能添加区

                /** * @brief           链表的遍历 * @param           头信息结构体的指针 * @param           自定义打印数据函数 * @return           *      @arg  0:正常 *      @arg  PAR_ERROR:参数错误 *      @arg  FUN_ERROR:函数错误 */int uolist_traverse(uolist_t *uo, op_t my_print){    node_t *temp = NULL;    /* 参数检查 */    if (NULL == uo || NULL == my_print)    {    #ifdef DEBUG        printf("uolist_traverse: Parameter error\n");    #elif defined FILE_DEBUG            #endif        goto ERR0;            } /* end of if (NULL == uo || NULL == my_print) */    /* 链表的遍历 */    temp = uo->fstnode_p;    while (temp != NULL)    {        my_print(temp->data);        temp = temp->next;    } /* end of while (temp != NULL) */    return 0;ERR0:    return PAR_ERROR;ERR1:    return FUN_ERROR;    }

                4 链表的销毁 - Necessary

                .h功能添加区

                /** * @brief           链表销毁函数(不包括头信息结构体) * @param           头信息结构体的指针 * @return           *      @arg  0:正常 *      @arg  PAR_ERROR:参数错误 *      @arg  FUN_ERROR:函数错误 */int uolist_destroy(uolist_t *uo);

                .c功能添加区

                /** * @brief           链表销毁函数(不包括头信息结构体) * @param           头信息结构体的指针 * @return           *      @arg  0:正常 *      @arg  PAR_ERROR:参数错误 *      @arg  FUN_ERROR:函数错误 */int uolist_destroy(uolist_t *uo){    node_t *temp = NULL;    node_t *save = NULL;    /* 参数检查 */    if (NULL == uo)    {    #ifdef DEBUG        printf("uolist_destroy: Parameter error\n");    #elif defined FILE_DEBUG            #endif        goto ERR0;            } /* end of if (NULL == uo) */        temp = uo->fstnode_p;    /* 依次释放节点空间 */    while (NULL != temp)    {        /* 1.保存下个节点的指针 */        save = temp->next;        /* 2.释放数据空间 */        uo->my_destroy(temp->data);        temp->data = NULL;        /* 3.释放节点空间 */        free(temp);        temp = NULL;        /* 4.指向下一个节点 */        temp = save;    } /* end of while (NULL != temp) */    /* 头信息刷新 */    uo->fstnode_p = NULL;    uo->count = 0;    return 0;ERR0:    return PAR_ERROR;ERR1:    return FUN_ERROR;     }

                5 链表头信息结构体销毁 - Necessary

                .h功能添加区

                /** * @brief           头信息结构体销毁函数 * @param           头信息结构体的指针的地址 * @return           *      @arg  0:正常 *      @arg  PAR_ERROR:参数错误 *      @arg  FUN_ERROR:函数错误 */int head_destroy(uolist_t **p);

                .c功能添加区

                /** * @brief           头信息结构体销毁函数 * @param           头信息结构体的指针的地址 * @return           *      @arg  0:正常 *      @arg  PAR_ERROR:参数错误 *      @arg  FUN_ERROR:函数错误 */int head_destroy(uolist_t **p){    /* 参数检查 */    if (NULL == p)    {    #ifdef DEBUG        printf("head_destroy: Parameter error\n");    #elif defined FILE_DEBUG            #endif        goto ERR0;            } /* end of if (NULL == p) */      /* 销毁结构体空间 */    free(*p);    *p = NULL;    return 0;ERR0:    return PAR_ERROR;ERR1:    return FUN_ERROR;  }

                6 获取链表中节点的个数 - Optional

                .h功能添加区

                /** * @brief           获取链表中节点的个数 * @param           头信息结构体的指针 * @return          链表节点个数 */int get_count(uolist_t *p);

                .c功能添加区

                /** * @brief           获取链表中节点的个数 * @param           头信息结构体的指针 * @return          链表节点个数 */int get_count(uolist_t *p){    /* 参数检查 */    if (NULL == p)    {    #ifdef DEBUG        printf("get_count: Parameter error\n");    #elif defined FILE_DEBUG            #endif        goto ERR0;            } /* end of if (NULL == p) */      return p->count;ERR0:    return PAR_ERROR;}

                7 链表尾部插入 - Optional/Dependent

                .h功能添加区

                /** * @brief           链表尾部插入 * @param           头信息结构体的指针 * @param           数据的指针 * @return           *      @arg  0:正常 *      @arg  PAR_ERROR:参数错误 *      @arg  FUN_ERROR:函数错误 */int uolist_append(uolist_t *uo, void *data);

                .c功能添加区

                /** * @brief           链表尾部插入 * @param           头信息结构体的指针 * @param           数据的指针 * @return           *      @arg  0:正常 *      @arg  PAR_ERROR:参数错误 *      @arg  FUN_ERROR:函数错误 */int uolist_append(uolist_t *uo, void *data){    node_t *temp1 = NULL;    node_t *temp2 = NULL;    /* 参数检查 */    if (NULL == uo || NULL == data)    {    #ifdef DEBUG        printf("uolist_append: Parameter error\n");    #elif defined FILE_DEBUG            #endif        goto ERR0;            } /* end of if (NULL == uo || NULL == data) */    /* 1.创建一个新的节点 */    temp1 = __node_calloc(uo);    /* 2.节点数据输入 */    temp1->next = NULL;    memcpy(temp1->data, data, uo->size);    /* 3.数据尾部插入 */    if (NULL == uo->fstnode_p)    {        uo->fstnode_p = temp1;    }    else     {        temp2 = uo->fstnode_p;        while (temp2->next != NULL)        {            temp2 = temp2->next;        } /* end of while (temp2->next != NULL) */        temp2->next = temp1;    }    /* 4.刷新信息 */    uo->count++;    return 0;ERR0:    return PAR_ERROR;ERR1:    return FUN_ERROR;  }

                8 链表根据索引插入数据 - Optional

                .h功能添加区

                /** * @brief           链表根据索引插入 * @param           头信息结构体的指针 * @param           数据的指针 * @param           索引值 * @return           *      @arg  0:正常 *      @arg  PAR_ERROR:参数错误 *      @arg  FUN_ERROR:函数错误 */int uolist_insert_by_index(uolist_t *uo, void *data, int index);

                .c功能添加区

                /** * @brief           链表根据索引插入 * @param           头信息结构体的指针 * @param           数据的指针 * @param           索引值 * @return           *      @arg  0:正常 *      @arg  PAR_ERROR:参数错误 *      @arg  FUN_ERROR:函数错误 */int uolist_insert_by_index(uolist_t *uo, void *data, int index){    node_t *temp1 = NULL;    node_t *temp2 = NULL;    node_t *save = NULL;    int i = 0;    /* 参数检查 */    if (NULL == uo || NULL == data || index next = NULL;    memcpy(temp1->data, data, uo->size);    /* 3.判断索引 */    temp2 = uo->fstnode_p;    if (index count && index > 0)    {        // 寻找索引位置        for (i = 0; i next;        } /* end of for (i = 0; i next;        // 在索引位置插入新节点        temp2->next = temp1;        // 链接保存链表        temp1->next = save;    }    else if (index == 0)    {        // 头部插入        uo->fstnode_p = temp1;        temp1->next = temp2;    }    else     {        // 尾部插入        while (temp2->next != NULL)        {            temp2 = temp2->next;        } /* end of while (temp2->next != NULL) */        temp2->next = temp1;    }    /* 刷新管理信息 */    uo->count++;    return 0;ERR0:    return PAR_ERROR;ERR1:    return FUN_ERROR; }

                9 链表根据索引删除数据 - Optional/Dependent

                .h功能添加区

                /** * @brief           链表根据索引删除 * @param           头信息结构体的指针 * @param           索引值 * @return           *      @arg  0:正常 *      @arg  PAR_ERROR:参数错误 *      @arg  FUN_ERROR:函数错误 */int uolist_delete_by_index(uolist_t *uo, int index);

                .c功能添加区

                /** * @brief           链表根据索引删除 * @param           头信息结构体的指针 * @param           索引值 * @return           *      @arg  0:正常 *      @arg  PAR_ERROR:参数错误 *      @arg  FUN_ERROR:函数错误 */int uolist_delete_by_index(uolist_t *uo, int index){    node_t *temp1 = NULL;    node_t *temp2 = NULL;    node_t *des = NULL;    int i = 0;    /* 参数检查 */    if (NULL == uo || index = uo->count)    {    #ifdef DEBUG        printf("uolist_delete_by_index: Parameter error\n");    #elif defined FILE_DEBUG            #endif        goto ERR0;            } /* end of if (NULL == uo || index = uo->count) */    /* 寻找索引的前一个 */    if (index == 0)    {        // 保存节点        des = uo->fstnode_p;        temp2 = uo->fstnode_p->next;        // 连接节点        uo->fstnode_p = temp2;        // 释放节点        uo->my_destroy(des->data);        free(des);        des = NULL;    }    else     {        // 寻找并保存节点        temp1 = uo->fstnode_p;        for (i = 0; i next;        } /* end of for (i = 0; i next->next;        des = temp1->next;        // 连接节点        temp1->next = temp2;        // 释放节点        uo->my_destroy(des->data);        free(des);        des = NULL;    }    /* 刷新信息 */    uo->count--;    return 0;ERR0:    return PAR_ERROR;ERR1:    return FUN_ERROR; }

                10 链表根据索引修改数据 - Optional/Dependent

                .h功能添加区

                /** * @brief           链表根据索引修改数据 * @param           头信息结构体的指针 * @param           修改数据 * @param           索引值 * @return           *      @arg  0:正常 *      @arg  PAR_ERROR:参数错误 *      @arg  FUN_ERROR:函数错误 */int uolist_modify_by_index(uolist_t *uo, void *data, int index);

                .c功能添加区

                /** * @brief           链表根据索引修改数据 * @param           头信息结构体的指针 * @param           修改数据 * @param           索引值 * @return           *      @arg  0:正常 *      @arg  PAR_ERROR:参数错误 *      @arg  FUN_ERROR:函数错误 */int uolist_modify_by_index(uolist_t *uo, void *data, int index){    int i = 0;    node_t *temp = NULL;    /* 参数检查 */    if (NULL == uo || index = uo->count || NULL == data)    {    #ifdef DEBUG        printf("uolist_modify_by_index: Parameter error\n");    #elif defined FILE_DEBUG            #endif        goto ERR0;            } /* end of if (NULL == uo || index = uo->count || NULL == data) */    /* 寻找索引位置 */    temp = uo->fstnode_p;    for (i = 0; i next;    } /* end of for (i = 0; i data, data, uo->size);    return 0;ERR0:    return PAR_ERROR;ERR1:    return FUN_ERROR;     }

                11 链表根据索引获取数据 - Optional/Dependent

                .h功能添加区

                /** * @brief           链表根据索引检索数据 * @param           头信息结构体的指针 * @param           要检索的数据 * @param           索引值 * @return           *      @arg  0:正常 *      @arg  PAR_ERROR:参数错误 *      @arg  FUN_ERROR:函数错误 */int uolist_retrieve_by_index(uolist_t *uo, void *data, int index);

                .c功能添加区

                /** * @brief           链表根据索引检索数据 * @param           头信息结构体的指针 * @param           要检索的数据 * @param           索引值 * @return           *      @arg  0:正常 *      @arg  PAR_ERROR:参数错误 *      @arg  FUN_ERROR:函数错误 */int uolist_retrieve_by_index(uolist_t *uo, void *data, int index){    int i = 0;    node_t *temp = NULL;    /* 参数检查 */    if (NULL == uo || index = uo->count || NULL == data)    {    #ifdef DEBUG        printf("uolist_retrieve_by_index: Parameter error\n");    #elif defined FILE_DEBUG            #endif        goto ERR0;            } /* end of if (NULL == uo || index = uo->count || NULL == data) */    /* 寻找索引位置 */    temp = uo->fstnode_p;    for (i = 0; i next;    } /* end of for (i = 0; i data, uo->size);    return 0;ERR0:    return PAR_ERROR;ERR1:    return FUN_ERROR;      }

                12 根据关键字寻找匹配索引 - Optional/Dependent

                .h功能添加区

                /** * @brief           根据关键字寻找匹配索引 * @param           头信息结构体的指针 * @param           关键字 * @param           自定义比较函数 * @return          索引值     *      @arg  PAR_ERROR:参数错误 *      @arg  MATCH_FAIL:无匹配索引 */int get_match_index(uolist_t *uo, void *key, cmp_t op_cmp);

                .c功能添加区

                /** * @brief           根据关键字寻找匹配索引 * @param           头信息结构体的指针 * @param           关键字 * @param           自定义比较函数 * @return          索引值     *      @arg  PAR_ERROR:参数错误 *      @arg  MATCH_FAIL:无匹配索引 */int get_match_index(uolist_t *uo, void *key, cmp_t op_cmp){    int index = 0;    node_t *temp = NULL;    /* 参数检查 */    if (NULL == uo || NULL == key || NULL == op_cmp)    {    #ifdef DEBUG        printf("get_match_index: Parameter error\n");    #elif defined FILE_DEBUG            #endif        goto ERR0;            } /* end of if (NULL == uo || NULL == key || NULL == op_cmp) */    /* 判断是否为空链表 */    if (NULL == uo->fstnode_p)    {        goto ERR1;    } /* end of if (NULL == uo->fstnode_p) */    /* 寻找匹配索引 */    index = 0;    temp = uo->fstnode_p;    while (1)    {        if (MATCH_SUCCESS == op_cmp(temp->data, key))        {            return index;        } /* end of if (MATCH_SUCCESS == op_cmp(temp->data, key)) */        temp = temp->next;        if (NULL == temp)        {            goto ERR1;        } /* end of if (NULL == temp) */        index++;    } /* end of while (1) */ERR0:    return PAR_ERROR;ERR1:    return MATCH_FAIL; }

                13 链表根据关键字删除数据 - Optional

                .h功能添加区

                /** * @brief           链表根据关键字删除 * @param           头信息结构体的指针 * @param           关键字 * @param           自定义比较函数 * @return           *      @arg  0:正常 *      @arg  PAR_ERROR:参数错误 *      @arg  FUN_ERROR:函数错误 */int uolist_delete_by_key(uolist_t *uo, void *key, cmp_t op_cmp);

                .c功能添加区

                /** * @brief           链表根据关键字删除 * @param           头信息结构体的指针 * @param           关键字 * @param           自定义比较函数 * @return           *      @arg  0:正常 *      @arg  PAR_ERROR:参数错误 *      @arg  FUN_ERROR:函数错误 */int uolist_delete_by_key(uolist_t *uo, void *key, cmp_t op_cmp){    int index = 0;    /* 参数检查 */    if (NULL == uo || NULL == key || NULL == op_cmp)    {    #ifdef DEBUG        printf("uolist_delete_by_key: Parameter error\n");    #elif defined FILE_DEBUG            #endif        goto ERR0;            } /* end of if (NULL == uo || NULL == key || NULL == op_cmp) */    /* 获取匹配索引 */    index = get_match_index(uo, key, op_cmp);    if (PAR_ERROR == index || MATCH_FAIL == index)    {        goto ERR1;    } /* end of if (PAR_ERROR == index || MATCH_FAIL == index) */    /* 根据索引删除节点 */    uolist_delete_by_index(uo, index);    return 0;ERR0:    return PAR_ERROR;ERR1:    return FUN_ERROR;        }

                使用此功能同时需要添加9、12功能。

                14 链表根据关键字修改数据 - Optional

                .h功能添加区

                /** * @brief           链表根据关键字修改数据 * @param           头信息结构体的指针 * @param           修改的数据 * @param           关键字 * @param           自定义比较函数 * @return           *      @arg  0:正常 *      @arg  PAR_ERROR:参数错误 *      @arg  FUN_ERROR:函数错误 */int uolist_modify_by_key(uolist_t *uo, void *data, void *key, cmp_t op_cmp);

                .c功能添加区

                /** * @brief           链表根据关键字修改数据 * @param           头信息结构体的指针 * @param           修改的数据 * @param           关键字 * @param           自定义比较函数 * @return           *      @arg  0:正常 *      @arg  PAR_ERROR:参数错误 *      @arg  FUN_ERROR:函数错误 */int uolist_modify_by_key(uolist_t *uo, void *data, void *key, cmp_t op_cmp){    int index = 0;    /* 参数检查 */    if (NULL == uo || NULL == key || NULL == op_cmp || NULL == data)    {    #ifdef DEBUG        printf("uolist_modify_by_key: Parameter error\n");    #elif defined FILE_DEBUG            #endif        goto ERR0;            } /* end of if (NULL == uo || NULL == key || NULL == op_cmp || NULL == data) */    /* 获取匹配索引 */    index = get_match_index(uo, key, op_cmp);    if (PAR_ERROR == index || MATCH_FAIL == index)    {        goto ERR1;    } /* end of if (PAR_ERROR == index || MATCH_FAIL == index) */    /* 根据索引修改数据 */    uolist_modify_by_index(uo, data, index);    return 0;ERR0:    return PAR_ERROR;ERR1:    return FUN_ERROR; }

                使用此功能同时需要添加10、12功能。

                15 链表根据关键字获取数据 - Optional

                .h功能添加区

                /** * @brief           链表根据关键字获取数据 * @param           头信息结构体的指针 * @param           获取的数据 * @param           关键字 * @param           自定义比较函数 * @return           *      @arg  0:正常 *      @arg  PAR_ERROR:参数错误 *      @arg  FUN_ERROR:函数错误 */int uolist_retrieve_by_key(uolist_t *uo, void *data, void *key, cmp_t op_cmp);

                .c功能添加区

                /** * @brief           链表根据关键字获取数据 * @param           头信息结构体的指针 * @param           获取的数据 * @param           关键字 * @param           自定义比较函数 * @return           *      @arg  0:正常 *      @arg  PAR_ERROR:参数错误 *      @arg  FUN_ERROR:函数错误 */int uolist_retrieve_by_key(uolist_t *uo, void *data, void *key, cmp_t op_cmp){    int index = 0;    /* 参数检查 */    if (NULL == uo || NULL == key || NULL == op_cmp || NULL == data)    {    #ifdef DEBUG        printf("uolist_retrieve_by_key: Parameter error\n");    #elif defined FILE_DEBUG            #endif        goto ERR0;            } /* end of if (NULL == uo || NULL == key || NULL == op_cmp || NULL == data) */    /* 获取匹配索引 */    index = get_match_index(uo, key, op_cmp);    if (PAR_ERROR == index || MATCH_FAIL == index)    {        goto ERR1;    } /* end of if (PAR_ERROR == index || MATCH_FAIL == index) */    /* 根据索引获取数据 */    uolist_retrieve_by_index(uo, data, index);    return 0;ERR0:    return PAR_ERROR;ERR1:    return FUN_ERROR; }

                使用此功能同时需要添加11、12功能。

                16 链表根据关键字删除所有匹配的节点 - Optional

                .h功能添加区

                /** * @brief           链表根据关键字删除所有匹配的节点 * @param           头信息结构体的指针 * @param           关键字 * @param           自定义比较函数  * @return           *      @arg  0:正常 *      @arg  PAR_ERROR:参数错误 *      @arg  FUN_ERROR:函数错误 */int uolist_delete_all_by_key(uolist_t *uo, void *key, cmp_t op_cmp);

                .c功能添加区

                /** * @brief           链表根据关键字删除所有匹配的节点 * @param           头信息结构体的指针 * @param           关键字 * @param           自定义比较函数  * @return           *      @arg  0:正常 *      @arg  PAR_ERROR:参数错误 *      @arg  FUN_ERROR:函数错误 */int uolist_delete_all_by_key(uolist_t *uo, void *key, cmp_t op_cmp){    int index = 0;    /* 参数检查 */    if (NULL == uo || NULL == key || NULL == op_cmp)    {    #ifdef DEBUG        printf("uolist_delete_all_by_key: Parameter error\n");    #elif defined FILE_DEBUG            #endif        goto ERR0;            } /* end of if (NULL == uo || NULL == key || NULL == op_cmp) */    while (1)    {        /* 获取匹配索引 */        index = get_match_index(uo, key, op_cmp);        if (PAR_ERROR == index || MATCH_FAIL == index)        {            goto ERR1;        } /* end of if (PAR_ERROR == index || MATCH_FAIL == index) */        /* 根据索引删除节点 */        uolist_delete_by_index(uo, index);    } /* end of while (1) */    return 0;ERR0:    return PAR_ERROR;ERR1:    return FUN_ERROR;  }

                使用此功能同时需要添加9、12功能。

                17 链表根据关键字修改所有匹配的节点 - Optional

                .h功能添加区

                /** * @brief           链表根据关键字修改所有匹配节点的数据 * @param           头信息结构体的指针 * @param           修改的数据 * @param           关键字 * @param           自定义比较函数 * @return           *      @arg  0:正常 *      @arg  PAR_ERROR:参数错误 *      @arg  FUN_ERROR:函数错误 */int uolist_modify_all_by_key(uolist_t *uo, void *data, void *key, cmp_t op_cmp);

                .c功能添加区

                /** * @brief           链表根据关键字修改所有匹配节点的数据 * @param           头信息结构体的指针 * @param           修改的数据 * @param           关键字 * @param           自定义比较函数 * @return           *      @arg  0:正常 *      @arg  PAR_ERROR:参数错误 *      @arg  FUN_ERROR:函数错误 */int uolist_modify_all_by_key(uolist_t *uo, void *data, void *key, cmp_t op_cmp){    int index = 0;    /* 参数检查 */    if (NULL == uo || NULL == key || NULL == op_cmp || NULL == data)    {    #ifdef DEBUG        printf("uolist_modify_all_by_key: Parameter error\n");    #elif defined FILE_DEBUG            #endif        goto ERR0;            } /* end of if (NULL == uo || NULL == key || NULL == op_cmp || NULL == data) */    while (1)    {        /* 获取匹配索引 */        index = get_match_index(uo, key, op_cmp);        if (PAR_ERROR == index || MATCH_FAIL == index)        {            goto ERR1;        } /* end of if (PAR_ERROR == index || MATCH_FAIL == index) */        /* 根据索引修改数据 */        uolist_modify_by_index(uo, data, index);    } /* end of while (1) */    return 0;ERR0:    return PAR_ERROR;ERR1:    return FUN_ERROR; }

                使用此功能同时需要添加10、12功能。

                18 链表根据关键字查找所有的索引 - Optional

                .h功能添加区

                /** * @brief           链表根据关键字查找所有的索引 * @param           头信息结构体的指针 * @param           关键字 * @param           自定义比较函数  * @return          存储索引链表 *      @arg  PAR_ERROR: 参数错误 *      @arg  NULL     : 没有找到匹配索引 */uolist_t *uolist_find_all_index_by_key(uolist_t *uo, void *key, cmp_t op_cmp);/** * @brief           自定义索引销毁函数 * @param           数据域 * @return          0 */int index_destroy(void *data);/** * @brief           自定义索引打印函数 * @param           数据域 * @return          0 */int index_print(void *data);

                .c功能添加区

                /** * @brief           链表根据关键字查找所有的索引 * @param           头信息结构体的指针 * @param           关键字 * @param           自定义比较函数  * @return          存储索引链表 *      @arg  PAR_ERROR: 参数错误 *      @arg  NULL     : 没有找到匹配索引 */uolist_t *uolist_find_all_index_by_key(uolist_t *uo, void *key, cmp_t op_cmp){    uolist_t *index_head = NULL;    node_t *temp = NULL;    int index = 0;    /* 参数检查 */    if (NULL == uo || NULL == key || NULL == op_cmp)    {    #ifdef DEBUG        printf("uolist_find_all_index_by_key: Parameter error\n");    #elif defined FILE_DEBUG            #endif        goto ERR0;            } /* end of if (NULL == uo || NULL == key || NULL == op_cmp) */    /* 判断链表是否存在 */    if (NULL == uo->fstnode_p)    {        goto ERR1;    } /* end of if (NULL == uo->fstnode_p) */    /* 创建存储索引的链表头信息结构体 */    index_head = uolist_create(sizeof(int), index_destroy);    /* 查找索引并插入链表 */    temp = uo->fstnode_p;    for (index = 0; NULL != temp; index++, temp = temp->next)    {        if (MATCH_SUCCESS == op_cmp(temp->data, key))        {            uolist_append(index_head, &index);        }    } /* end of for (index = 0; NULL != temp; index++, temp = temp->next) */    /* 判断是否为空链表 */    if (0 == get_count(index_head))    {        head_destroy(&index_head);    } /* end of if (0 == get_count(index_head)) */    return index_head;ERR0:    return (void *)PAR_ERROR;ERR1:    return NULL;}/** * @brief           自定义索引销毁函数 * @param           数据域 * @return          0 */int index_destroy(void *data){    free(data);    data = NULL;    return 0;}/** * @brief           自定义索引打印函数 * @param           数据域 * @return          0 */int index_print(void *data){    printf("index = %d\n", *(int *)data);    return 0;}

                使用此功能同时需要添加7功能。

                19 链表的翻转 - Optional

                .h功能添加区

                /** * @brief           链表的翻转 * @param           头信息结构体的指针 * @return           *      @arg  PAR_ERROR: 参数错误 *      @arg  0        : 正常 */int uolist_reverse(uolist_t *uo);

                .c功能添加区

                /** * @brief           链表的翻转 * @param           头信息结构体的指针 * @return           *      @arg  PAR_ERROR: 参数错误 *      @arg  0        : 正常 */int uolist_reverse(uolist_t *uo){    node_t *p = NULL;    node_t *save = NULL;    node_t *temp = NULL;    /* 参数检查 */    if (NULL == uo)    {    #ifdef DEBUG        printf("uolist_reverse: Parameter error\n");    #elif defined FILE_DEBUG            #endif        goto ERR0;            } /* end of if (NULL == uo) */    /* 链表的翻转 */    for (p = uo->fstnode_p, uo->fstnode_p = NULL, uo->count = 0; NULL != p; p = save)    {        /* 保存下一个节点 */        save = p->next;        /* 链表头插 */        p->next = NULL;        if (NULL == uo->fstnode_p)        {            uo->fstnode_p = p;        }        else         {            temp = uo->fstnode_p;            uo->fstnode_p = p;            p->next = temp;        }        /* 链表头信息更新 */        uo->count++;    } /* end of for (p = uo->fstnode_p, uo->fstnode_p = NULL, uo->count = 0; NULL != p; p = save) */    return 0;ERR0:    return PAR_ERROR;}

                测试代码添加模块

                1 自定义数据销毁函数 - Necessary

                int node_destroy(void *data){}

                2 自定义数据打印函数 - Necessary

                int data_print(void *data){}

                3 自定义数据比较函数 - Necessary

                int data_compare(void *data, void *key){}

                测试代码参考

                test.c

                /* 普通存储(int)变量测试代码 */#include #include ".h"/* 自定义节点中数据域销毁函数 */int node_destroy(void *data){    free(data);    data = NULL;    return 0;}/* 自定义数据域打印函数 */int data_print(void *data){    printf("%d\n", *(int *)data);    return 0;}/* 自定义关键字比较函数 */int data_compare(void *data, void *key){    if (0 == memcmp(data, key, sizeof(int)))    {        return MATCH_SUCCESS;    }    else     {        return MATCH_FAIL;    }}int main(int argc, char **argv){    uolist_t *index = NULL;    uolist_t *head = NULL;    int i = 0;    int j = 0;    int temp = 0;    int key = 0;    // 头信息结构体的创建    head = uolist_create(sizeof(int), node_destroy);    // 节点插入    for (i = 1; i         uolist_append(head, &i);    }    // 链表的遍历    printf("count = %d\n", get_count(head));    uolist_traverse(head, data_print);    printf("==================================================\n");    // 链表按照索引插入    temp = 1989;    uolist_insert_by_index(head, &temp, 6);    // 链表的遍历    printf("count = %d\n", get_count(head));    uolist_traverse(head, data_print);    printf("==================================================\n");    // 链表根据索引修改    temp = 2024;    uolist_modify_by_index(head, &temp, 6);    // 链表的遍历    printf("count = %d\n", get_count(head));    uolist_traverse(head, data_print);    printf("==================================================\n");    // 链表根据索引删除    uolist_delete_by_index(head, 6);    // 链表的遍历    printf("count = %d\n", get_count(head));    uolist_traverse(head, data_print);    printf("==================================================\n");    // 链表根据索引获取    uolist_retrieve_by_index(head, &temp, 6);    printf("temp = %d\n", temp);    // 链表的遍历    printf("count = %d\n", get_count(head));    uolist_traverse(head, data_print);    printf("==================================================\n");    // 链表根据关键字删除    key = 3;    uolist_delete_by_key(head, &key, data_compare);    // 链表的遍历    printf("count = %d\n", get_count(head));    uolist_traverse(head, data_print);    printf("==================================================\n");    // 链表根据关键字修改    temp = 666;    key = 6;    uolist_modify_by_key(head, &temp, &key, data_compare);    // 链表的遍历    printf("count = %d\n", get_count(head));    uolist_traverse(head, data_print);    printf("==================================================\n");    // 链表根据关键字获取数据    temp = 0;    key = 666;    uolist_retrieve_by_key(head, &temp, &key, data_compare);    printf("temp = %d\n", temp);    // 尾差3个5    temp = 5;    uolist_append(head, &temp);    uolist_append(head, &temp);    uolist_append(head, &temp);    // 链表的遍历    printf("count = %d\n", get_count(head));    uolist_traverse(head, data_print);    printf("==================================================\n");    // 链表根据关键字查找所有的索引    key = 5;    index = uolist_find_all_index_by_key(head, &key, data_compare);    // 索引链表的遍历    printf("count = %d\n", get_count(index));    uolist_traverse(index, index_print);    printf("==================================================\n");    // 链表根据关键字修改所有的节点    temp = 555;    key = 5;    uolist_modify_all_by_key(head, &temp, &key, data_compare);    // 链表的遍历    printf("count = %d\n", get_count(head));    uolist_traverse(head, data_print);    printf("==================================================\n");    // 链表根据关键字删除所有的节点    key = 555;    uolist_delete_all_by_key(head, &key, data_compare);    // 链表的遍历    printf("count = %d\n", get_count(head));    uolist_traverse(head, data_print);    printf("==================================================\n");    // 链表的翻转    uolist_reverse(head);    // 链表的遍历    printf("count = %d\n", get_count(head));    uolist_traverse(head, data_print);    printf("==================================================\n");    // 链表的释放    uolist_destroy(head);    uolist_destroy(index);    head_destroy(&head);    head_destroy(&index);    return 0;}
                h2双向循环链表/h2 pimg src="https://m.xiaogongju.com.cn/uploads/allimg/20250422/-250422235115118.png" //p h3拼图框架搭建 - Necessary/h3 p.h
                #ifndef ___h__#define ___h__#include #include #include // 匹配成功#define MATCH_SUCCESS 0// 匹配失败#define MATCH_FAIL -3// 调试宏#define DEBUG#define _FILE_DEBUG// 函数功能错误#define FUN_ERROR -1// 参数错误#define PAR_ERROR -2// 类型定义typedef int(*op_t)(void *data);typedef int(*cmp_t)(void *data, void *key);/** * @brief 链表节点定义 */typedef struct _node_t{    void *data;                     // 数据域    struct _node_t *prev;           // 前驱指针    struct _node_t *next;           // 后继指针}node_t;/** * @brief 链表头信息结构体定义 */typedef struct _udlist_t{    node_t *fstnode_p;              // 指向链表的第一个节点    int size;                       // 存储数据的类型大小    int count;                      // 节点的个数    op_t my_destroy;                // 自定义销毁函数}udlist_t;/********************************** 请在这个区域内添加功能拼图 ***********************************//***********************************************************************************************/#endif

                .c

                #include ".h"/** * @brief           创建节点空间 * @param           链表头信息结构体指针 * @return          节点指针 */static node_t *__node_calloc(udlist_t *ud){    /* 变量定义 */    node_t *p = NULL;    /* 参数检查 */    if (NULL == ud)    {    #ifdef DEBUG        printf("__node_calloc: Parameter error\n");    #elif defined FILE_DEBUG            #endif        goto ERR0;      } /* end of if (NULL == ud) */    /* 创建节点空间 */     p = (node_t *)calloc(1, sizeof(node_t));    if (NULL == p)    {    #ifdef DEBUG        printf("__node_calloc: p calloc error\n");    #elif defined FILE_DEBUG            #endif        goto ERR1;      } /* end of if (NULL == p) */    /* 创建节点中数据空间 */    p->data = (void *)calloc(1, ud->size);    if (NULL == p->data)    {    #ifdef DEBUG        printf("__node_calloc: data calloc error\n");    #elif defined FILE_DEBUG            #endif        goto ERR2;              } /* end of if (NULL == p->data) */    return p;ERR0:    return (void *)PAR_ERROR;ERR2:    free(p);    p = NULL;ERR1:    return (void *)FUN_ERROR;}/****************************************请在下方添加功能块拼图************************************************/

                功能拼图块

                1 创建链表头信息结构体 - Necessary

                .h功能添加区

                /** * @brief           创建链表头信息结构体 * @param           存储数据类型大小 * @param           自定义销毁数据函数 * @return          指向链表头信息结构体的指针 */udlist_t *udlist_create(int size, op_t my_destroy);

                .c功能添加区

                /** * @brief           创建链表头信息结构体 * @param           存储数据类型大小 * @param           自定义销毁数据函数 * @return          指向链表头信息结构体的指针 */udlist_t *udlist_create(int size, op_t my_destroy){    /* 变量定义 */    udlist_t *ud = NULL;    /* 参数检查 */    if (size     #ifdef DEBUG        printf("udlist_create: Parameter error\n");    #elif defined FILE_DEBUG            #endif        goto ERR0;    } /* end of if (size     #ifdef DEBUG        printf("udlist_create: calloc error\n");    #elif defined FILE_DEBUG            #endif        goto ERR1;           } /* end of if (NULL == ud) */    /* 信息输入 */    ud-count = 0;    ud-size = size;    ud->fstnode_p = NULL;    ud->my_destroy = my_destroy;    return ud;ERR0:    return (void *)PAR_ERROR;ERR1:    return (void *)FUN_ERROR;}

                2 链表头部插入 - Optional/Dependent

                .h功能添加区

                /** * @brief           链表头部插入 * @param           头信息结构体的指针 * @param           插入节点数据 * @return           *      @arg  0:正常 *      @arg  PAR_ERROR:参数错误 *      @arg  FUN_ERROR:函数错误 */int udlist_prepend(udlist_t *ud, void *data);

                .c功能添加区

                /** * @brief           链表头部插入 * @param           头信息结构体的指针 * @param           插入节点数据 * @return           *      @arg  0:正常 *      @arg  PAR_ERROR:参数错误 *      @arg  FUN_ERROR:函数错误 */int udlist_prepend(udlist_t *ud, void *data){    udlist_append(ud, data);    ud->fstnode_p = ud->fstnode_p->prev;    return 0;}

                使用此功能需要添加3功能。

                3 链表尾部插入 - Optional/Dependent

                .h功能添加区

                /** * @brief           链表尾部插入 * @param           头信息结构体的指针 * @param           数据的指针 * @return           *      @arg  0:正常 *      @arg  PAR_ERROR:参数错误 *      @arg  FUN_ERROR:函数错误 */int udlist_append(udlist_t *ud, void *data);

                .c功能添加区

                /** * @brief           链表尾部插入 * @param           头信息结构体的指针 * @param           数据的指针 * @return           *      @arg  0:正常 *      @arg  PAR_ERROR:参数错误 *      @arg  FUN_ERROR:函数错误 */int udlist_append(udlist_t *ud, void *data){    node_t *temp1 = NULL;    node_t *temp2 = NULL;    /* 参数检查 */    if (NULL == ud || NULL == data)    {    #ifdef DEBUG        printf("udlist_append: Parameter error\n");    #elif defined FILE_DEBUG            #endif        goto ERR0;            } /* end of if (NULL == ud || NULL == data) */    /* 1.创建一个新的节点 */    temp1 = __node_calloc(ud);    /* 2.节点数据输入 */    temp1->next = temp1;    temp1->prev = temp1;    memcpy(temp1->data, data, ud->size);    /* 3.数据尾部插入 */    if (0 == ud->count)    {        ud->fstnode_p = temp1;    }    else     {        temp2 = ud->fstnode_p->prev;        ud->fstnode_p->prev = temp1;        temp2->next = temp1;        temp1->prev = temp2;        temp1->next = ud->fstnode_p;    }    /* 4.刷新信息 */    ud->count++;    return 0;ERR0:    return PAR_ERROR;ERR1:    return FUN_ERROR;     }

                4 链表的遍历 - Optional

                .h功能添加区

                /** * @brief           链表的遍历 * @param           头信息结构体的指针 * @param           自定义打印数据函数 * @return           *      @arg  0:正常 *      @arg  PAR_ERROR:参数错误 *      @arg  FUN_ERROR:函数错误 */int udlist_traverse(udlist_t *ud, op_t my_print);

                .c功能添加区

                /** * @brief           链表的遍历 * @param           头信息结构体的指针 * @param           自定义打印数据函数 * @return           *      @arg  0:正常 *      @arg  PAR_ERROR:参数错误 *      @arg  FUN_ERROR:函数错误 */int udlist_traverse(udlist_t *ud, op_t my_print){    node_t *temp = NULL;    /* 参数检查 */    if (NULL == ud || NULL == my_print)    {    #ifdef DEBUG        printf("udlist_traverse: Parameter error\n");    #elif defined FILE_DEBUG            #endif        goto ERR0;            } /* end of if (NULL == ud || NULL == my_print) */    /* 链表的遍历 */    temp = ud->fstnode_p;    do     {        my_print(temp->data);        temp = temp->next;    }    while (temp != ud->fstnode_p);    return 0;ERR0:    return PAR_ERROR;ERR1:    return FUN_ERROR;   }

                5 链表的反向遍历 - Optional

                .h功能添加区

                /** * @brief           链表的反向遍历 * @param           头信息结构体的指针 * @param           自定义打印数据函数 * @return           *      @arg  0:正常 *      @arg  PAR_ERROR:参数错误 *      @arg  FUN_ERROR:函数错误 */int udlist_traverse_back(udlist_t *ud, op_t my_print);

                .c功能添加区

                /** * @brief           链表的反向遍历 * @param           头信息结构体的指针 * @param           自定义打印数据函数 * @return           *      @arg  0:正常 *      @arg  PAR_ERROR:参数错误 *      @arg  FUN_ERROR:函数错误 */int udlist_traverse_back(udlist_t *ud, op_t my_print){    node_t *temp = NULL;    /* 参数检查 */    if (NULL == ud || NULL == my_print)    {    #ifdef DEBUG        printf("udlist_traverse_back: Parameter error\n");    #elif defined FILE_DEBUG            #endif        goto ERR0;            } /* end of if (NULL == ud || NULL == my_print) */    /* 链表的遍历 */    temp = ud->fstnode_p;    do     {        my_print(temp->data);        temp = temp->prev;    }    while (temp != ud->fstnode_p);    return 0;ERR0:    return PAR_ERROR;ERR1:    return FUN_ERROR;   }

                6 链表的销毁 - Necessary

                .h功能添加区

                /** * @brief           链表销毁函数(不包括头信息结构体) * @param           头信息结构体的指针 * @return           *      @arg  0:正常 *      @arg  PAR_ERROR:参数错误 *      @arg  FUN_ERROR:函数错误 */int udlist_destroy(udlist_t *ud);

                .c功能添加区

                /** * @brief           链表销毁函数(不包括头信息结构体) * @param           头信息结构体的指针 * @return           *      @arg  0:正常 *      @arg  PAR_ERROR:参数错误 *      @arg  FUN_ERROR:函数错误 */int udlist_destroy(udlist_t *ud){    node_t *temp = NULL;    node_t *save = NULL;    /* 参数检查 */    if (NULL == ud)    {    #ifdef DEBUG        printf("udlist_destroy: Parameter error\n");    #elif defined FILE_DEBUG            #endif        goto ERR0;            } /* end of if (NULL == ud) */        temp = ud->fstnode_p;    /* 依次释放节点空间 */    if (NULL != temp)    {        do         {            /* 1.保存下个节点的指针 */            save = temp->next;            /* 2.释放数据空间 */            ud->my_destroy(temp->data);            temp->data = NULL;            /* 3.释放节点空间 */            free(temp);            temp = NULL;            /* 4.指向下一个节点 */            temp = save;        }        while (temp != ud->fstnode_p);    } /* end of if (NULL != temp) */    /* 头信息刷新 */    ud->fstnode_p = NULL;    ud->count = 0;    return 0;ERR0:    return PAR_ERROR;ERR1:    return FUN_ERROR;   }

                7 链表头信息结构体销毁 - Necessary

                .h功能添加区

                /** * @brief           头信息结构体销毁函数 * @param           头信息结构体的指针的地址 * @return           *      @arg  0:正常 *      @arg  PAR_ERROR:参数错误 *      @arg  FUN_ERROR:函数错误 */int head_destroy(udlist_t **p);

                .c功能添加区

                /** * @brief           头信息结构体销毁函数 * @param           头信息结构体的指针的地址 * @return           *      @arg  0:正常 *      @arg  PAR_ERROR:参数错误 *      @arg  FUN_ERROR:函数错误 */int head_destroy(udlist_t **p){    /* 参数检查 */    if (NULL == p)    {    #ifdef DEBUG        printf("head_destroy: Parameter error\n");    #elif defined FILE_DEBUG            #endif        goto ERR0;            } /* end of if (NULL == p) */      /* 销毁结构体空间 */    free(*p);    *p = NULL;    return 0;ERR0:    return PAR_ERROR;ERR1:    return FUN_ERROR;  }

                8 获取链表中节点的个数 - Optional

                .h功能添加区

                /** * @brief           获取链表中节点的个数 * @param           头信息结构体的指针 * @return          链表节点个数 */int get_count(udlist_t *p);

                .c功能添加区

                /** * @brief           获取链表中节点的个数 * @param           头信息结构体的指针 * @return          链表节点个数 */int get_count(udlist_t *p){    /* 参数检查 */    if (NULL == p)    {    #ifdef DEBUG        printf("get_count: Parameter error\n");    #elif defined FILE_DEBUG            #endif        goto ERR0;            } /* end of if (NULL == p) */      return p->count;ERR0:    return PAR_ERROR;    }

                9 链表根据索引插入数据 - Optional

                .h功能添加区

                /** * @brief           链表根据索引插入 * @param           头信息结构体的指针 * @param           数据的指针 * @param           索引值 * @return           *      @arg  0:正常 *      @arg  PAR_ERROR:参数错误 *      @arg  FUN_ERROR:函数错误 */int udlist_insert_by_index(udlist_t *ud, void *data, int index);

                .c功能添加区

                /** * @brief           链表根据索引插入 * @param           头信息结构体的指针 * @param           数据的指针 * @param           索引值 * @return           *      @arg  0:正常 *      @arg  PAR_ERROR:参数错误 *      @arg  FUN_ERROR:函数错误 */int udlist_insert_by_index(udlist_t *ud, void *data, int index){    node_t *temp1 = NULL;    node_t *temp2 = NULL;    node_t *save = NULL;    int i = 0;    /* 参数检查 */    if (NULL == ud || NULL == data || index fstnode_p;    if (index count && index > 0)    {        // 创建一个新的节点         temp1 = __node_calloc(ud);        // 节点数据输入         temp1->next = temp1;        temp1->prev = temp1;        memcpy(temp1->data, data, ud->size);        // 寻找索引位置        for (i = 0; i next;        } /* end of for (i = 0; i next;        // 链接新节点        save->prev = temp1;        temp2->next = temp1;        temp1->prev = temp2;        temp1->next = save;        // 刷新管理信息         ud->count++;    }    else if (index == 0)    {        // 头部插入        udlist_prepend(ud, data);    }    else     {        // 尾部插入        udlist_append(ud, data);    }    return 0;ERR0:    return PAR_ERROR;ERR1:    return FUN_ERROR; }

                使用此功能需要添加3、2功能。

                10 链表根据索引删除数据 - Optional/Dependent

                .h功能添加区

                /** * @brief           链表根据索引删除 * @param           头信息结构体的指针 * @param           索引值 * @return           *      @arg  0:正常 *      @arg  PAR_ERROR:参数错误 *      @arg  FUN_ERROR:函数错误 */int udlist_delete_by_index(udlist_t *ud, int index);

                .c功能添加区

                /** * @brief           链表根据索引删除 * @param           头信息结构体的指针 * @param           索引值 * @return           *      @arg  0:正常 *      @arg  PAR_ERROR:参数错误 *      @arg  FUN_ERROR:函数错误 */int udlist_delete_by_index(udlist_t *ud, int index){    node_t *temp1 = NULL;    node_t *temp2 = NULL;    node_t *des = NULL;    int i = 0;    /* 参数检查 */    if (NULL == ud || index = ud->count)    {    #ifdef DEBUG        printf("udlist_delete_by_index: Parameter error\n");    #elif defined FILE_DEBUG            #endif        goto ERR0;            } /* end of if (NULL == ud || index = ud->count) */    /* 寻找索引的前一个 */    if (index == 0)    {        // 保存节点        des = ud->fstnode_p;        temp1 = ud->fstnode_p->prev;        temp2 = ud->fstnode_p->next;        // 连接节点        temp1->next = temp2;        temp2->prev = temp1;        ud->fstnode_p = temp2;        // 释放节点        ud->my_destroy(des->data);        free(des);        des = NULL;    }    else     {        // 寻找并保存节点        temp1 = ud->fstnode_p;        for (i = 0; i next;        } /* end of for (i = 0; i next->next;        des = temp1->next;        // 连接节点        temp1->next = temp2;        temp2->prev = temp1;        // 释放节点        ud->my_destroy(des->data);        free(des);        des = NULL;    }    /* 刷新信息 */    ud->count--;    return 0;ERR0:    return PAR_ERROR;ERR1:    return FUN_ERROR; }

                11 链表根据索引修改数据 - Optional/Dependent

                .h功能添加区

                /** * @brief           链表根据索引修改数据 * @param           头信息结构体的指针 * @param           修改数据 * @param           索引值 * @return           *      @arg  0:正常 *      @arg  PAR_ERROR:参数错误 *      @arg  FUN_ERROR:函数错误 */int udlist_modify_by_index(udlist_t *ud, void *data, int index);

                .c功能添加区

                /** * @brief           链表根据索引修改数据 * @param           头信息结构体的指针 * @param           修改数据 * @param           索引值 * @return           *      @arg  0:正常 *      @arg  PAR_ERROR:参数错误 *      @arg  FUN_ERROR:函数错误 */int udlist_modify_by_index(udlist_t *ud, void *data, int index){    int i = 0;    node_t *temp = NULL;    /* 参数检查 */    if (NULL == ud || index = ud->count || NULL == data)    {    #ifdef DEBUG        printf("udlist_modify_by_index: Parameter error\n");    #elif defined FILE_DEBUG            #endif        goto ERR0;            } /* end of if (NULL == ud || index = ud->count || NULL == data) */    /* 寻找索引位置 */    temp = ud->fstnode_p;    for (i = 0; i next;    } /* end of for (i = 0; i data, data, ud->size);    return 0;ERR0:    return PAR_ERROR;ERR1:    return FUN_ERROR;       }

                12 链表根据索引获取数据 - Optional/Dependent

                .h功能添加区

                /** * @brief           链表根据索引检索数据 * @param           头信息结构体的指针 * @param           要检索的数据 * @param           索引值 * @return           *      @arg  0:正常 *      @arg  PAR_ERROR:参数错误 *      @arg  FUN_ERROR:函数错误 */int udlist_retrieve_by_index(udlist_t *ud, void *data, int index);

                .c功能添加区

                /** * @brief           链表根据索引检索数据 * @param           头信息结构体的指针 * @param           要检索的数据 * @param           索引值 * @return           *      @arg  0:正常 *      @arg  PAR_ERROR:参数错误 *      @arg  FUN_ERROR:函数错误 */int udlist_retrieve_by_index(udlist_t *ud, void *data, int index){    int i = 0;    node_t *temp = NULL;    /* 参数检查 */    if (NULL == ud || index = ud->count || NULL == data)    {    #ifdef DEBUG        printf("udlist_retrieve_by_index: Parameter error\n");    #elif defined FILE_DEBUG            #endif        goto ERR0;            } /* end of if (NULL == ud || index = ud->count || NULL == data) */    /* 寻找索引位置 */    temp = ud->fstnode_p;    for (i = 0; i next;    } /* end of for (i = 0; i data, ud->size);    return 0;ERR0:    return PAR_ERROR;ERR1:    return FUN_ERROR;      }

                13 根据关键字寻找匹配索引 - Optional/Dependent

                .h功能添加区

                /** * @brief           根据关键字寻找匹配索引 * @param           头信息结构体的指针 * @param           关键字 * @param           自定义比较函数 * @return          索引值     *      @arg  PAR_ERROR:参数错误 *      @arg  MATCH_FAIL:无匹配索引 */int get_match_index(udlist_t *ud, void *key, cmp_t op_cmp);

                .c功能添加区

                /** * @brief           根据关键字寻找匹配索引 * @param           头信息结构体的指针 * @param           关键字 * @param           自定义比较函数 * @return          索引值     *      @arg  PAR_ERROR:参数错误 *      @arg  MATCH_FAIL:无匹配索引 */int get_match_index(udlist_t *ud, void *key, cmp_t op_cmp){    int index = 0;    node_t *temp = NULL;    /* 参数检查 */    if (NULL == ud || NULL == key || NULL == op_cmp)    {    #ifdef DEBUG        printf("get_match_index: Parameter error\n");    #elif defined FILE_DEBUG            #endif        goto ERR0;            } /* end of if (NULL == ud || NULL == key || NULL == op_cmp) */    /* 判断是否为空链表 */    if (NULL == ud->fstnode_p)    {        goto ERR1;    } /* end of if (NULL == ud->fstnode_p) */    /* 寻找匹配索引 */    index = 0;    temp = ud->fstnode_p;    while (1)    {        if (MATCH_SUCCESS == op_cmp(temp->data, key))        {            return index;        } /* end of if (MATCH_SUCCESS == op_cmp(temp->data, key)) */        temp = temp->next;        if (ud->fstnode_p == temp)        {            goto ERR1;        } /* end of if (ud->fstnode_p == temp) */        index++;    } /* end of while (1) */ERR0:    return PAR_ERROR;ERR1:    return MATCH_FAIL; }

                14 链表根据关键字删除数据 - Optional

                .h功能添加区

                /** * @brief           链表根据关键字删除 * @param           头信息结构体的指针 * @param           关键字 * @param           自定义比较函数 * @return           *      @arg  0:正常 *      @arg  PAR_ERROR:参数错误 *      @arg  FUN_ERROR:函数错误 */int udlist_delete_by_key(udlist_t *ud, void *key, cmp_t op_cmp);

                .c功能添加区

                /** * @brief           链表根据关键字删除 * @param           头信息结构体的指针 * @param           关键字 * @param           自定义比较函数 * @return           *      @arg  0:正常 *      @arg  PAR_ERROR:参数错误 *      @arg  FUN_ERROR:函数错误 */int udlist_delete_by_key(udlist_t *ud, void *key, cmp_t op_cmp){    int index = 0;    /* 参数检查 */    if (NULL == ud || NULL == key || NULL == op_cmp)    {    #ifdef DEBUG        printf("udlist_delete_by_key: Parameter error\n");    #elif defined FILE_DEBUG            #endif        goto ERR0;            } /* end of if (NULL == ud || NULL == key || NULL == op_cmp) */    /* 获取匹配索引 */    index = get_match_index(ud, key, op_cmp);    if (PAR_ERROR == index || MATCH_FAIL == index)    {        goto ERR1;    } /* end of if (PAR_ERROR == index || MATCH_FAIL == index) */    /* 根据索引删除节点 */    udlist_delete_by_index(ud, index);    return 0;ERR0:    return PAR_ERROR;ERR1:    return FUN_ERROR;        }

                使用此功能同时需要添加10、13功能。

                15 链表根据关键字修改数据 - Optional

                .h功能添加区

                /** * @brief           链表根据关键字修改数据 * @param           头信息结构体的指针 * @param           修改的数据 * @param           关键字 * @param           自定义比较函数 * @return           *      @arg  0:正常 *      @arg  PAR_ERROR:参数错误 *      @arg  FUN_ERROR:函数错误 */int udlist_modify_by_key(udlist_t *ud, void *data, void *key, cmp_t op_cmp);

                .c功能添加区

                /** * @brief           链表根据关键字修改数据 * @param           头信息结构体的指针 * @param           修改的数据 * @param           关键字 * @param           自定义比较函数 * @return           *      @arg  0:正常 *      @arg  PAR_ERROR:参数错误 *      @arg  FUN_ERROR:函数错误 */int udlist_modify_by_key(udlist_t *ud, void *data, void *key, cmp_t op_cmp){    int index = 0;    /* 参数检查 */    if (NULL == ud || NULL == key || NULL == op_cmp || NULL == data)    {    #ifdef DEBUG        printf("udlist_modify_by_key: Parameter error\n");    #elif defined FILE_DEBUG            #endif        goto ERR0;            } /* end of if (NULL == ud || NULL == key || NULL == op_cmp || NULL == data) */    /* 获取匹配索引 */    index = get_match_index(ud, key, op_cmp);    if (PAR_ERROR == index || MATCH_FAIL == index)    {        goto ERR1;    } /* end of if (PAR_ERROR == index || MATCH_FAIL == index) */    /* 根据索引修改数据 */    udlist_modify_by_index(ud, data, index);    return 0;ERR0:    return PAR_ERROR;ERR1:    return FUN_ERROR; }

                使用此功能同时需要添加11、13功能。

                16 链表根据关键字获取数据 - Optional

                .h功能添加区

                /** * @brief           链表根据关键字获取数据 * @param           头信息结构体的指针 * @param           获取的数据 * @param           关键字 * @param           自定义比较函数 * @return           *      @arg  0:正常 *      @arg  PAR_ERROR:参数错误 *      @arg  FUN_ERROR:函数错误 */int udlist_retrieve_by_key(udlist_t *ud, void *data, void *key, cmp_t op_cmp);

                .c功能添加区

                /** * @brief           链表根据关键字获取数据 * @param           头信息结构体的指针 * @param           获取的数据 * @param           关键字 * @param           自定义比较函数 * @return           *      @arg  0:正常 *      @arg  PAR_ERROR:参数错误 *      @arg  FUN_ERROR:函数错误 */int udlist_retrieve_by_key(udlist_t *ud, void *data, void *key, cmp_t op_cmp){    int index = 0;    /* 参数检查 */    if (NULL == ud || NULL == key || NULL == op_cmp || NULL == data)    {    #ifdef DEBUG        printf("udlist_retrieve_by_key: Parameter error\n");    #elif defined FILE_DEBUG            #endif        goto ERR0;            } /* end of if (NULL == ud || NULL == key || NULL == op_cmp || NULL == data) */    /* 获取匹配索引 */    index = get_match_index(ud, key, op_cmp);    if (PAR_ERROR == index || MATCH_FAIL == index)    {        goto ERR1;    } /* end of if (PAR_ERROR == index || MATCH_FAIL == index) */    /* 根据索引获取数据 */    udlist_retrieve_by_index(ud, data, index);    return 0;ERR0:    return PAR_ERROR;ERR1:    return FUN_ERROR; }

                使用此功能同时需要添加12、13功能。

                17 链表根据关键字删除所有匹配的节点 - Optional

                .h功能添加区

                /** * @brief           链表根据关键字删除所有匹配的节点 * @param           头信息结构体的指针 * @param           关键字 * @param           自定义比较函数  * @return           *      @arg  0:正常 *      @arg  PAR_ERROR:参数错误 *      @arg  FUN_ERROR:函数错误 */int udlist_delete_all_by_key(udlist_t *ud, void *key, cmp_t op_cmp);

                .c功能添加区

                /** * @brief           链表根据关键字删除所有匹配的节点 * @param           头信息结构体的指针 * @param           关键字 * @param           自定义比较函数  * @return           *      @arg  0:正常 *      @arg  PAR_ERROR:参数错误 *      @arg  FUN_ERROR:函数错误 */int udlist_delete_all_by_key(udlist_t *ud, void *key, cmp_t op_cmp){    int index = 0;    /* 参数检查 */    if (NULL == ud || NULL == key || NULL == op_cmp)    {    #ifdef DEBUG        printf("udlist_delete_all_by_key: Parameter error\n");    #elif defined FILE_DEBUG            #endif        goto ERR0;            } /* end of if (NULL == ud || NULL == key || NULL == op_cmp) */    while (1)    {        /* 获取匹配索引 */        index = get_match_index(ud, key, op_cmp);        if (PAR_ERROR == index || MATCH_FAIL == index)        {            goto ERR1;        } /* end of if (PAR_ERROR == index || MATCH_FAIL == index) */        /* 根据索引删除节点 */        udlist_delete_by_index(ud, index);    } /* end of while (1) */    return 0;ERR0:    return PAR_ERROR;ERR1:    return FUN_ERROR;  }

                使用此功能同时需要添加10、13功能。

                18 链表根据关键字修改所有匹配的节点 - Optional

                .h功能添加区

                /** * @brief           链表根据关键字修改所有匹配节点的数据 * @param           头信息结构体的指针 * @param           修改的数据 * @param           关键字 * @param           自定义比较函数 * @return           *      @arg  0:正常 *      @arg  PAR_ERROR:参数错误 *      @arg  FUN_ERROR:函数错误 */int udlist_modify_all_by_key(udlist_t *ud, void *data, void *key, cmp_t op_cmp);

                .c功能添加区

                /** * @brief           链表根据关键字修改所有匹配节点的数据 * @param           头信息结构体的指针 * @param           修改的数据 * @param           关键字 * @param           自定义比较函数 * @return           *      @arg  0:正常 *      @arg  PAR_ERROR:参数错误 *      @arg  FUN_ERROR:函数错误 */int udlist_modify_all_by_key(udlist_t *ud, void *data, void *key, cmp_t op_cmp){    int index = 0;    /* 参数检查 */    if (NULL == ud || NULL == key || NULL == op_cmp || NULL == data)    {    #ifdef DEBUG        printf("udlist_modify_all_by_key: Parameter error\n");    #elif defined FILE_DEBUG            #endif        goto ERR0;            } /* end of if (NULL == ud || NULL == key || NULL == op_cmp || NULL == data) */    while (1)    {        /* 获取匹配索引 */        index = get_match_index(ud, key, op_cmp);        if (PAR_ERROR == index || MATCH_FAIL == index)        {            goto ERR1;        } /* end of if (PAR_ERROR == index || MATCH_FAIL == index) */        /* 根据索引修改数据 */        udlist_modify_by_index(ud, data, index);    } /* end of while (1) */    return 0;ERR0:    return PAR_ERROR;ERR1:    return FUN_ERROR; }

                使用此功能同时需要添加11、13功能。

                19 链表根据关键字查找所有的索引 - Optional

                .h功能添加区

                /** * @brief           自定义索引销毁函数 * @param           数据域 * @return          0 */int index_destroy(void *data);/** * @brief           自定义索引打印函数 * @param           数据域 * @return          0 */int index_print(void *data);/** * @brief           链表根据关键字查找所有的索引 * @param           头信息结构体的指针 * @param           关键字 * @param           自定义比较函数  * @return          存储索引链表 *      @arg  PAR_ERROR: 参数错误 *      @arg  NULL     : 没有找到匹配索引 */udlist_t *udlist_find_all_index_by_key(udlist_t *ud, void *key, cmp_t op_cmp);

                .c功能添加区

                /** * @brief           自定义索引销毁函数 * @param           数据域 * @return          0 */int index_destroy(void *data){    free(data);    data = NULL;    return 0;}/** * @brief           自定义索引打印函数 * @param           数据域 * @return          0 */int index_print(void *data){    printf("index = %d\n", *(int *)data);    return 0;}/** * @brief           链表根据关键字查找所有的索引 * @param           头信息结构体的指针 * @param           关键字 * @param           自定义比较函数  * @return          存储索引链表 *      @arg  PAR_ERROR: 参数错误 *      @arg  NULL     : 没有找到匹配索引 */udlist_t *udlist_find_all_index_by_key(udlist_t *ud, void *key, cmp_t op_cmp){    udlist_t *index_head = NULL;    node_t *temp = NULL;    int index = 0;    /* 参数检查 */    if (NULL == ud || NULL == key || NULL == op_cmp)    {    #ifdef DEBUG        printf("udlist_find_all_index_by_key: Parameter error\n");    #elif defined FILE_DEBUG            #endif        goto ERR0;            } /* end of if (NULL == ud || NULL == key || NULL == op_cmp) */    /* 判断链表是否存在 */    if (NULL == ud->fstnode_p)    {        goto ERR1;    } /* end of if (NULL == ud->fstnode_p) */    /* 创建存储索引的链表头信息结构体 */    index_head = udlist_create(sizeof(int), index_destroy);    /* 查找索引并插入链表 */    temp = ud->fstnode_p;    index = 0;    do     {        if (MATCH_SUCCESS == op_cmp(temp->data, key))        {            udlist_append(index_head, &index);        } /* end of if (MATCH_SUCCESS == op_cmp(temp->data, key)) */        index++;        temp = temp->next;    }    while (temp != ud->fstnode_p);    /* 判断是否为空链表 */    if (0 == get_count(index_head))    {        head_destroy(&index_head);    } /* end of if (0 == get_count(index_head)) */    return index_head;ERR0:    return (void *)PAR_ERROR;ERR1:    return NULL;}

                使用此功能同时需要添加3功能。

                测试代码添加模块

                1 自定义数据销毁函数 - Necessary

                int node_destroy(void *data){}

                2 自定义数据打印函数 - Necessary

                int data_print(void *data){}

                3 自定义数据比较函数 - Necessary

                int data_compare(void *data, void *key){}

                测试代码分享

                test.c

                #include "uni_doubly_linkedlist.h"#include #include #include int node_destroy(void *data){    free(data);    return 0;}int data_print(void *data){    printf("%d\n", *(int *)data);    return 0;}int data_compare(void *data, void *key){    if (0 == memcmp(data, key, sizeof(int)))    {        return MATCH_SUCCESS;    }    else     {        return MATCH_FAIL;    }}int main(int argc, char **argv){    udlist_t *head = NULL;    udlist_t *arr_index = NULL;    int temp = 0;    // 创建头信息结构体    head = udlist_create(sizeof(int), node_destroy);    // 插入数据    for (temp = 1; temp         // udlist_append(head, &temp);        udlist_prepend(head, &temp);    } /* end of for (temp = 1; temp 整体换成任意名称。Necessary该标签标注的区域是必须阅读或者执行的,否则会导致功能异常。Optional该标签标注的区域的阅读或者执行是可选的,忽略不会导致功能异常。Dependent该标签标注的区域的阅读或者执行是可选的,但是它被某些功能所依赖时则必须添加。

上一篇:怎么在服务器里面获得神兽?

下一篇:国密SM2前端加密解密示例