文章目录
- 序言
- 单向不循环链表
-
- [拼图框架搭建 - `Necessary`](#拼图框架搭建 -
Necessary
) - 功能拼图块
-
- [1 创建链表头信息结构体 - `Necessary`](#1 创建链表头信息结构体 -
Necessary
) - [2 链表头部插入 - `Optional`](#2 链表头部插入 -
Optional
) - [3 链表的遍历 - `Optional`](#3 链表的遍历 -
Optional
) - [4 链表的销毁 - `Necessary`](#4 链表的销毁 -
Necessary
) - [5 链表头信息结构体销毁 - `Necessary`](#5 链表头信息结构体销毁 -
Necessary
) - [6 获取链表中节点的个数 - `Optional`](#6 获取链表中节点的个数 -
Optional
) - [7 链表尾部插入 - `Optional`/`Dependent`](#7 链表尾部插入 -
Optional
/Dependent
) - [8 链表根据索引插入数据 - `Optional`](#8 链表根据索引插入数据 -
Optional
) - [9 链表根据索引删除数据 - `Optional`/`Dependent`](#9 链表根据索引删除数据 -
Optional
/Dependent
) - [10 链表根据索引修改数据 - `Optional`/`Dependent`](#10 链表根据索引修改数据 -
Optional
/Dependent
) - [11 链表根据索引获取数据 - `Optional`/`Dependent`](#11 链表根据索引获取数据 -
Optional
/Dependent
) - [12 根据关键字寻找匹配索引 - `Optional`/`Dependent`](#12 根据关键字寻找匹配索引 -
Optional
/Dependent
) - [13 链表根据关键字删除数据 - `Optional`](#13 链表根据关键字删除数据 -
Optional
) - [14 链表根据关键字修改数据 - `Optional`](#14 链表根据关键字修改数据 -
Optional
) - [15 链表根据关键字获取数据 - `Optional`](#15 链表根据关键字获取数据 -
Optional
) - [16 链表根据关键字删除所有匹配的节点 - `Optional`](#16 链表根据关键字删除所有匹配的节点 -
Optional
) - [17 链表根据关键字修改所有匹配的节点 - `Optional`](#17 链表根据关键字修改所有匹配的节点 -
Optional
) - [18 链表根据关键字查找所有的索引 - `Optional`](#18 链表根据关键字查找所有的索引 -
Optional
) - [19 链表的翻转 - `Optional`](#19 链表的翻转 -
Optional
)
- [1 创建链表头信息结构体 - `Necessary`](#1 创建链表头信息结构体 -
- 测试代码添加模块
-
- [1 自定义数据销毁函数 - `Necessary`](#1 自定义数据销毁函数 -
Necessary
) - [2 自定义数据打印函数 - `Necessary`](#2 自定义数据打印函数 -
Necessary
) - [3 自定义数据比较函数 - `Necessary`](#3 自定义数据比较函数 -
Necessary
)
- [1 自定义数据销毁函数 - `Necessary`](#1 自定义数据销毁函数 -
- 测试代码参考
- [拼图框架搭建 - `Necessary`](#拼图框架搭建 -
- 双向循环链表
-
- [拼图框架搭建 - `Necessary`](#拼图框架搭建 -
Necessary
) - 功能拼图块
-
- [1 创建链表头信息结构体 - `Necessary`](#1 创建链表头信息结构体 -
Necessary
) - [2 链表头部插入 - `Optional`/`Dependent`](#2 链表头部插入 -
Optional
/Dependent
) - [3 链表尾部插入 - `Optional`/`Dependent`](#3 链表尾部插入 -
Optional
/Dependent
) - [4 链表的遍历 - `Optional`](#4 链表的遍历 -
Optional
) - [5 链表的反向遍历 - `Optional`](#5 链表的反向遍历 -
Optional
) - [6 链表的销毁 - `Necessary`](#6 链表的销毁 -
Necessary
) - [7 链表头信息结构体销毁 - `Necessary`](#7 链表头信息结构体销毁 -
Necessary
) - [8 获取链表中节点的个数 - `Optional`](#8 获取链表中节点的个数 -
Optional
) - [9 链表根据索引插入数据 - `Optional`](#9 链表根据索引插入数据 -
Optional
) - [10 链表根据索引删除数据 - `Optional`/`Dependent`](#10 链表根据索引删除数据 -
Optional
/Dependent
) - [11 链表根据索引修改数据 - `Optional`/`Dependent`](#11 链表根据索引修改数据 -
Optional
/Dependent
) - [12 链表根据索引获取数据 - `Optional`/`Dependent`](#12 链表根据索引获取数据 -
Optional
/Dependent
) - [13 根据关键字寻找匹配索引 - `Optional`/`Dependent`](#13 根据关键字寻找匹配索引 -
Optional
/Dependent
) - [14 链表根据关键字删除数据 - `Optional`](#14 链表根据关键字删除数据 -
Optional
) - [15 链表根据关键字修改数据 - `Optional`](#15 链表根据关键字修改数据 -
Optional
) - [16 链表根据关键字获取数据 - `Optional`](#16 链表根据关键字获取数据 -
Optional
) - [17 链表根据关键字删除所有匹配的节点 - `Optional`](#17 链表根据关键字删除所有匹配的节点 -
Optional
) - [18 链表根据关键字修改所有匹配的节点 - `Optional`](#18 链表根据关键字修改所有匹配的节点 -
Optional
) - [19 链表根据关键字查找所有的索引 - `Optional`](#19 链表根据关键字查找所有的索引 -
Optional
)
- [1 创建链表头信息结构体 - `Necessary`](#1 创建链表头信息结构体 -
- 测试代码添加模块
-
- [1 自定义数据销毁函数 - `Necessary`](#1 自定义数据销毁函数 -
Necessary
) - [2 自定义数据打印函数 - `Necessary`](#2 自定义数据打印函数 -
Necessary
) - [3 自定义数据比较函数 - `Necessary`](#3 自定义数据比较函数 -
Necessary
)
- [1 自定义数据销毁函数 - `Necessary`](#1 自定义数据销毁函数 -
- 测试代码分享
- [拼图框架搭建 - `Necessary`](#拼图框架搭建 -
- 附录
序言
本链表篇意在制作所有人都可拿来即用的万能型链表懒人拼装手册,使用门槛低,不需要使用者有很深的语言和数据结构理解,使用简单且有参考代码。如使用本手册进行链表的学习也是一种绝佳的体验,源码注释丰富且逻辑清晰,相信读者可以在轻松愉快的环境下学习掌握。如果全部理解并掌握此手册,相信你对于绝大部分链表及数据操作已然不成问题,借此打下良好的基础便于日后面对更加复杂的挑战。
万能型链表义如其名,可以存储任何数据类型,只有你想不到的,没有它存不了的,但是需要读者注意其使用技巧(必要时请参考附录)。
在开始前,本人在这里借用戴尔·卡耐基的一句话祝各位学习路上可以披荆斩棘,乘风破浪,一往直前。
多数人都拥有自己不了解的能力和机会,都有可能做到未曾梦想的事情。
------戴尔·卡耐基
单向不循环链表
拼图框架搭建 - Necessary
< name >.h
c
#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
c
#include "< name >.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
功能添加区
c
/**
* @brief 创建链表头信息结构体
* @param 存储数据类型大小
* @param 自定义销毁数据函数
* @return 指向链表头信息结构体的指针
*/
uolist_t *uolist_create(int size, op_t my_destroy);
.c
功能添加区
c
/**
* @brief 创建链表头信息结构体
* @param 存储数据类型大小
* @param 自定义销毁数据函数
* @return 指向链表头信息结构体的指针
*/
uolist_t *uolist_create(int size, op_t my_destroy)
{
/* 变量定义 */
uolist_t *uo = NULL;
/* 参数检查 */
if (size <= 0)
{
#ifdef DEBUG
printf("uolist_create: Parameter error\n");
#elif defined FILE_DEBUG
#endif
goto ERR0;
} /* end of if (size <= 0 || NULL == my_destroy) */
/* 申请头信息结构体空间 */
uo = (uolist_t *)calloc(1, sizeof(uolist_t));
if (NULL == uo)
{
#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
功能添加区
c
/**
* @brief 链表头部插入
* @param 头信息结构体的指针
* @param 插入节点数据
* @return
* @arg 0:正常
* @arg PAR_ERROR:参数错误
* @arg FUN_ERROR:函数错误
*/
int uolist_prepend(uolist_t *uo, void *data);
.c
功能添加区
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
功能添加区
c
/**
* @brief 链表的遍历
* @param 头信息结构体的指针
* @param 自定义打印数据函数
* @return
* @arg 0:正常
* @arg PAR_ERROR:参数错误
* @arg FUN_ERROR:函数错误
*/
int uolist_traverse(uolist_t *uo, op_t my_print);
.c
功能添加区
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
功能添加区
c
/**
* @brief 链表销毁函数(不包括头信息结构体)
* @param 头信息结构体的指针
* @return
* @arg 0:正常
* @arg PAR_ERROR:参数错误
* @arg FUN_ERROR:函数错误
*/
int uolist_destroy(uolist_t *uo);
.c
功能添加区
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
功能添加区
c
/**
* @brief 头信息结构体销毁函数
* @param 头信息结构体的指针的地址
* @return
* @arg 0:正常
* @arg PAR_ERROR:参数错误
* @arg FUN_ERROR:函数错误
*/
int head_destroy(uolist_t **p);
.c
功能添加区
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
功能添加区
c
/**
* @brief 获取链表中节点的个数
* @param 头信息结构体的指针
* @return 链表节点个数
*/
int get_count(uolist_t *p);
.c
功能添加区
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
功能添加区
c
/**
* @brief 链表尾部插入
* @param 头信息结构体的指针
* @param 数据的指针
* @return
* @arg 0:正常
* @arg PAR_ERROR:参数错误
* @arg FUN_ERROR:函数错误
*/
int uolist_append(uolist_t *uo, void *data);
.c
功能添加区
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
功能添加区
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);
.c
功能添加区
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 DEBUG
printf("uolist_insert_by_index: Parameter error\n");
#elif defined FILE_DEBUG
#endif
goto 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
功能添加区
c
/**
* @brief 链表根据索引删除
* @param 头信息结构体的指针
* @param 索引值
* @return
* @arg 0:正常
* @arg PAR_ERROR:参数错误
* @arg FUN_ERROR:函数错误
*/
int uolist_delete_by_index(uolist_t *uo, int index);
.c
功能添加区
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 DEBUG
printf("uolist_delete_by_index: Parameter error\n");
#elif defined FILE_DEBUG
#endif
goto 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
功能添加区
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);
.c
功能添加区
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 DEBUG
printf("uolist_modify_by_index: Parameter error\n");
#elif defined FILE_DEBUG
#endif
goto 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
功能添加区
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);
.c
功能添加区
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 DEBUG
printf("uolist_retrieve_by_index: Parameter error\n");
#elif defined FILE_DEBUG
#endif
goto 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
功能添加区
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);
.c
功能添加区
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
功能添加区
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);
.c
功能添加区
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
功能添加区
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);
.c
功能添加区
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
功能添加区
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);
.c
功能添加区
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
功能添加区
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);
.c
功能添加区
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
功能添加区
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);
.c
功能添加区
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
功能添加区
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);
/**
* @brief 自定义索引销毁函数
* @param 数据域
* @return 0
*/
int index_destroy(void *data);
/**
* @brief 自定义索引打印函数
* @param 数据域
* @return 0
*/
int index_print(void *data);
.c
功能添加区
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
功能添加区
c
/**
* @brief 链表的翻转
* @param 头信息结构体的指针
* @return
* @arg PAR_ERROR: 参数错误
* @arg 0 : 正常
*/
int uolist_reverse(uolist_t *uo);
.c
功能添加区
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
c
int node_destroy(void *data){}
2 自定义数据打印函数 - Necessary
c
int data_print(void *data){}
3 自定义数据比较函数 - Necessary
c
int data_compare(void *data, void *key){}
测试代码参考
test.c
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个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;
}
双向循环链表
拼图框架搭建 - Necessary
< name >.h
c
#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
c
#include "< name >.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
功能添加区
c
/**
* @brief 创建链表头信息结构体
* @param 存储数据类型大小
* @param 自定义销毁数据函数
* @return 指向链表头信息结构体的指针
*/
udlist_t *udlist_create(int size, op_t my_destroy);
.c
功能添加区
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 DEBUG
printf("udlist_create: Parameter error\n");
#elif defined FILE_DEBUG
#endif
goto ERR0;
} /* end of if (size <= 0 || NULL == my_destroy) */
/* 申请头信息结构体空间 */
ud = (udlist_t *)calloc(1, sizeof(udlist_t));
if (NULL == ud)
{
#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
功能添加区
c
/**
* @brief 链表头部插入
* @param 头信息结构体的指针
* @param 插入节点数据
* @return
* @arg 0:正常
* @arg PAR_ERROR:参数错误
* @arg FUN_ERROR:函数错误
*/
int udlist_prepend(udlist_t *ud, void *data);
.c
功能添加区
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
功能添加区
c
/**
* @brief 链表尾部插入
* @param 头信息结构体的指针
* @param 数据的指针
* @return
* @arg 0:正常
* @arg PAR_ERROR:参数错误
* @arg FUN_ERROR:函数错误
*/
int udlist_append(udlist_t *ud, void *data);
.c
功能添加区
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
功能添加区
c
/**
* @brief 链表的遍历
* @param 头信息结构体的指针
* @param 自定义打印数据函数
* @return
* @arg 0:正常
* @arg PAR_ERROR:参数错误
* @arg FUN_ERROR:函数错误
*/
int udlist_traverse(udlist_t *ud, op_t my_print);
.c
功能添加区
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
功能添加区
c
/**
* @brief 链表的反向遍历
* @param 头信息结构体的指针
* @param 自定义打印数据函数
* @return
* @arg 0:正常
* @arg PAR_ERROR:参数错误
* @arg FUN_ERROR:函数错误
*/
int udlist_traverse_back(udlist_t *ud, op_t my_print);
.c
功能添加区
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
功能添加区
c
/**
* @brief 链表销毁函数(不包括头信息结构体)
* @param 头信息结构体的指针
* @return
* @arg 0:正常
* @arg PAR_ERROR:参数错误
* @arg FUN_ERROR:函数错误
*/
int udlist_destroy(udlist_t *ud);
.c
功能添加区
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
功能添加区
c
/**
* @brief 头信息结构体销毁函数
* @param 头信息结构体的指针的地址
* @return
* @arg 0:正常
* @arg PAR_ERROR:参数错误
* @arg FUN_ERROR:函数错误
*/
int head_destroy(udlist_t **p);
.c
功能添加区
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
功能添加区
c
/**
* @brief 获取链表中节点的个数
* @param 头信息结构体的指针
* @return 链表节点个数
*/
int get_count(udlist_t *p);
.c
功能添加区
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
功能添加区
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);
.c
功能添加区
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 DEBUG
printf("udlist_insert_by_index: Parameter error\n");
#elif defined FILE_DEBUG
#endif
goto 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
功能添加区
c
/**
* @brief 链表根据索引删除
* @param 头信息结构体的指针
* @param 索引值
* @return
* @arg 0:正常
* @arg PAR_ERROR:参数错误
* @arg FUN_ERROR:函数错误
*/
int udlist_delete_by_index(udlist_t *ud, int index);
.c
功能添加区
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 DEBUG
printf("udlist_delete_by_index: Parameter error\n");
#elif defined FILE_DEBUG
#endif
goto 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
功能添加区
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);
.c
功能添加区
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 DEBUG
printf("udlist_modify_by_index: Parameter error\n");
#elif defined FILE_DEBUG
#endif
goto 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
功能添加区
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);
.c
功能添加区
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 DEBUG
printf("udlist_retrieve_by_index: Parameter error\n");
#elif defined FILE_DEBUG
#endif
goto 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
功能添加区
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);
.c
功能添加区
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
功能添加区
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);
.c
功能添加区
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
功能添加区
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);
.c
功能添加区
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
功能添加区
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);
.c
功能添加区
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
功能添加区
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);
.c
功能添加区
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
功能添加区
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);
.c
功能添加区
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
功能添加区
c
/**
* @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
功能添加区
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
c
int node_destroy(void *data){}
2 自定义数据打印函数 - Necessary
c
int data_print(void *data){}
3 自定义数据比较函数 - Necessary
c
int data_compare(void *data, void *key){}
测试代码分享
test.c
c
#include "uni_doubly_linkedlist.h"
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
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 <= 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 |
该标签标注的区域的阅读或者执行是可选的,但是它被某些功能所依赖时则必须添加。 |