濮阳微信网站开发,深圳市龙华区民治街道,网站建设必备软件,wordpress溢价主题文章目录 序言单向不循环链表拼图框架搭建 - Necessary功能拼图块1 创建链表头信息结构体 - Necessary2 链表头部插入 - Optional3 链表的遍历 - Optional4 链表的销毁 - Necessary5 链表头信息结构体销毁 - Necessary6 获取链表中节点的个数 - Optional7 链表尾部插入 - Optio… 文章目录 序言单向不循环链表拼图框架搭建 - Necessary功能拼图块1 创建链表头信息结构体 - Necessary2 链表头部插入 - Optional3 链表的遍历 - Optional4 链表的销毁 - Necessary5 链表头信息结构体销毁 - Necessary6 获取链表中节点的个数 - Optional7 链表尾部插入 - Optional/Dependent8 链表根据索引插入数据 - Optional9 链表根据索引删除数据 - Optional/Dependent10 链表根据索引修改数据 - Optional/Dependent11 链表根据索引获取数据 - Optional/Dependent12 根据关键字寻找匹配索引 - Optional/Dependent13 链表根据关键字删除数据 - Optional14 链表根据关键字修改数据 - Optional15 链表根据关键字获取数据 - Optional16 链表根据关键字删除所有匹配的节点 - Optional17 链表根据关键字修改所有匹配的节点 - Optional18 链表根据关键字查找所有的索引 - Optional19 链表的翻转 - Optional 测试代码添加模块1 自定义数据销毁函数 - Necessary2 自定义数据打印函数 - Necessary3 自定义数据比较函数 - Necessary 测试代码参考 双向循环链表拼图框架搭建 - Necessary功能拼图块1 创建链表头信息结构体 - Necessary2 链表头部插入 - Optional/Dependent3 链表尾部插入 - Optional/Dependent4 链表的遍历 - Optional5 链表的反向遍历 - Optional6 链表的销毁 - Necessary7 链表头信息结构体销毁 - Necessary8 获取链表中节点的个数 - Optional9 链表根据索引插入数据 - Optional10 链表根据索引删除数据 - Optional/Dependent11 链表根据索引修改数据 - Optional/Dependent12 链表根据索引获取数据 - Optional/Dependent13 根据关键字寻找匹配索引 - Optional/Dependent14 链表根据关键字删除数据 - Optional15 链表根据关键字修改数据 - Optional16 链表根据关键字获取数据 - Optional17 链表根据关键字删除所有匹配的节点 - Optional18 链表根据关键字修改所有匹配的节点 - Optional19 链表根据关键字查找所有的索引 - Optional 测试代码添加模块1 自定义数据销毁函数 - Necessary2 自定义数据打印函数 - Necessary3 自定义数据比较函数 - Necessary 测试代码分享 附录 序言
本链表篇意在制作所有人都可拿来即用的万能型链表懒人拼装手册使用门槛低不需要使用者有很深的语言和数据结构理解使用简单且有参考代码。如使用本手册进行链表的学习也是一种绝佳的体验源码注释丰富且逻辑清晰相信读者可以在轻松愉快的环境下学习掌握。如果全部理解并掌握此手册相信你对于绝大部分链表及数据操作已然不成问题借此打下良好的基础便于日后面对更加复杂的挑战。
万能型链表义如其名可以存储任何数据类型只有你想不到的没有它存不了的但是需要读者注意其使用技巧必要时请参考附录。
在开始前本人在这里借用戴尔·卡耐基的一句话祝各位学习路上可以披荆斩棘乘风破浪一往直前。 多数人都拥有自己不了解的能力和机会都有可能做到未曾梦想的事情。 ——戴尔·卡耐基 单向不循环链表 拼图框架搭建 - Necessary name .h
#ifndef __ name _h__
#define __ name _h__#include stdio.h
#include stdlib.h
#include string.h// 匹配成功
#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 name .c
#include name .h/*** brief 创建节点空间* param 链表头信息结构体指针* return 节点指针*/
static node_t *__node_calloc(uolist_t *uo)
{/* 变量定义 */node_t *p NULL;/* 参数检查 */if (NULL uo){#ifdef DEBUGprintf(__node_calloc: Parameter error\n);#elif defined FILE_DEBUG#endifgoto ERR0; } /* end of if (NULL uo) *//* 创建节点空间 */ p (node_t *)calloc(1, sizeof(node_t));if (NULL p){#ifdef DEBUGprintf(__node_calloc: p calloc error\n);#elif defined FILE_DEBUG#endifgoto ERR1; } /* end of if (NULL p) *//* 创建节点中数据空间 */p-data (void *)calloc(1, uo-size);if (NULL p-data){#ifdef DEBUGprintf(__node_calloc: data calloc error\n);#elif defined FILE_DEBUG#endifgoto 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 0){#ifdef DEBUGprintf(uolist_create: Parameter error\n);#elif defined FILE_DEBUG#endifgoto ERR0;} /* end of if (size 0 || NULL my_destroy) *//* 申请头信息结构体空间 */uo (uolist_t *)calloc(1, sizeof(uolist_t));if (NULL uo){#ifdef DEBUGprintf(uolist_create: calloc error\n);#elif defined FILE_DEBUG#endifgoto 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 DEBUGprintf(uolist_prepend: Parameter error\n);#elif defined FILE_DEBUG#endifgoto 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 DEBUGprintf(uolist_traverse: Parameter error\n);#elif defined FILE_DEBUG#endifgoto 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 DEBUGprintf(uolist_destroy: Parameter error\n);#elif defined FILE_DEBUG#endifgoto 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 DEBUGprintf(head_destroy: Parameter error\n);#elif defined FILE_DEBUG#endifgoto 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 DEBUGprintf(get_count: Parameter error\n);#elif defined FILE_DEBUG#endifgoto 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 DEBUGprintf(uolist_append: Parameter error\n);#elif defined FILE_DEBUG#endifgoto 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 0){#ifdef DEBUGprintf(uolist_insert_by_index: Parameter error\n);#elif defined FILE_DEBUG#endifgoto ERR0; } /* end of if (NULL uo || NULL data || index 0) *//* 1.创建一个新的节点 */temp1 __node_calloc(uo);/* 2.节点数据输入 */temp1-next NULL;memcpy(temp1-data, data, uo-size);/* 3.判断索引 */temp2 uo-fstnode_p;if (index uo-count index 0){// 寻找索引位置for (i 0; i index - 1; i){temp2 temp2-next;} /* end of for (i 0; i index; i) */// 保存索引位置的链表save temp2-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 0 || index uo-count){#ifdef DEBUGprintf(uolist_delete_by_index: Parameter error\n);#elif defined FILE_DEBUG#endifgoto ERR0; } /* end of if (NULL uo || index 0 || 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 index - 1; i){temp1 temp1-next;} /* end of for (i 0; i index - 1; i) */temp2 temp1-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 0 || index uo-count || NULL data){#ifdef DEBUGprintf(uolist_modify_by_index: Parameter error\n);#elif defined FILE_DEBUG#endifgoto ERR0; } /* end of if (NULL uo || index 0 || index uo-count || NULL data) *//* 寻找索引位置 */temp uo-fstnode_p;for (i 0; i index; i){temp temp-next;} /* end of for (i 0; i index; i) *//* 修改数据 */memcpy(temp-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 0 || index uo-count || NULL data){#ifdef DEBUGprintf(uolist_retrieve_by_index: Parameter error\n);#elif defined FILE_DEBUG#endifgoto ERR0; } /* end of if (NULL uo || index 0 || index uo-count || NULL data) *//* 寻找索引位置 */temp uo-fstnode_p;for (i 0; i index; i){temp temp-next;} /* end of for (i 0; i index; i) *//* 修改数据 */memcpy(data, temp-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 DEBUGprintf(get_match_index: Parameter error\n);#elif defined FILE_DEBUG#endifgoto 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 DEBUGprintf(uolist_delete_by_key: Parameter error\n);#elif defined FILE_DEBUG#endifgoto 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 DEBUGprintf(uolist_modify_by_key: Parameter error\n);#elif defined FILE_DEBUG#endifgoto 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 DEBUGprintf(uolist_retrieve_by_key: Parameter error\n);#elif defined FILE_DEBUG#endifgoto 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 DEBUGprintf(uolist_delete_all_by_key: Parameter error\n);#elif defined FILE_DEBUG#endifgoto 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 DEBUGprintf(uolist_modify_all_by_key: Parameter error\n);#elif defined FILE_DEBUG#endifgoto 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 DEBUGprintf(uolist_find_all_index_by_key: Parameter error\n);#elif defined FILE_DEBUG#endifgoto 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 DEBUGprintf(uolist_reverse: Parameter error\n);#elif defined FILE_DEBUG#endifgoto 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 stdio.h
#include name .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 10; 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个5temp 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;
}双向循环链表 拼图框架搭建 - Necessary name .h
#ifndef __ name _h__
#define __ name _h__#include stdio.h
#include stdlib.h
#include string.h// 匹配成功
#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 name .c
#include name .h/*** brief 创建节点空间* param 链表头信息结构体指针* return 节点指针*/
static node_t *__node_calloc(udlist_t *ud)
{/* 变量定义 */node_t *p NULL;/* 参数检查 */if (NULL ud){#ifdef DEBUGprintf(__node_calloc: Parameter error\n);#elif defined FILE_DEBUG#endifgoto ERR0; } /* end of if (NULL ud) *//* 创建节点空间 */ p (node_t *)calloc(1, sizeof(node_t));if (NULL p){#ifdef DEBUGprintf(__node_calloc: p calloc error\n);#elif defined FILE_DEBUG#endifgoto ERR1; } /* end of if (NULL p) *//* 创建节点中数据空间 */p-data (void *)calloc(1, ud-size);if (NULL p-data){#ifdef DEBUGprintf(__node_calloc: data calloc error\n);#elif defined FILE_DEBUG#endifgoto 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 0 || NULL my_destroy){#ifdef DEBUGprintf(udlist_create: Parameter error\n);#elif defined FILE_DEBUG#endifgoto ERR0;} /* end of if (size 0 || NULL my_destroy) *//* 申请头信息结构体空间 */ud (udlist_t *)calloc(1, sizeof(udlist_t));if (NULL ud){#ifdef DEBUGprintf(udlist_create: calloc error\n);#elif defined FILE_DEBUG#endifgoto 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 DEBUGprintf(udlist_append: Parameter error\n);#elif defined FILE_DEBUG#endifgoto 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 DEBUGprintf(udlist_traverse: Parameter error\n);#elif defined FILE_DEBUG#endifgoto 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 DEBUGprintf(udlist_traverse_back: Parameter error\n);#elif defined FILE_DEBUG#endifgoto 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 DEBUGprintf(udlist_destroy: Parameter error\n);#elif defined FILE_DEBUG#endifgoto 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 DEBUGprintf(head_destroy: Parameter error\n);#elif defined FILE_DEBUG#endifgoto 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 DEBUGprintf(get_count: Parameter error\n);#elif defined FILE_DEBUG#endifgoto 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 0){#ifdef DEBUGprintf(udlist_insert_by_index: Parameter error\n);#elif defined FILE_DEBUG#endifgoto ERR0; } /* end of if (NULL ud || NULL data || index 0) *//* 判断索引 */temp2 ud-fstnode_p;if (index ud-count index 0){// 创建一个新的节点 temp1 __node_calloc(ud);// 节点数据输入 temp1-next temp1;temp1-prev temp1;memcpy(temp1-data, data, ud-size);// 寻找索引位置for (i 0; i index - 1; i){temp2 temp2-next;} /* end of for (i 0; i index; i) */// 保存索引位置的链表save temp2-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 0 || index ud-count){#ifdef DEBUGprintf(udlist_delete_by_index: Parameter error\n);#elif defined FILE_DEBUG#endifgoto ERR0; } /* end of if (NULL ud || index 0 || 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 index - 1; i){temp1 temp1-next;} /* end of for (i 0; i index - 1; i) */temp2 temp1-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 0 || index ud-count || NULL data){#ifdef DEBUGprintf(udlist_modify_by_index: Parameter error\n);#elif defined FILE_DEBUG#endifgoto ERR0; } /* end of if (NULL ud || index 0 || index ud-count || NULL data) *//* 寻找索引位置 */temp ud-fstnode_p;for (i 0; i index; i){temp temp-next;} /* end of for (i 0; i index; i) *//* 修改数据 */memcpy(temp-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 0 || index ud-count || NULL data){#ifdef DEBUGprintf(udlist_retrieve_by_index: Parameter error\n);#elif defined FILE_DEBUG#endifgoto ERR0; } /* end of if (NULL ud || index 0 || index ud-count || NULL data) *//* 寻找索引位置 */temp ud-fstnode_p;for (i 0; i index; i){temp temp-next;} /* end of for (i 0; i index; i) *//* 修改数据 */memcpy(data, temp-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 DEBUGprintf(get_match_index: Parameter error\n);#elif defined FILE_DEBUG#endifgoto 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 DEBUGprintf(udlist_delete_by_key: Parameter error\n);#elif defined FILE_DEBUG#endifgoto 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 DEBUGprintf(udlist_modify_by_key: Parameter error\n);#elif defined FILE_DEBUG#endifgoto 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 DEBUGprintf(udlist_retrieve_by_key: Parameter error\n);#elif defined FILE_DEBUG#endifgoto 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 DEBUGprintf(udlist_delete_all_by_key: Parameter error\n);#elif defined FILE_DEBUG#endifgoto 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 DEBUGprintf(udlist_modify_all_by_key: Parameter error\n);#elif defined FILE_DEBUG#endifgoto 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 DEBUGprintf(udlist_find_all_index_by_key: Parameter error\n);#elif defined FILE_DEBUG#endifgoto 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 stdio.h
#include stdlib.h
#include string.hint 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 10; temp){// udlist_append(head, temp);udlist_prepend(head, temp);} /* end of for (temp 1; temp 10; temp) */// 遍历输出udlist_traverse(head, data_print);udlist_traverse_back(head, data_print);printf(cnt: %d\n, get_count(head));printf(\n);// 按照索引插入temp 888;udlist_insert_by_index(head, temp, 0);// 输出printf(cnt: %d\n, get_count(head));udlist_traverse(head, data_print);printf(\n);// 按照索引插入temp 9090;udlist_insert_by_index(head, temp, 200);// 输出printf(cnt: %d\n, get_count(head));udlist_traverse(head, data_print);printf(\n);// 按照索引插入temp 77;udlist_insert_by_index(head, temp, 7);// 输出printf(cnt: %d\n, get_count(head));udlist_traverse(head, data_print);printf(\n);// 链表根据索引删除udlist_delete_by_index(head, 3);// 输出printf(cnt: %d\n, get_count(head));udlist_traverse(head, data_print);printf(\n);// 链表根据索引修改temp 100;udlist_modify_by_index(head, temp, 0);// 输出printf(cnt: %d\n, get_count(head));udlist_traverse(head, data_print);printf(\n);// 链表根据索引获取udlist_retrieve_by_index(head, temp, 5);// 输出printf(temp: %d\n, temp);printf(cnt: %d\n, get_count(head));udlist_traverse(head, data_print);printf(\n);// 链表根据关键字删除int key 100;udlist_delete_by_key(head, key, data_compare);// 输出printf(cnt: %d\n, get_count(head));udlist_traverse(head, data_print);printf(\n);// 链表根据关键字修改temp 3;key 10;udlist_modify_by_key(head, temp, key, data_compare);// 输出printf(cnt: %d\n, get_count(head));udlist_traverse(head, data_print);printf(\n);// 链表根据关键字获取temp 85;key 4;udlist_retrieve_by_key(head, temp, key, data_compare);// 输出printf(temp: %d\n, temp);printf(cnt: %d\n, get_count(head));udlist_traverse(head, data_print);printf(\n);// 链表根据关键字修改所有temp 9;key 3;// udlist_delete_all_by_key(head, key, data_compare);udlist_modify_all_by_key(head, temp, key, data_compare);// 输出printf(cnt: %d\n, get_count(head));udlist_traverse(head, data_print);printf(\n);// 链表根据关键字查找所有索引key 9;arr_index udlist_find_all_index_by_key(head, key, data_compare);// 输出printf(cnt: %d\n, get_count(arr_index));udlist_traverse(arr_index, index_print);printf(\n);// 释放udlist_destroy(head);head_destroy(head);udlist_destroy(arr_index);head_destroy(arr_index);return 0;
}附录
符号注解 name 将 name 整体换成任意名称。Necessary该标签标注的区域是必须阅读或者执行的否则会导致功能异常。Optional该标签标注的区域的阅读或者执行是可选的忽略不会导致功能异常。Dependent该标签标注的区域的阅读或者执行是可选的但是它被某些功能所依赖时则必须添加。