From ef79633f1ae75efa69c27acb68e72e83a9e36cbe Mon Sep 17 00:00:00 2001 From: JiXieShi Date: Fri, 21 Jun 2024 13:25:01 +0800 Subject: [PATCH] UP --- demo/list/t_list.h | 10 ++ demo/list/test.c | 103 +++++++++++++++ demo/task/t_task.h | 2 +- lib/inc/list/array.h | 32 +++++ lib/inc/list/list.h | 148 +++++++++++++++++++++ lib/inc/tool.h | 22 +++- lib/src/list/array.cpp | 43 +++++++ lib/src/list/list.cpp | 285 +++++++++++++++++++++++++++++++++++++++++ main.c | 12 +- 9 files changed, 650 insertions(+), 7 deletions(-) create mode 100644 demo/list/t_list.h create mode 100644 demo/list/test.c create mode 100644 lib/inc/list/array.h create mode 100644 lib/inc/list/list.h create mode 100644 lib/src/list/array.cpp create mode 100644 lib/src/list/list.cpp diff --git a/demo/list/t_list.h b/demo/list/t_list.h new file mode 100644 index 0000000..cfaf640 --- /dev/null +++ b/demo/list/t_list.h @@ -0,0 +1,10 @@ +// +// Created by lydxh on 24-6-21. +// + +#ifndef HW_LIB_T_LIST_H +#define HW_LIB_T_LIST_H + +extern void Test_List(); + +#endif //HW_LIB_T_LIST_H diff --git a/demo/list/test.c b/demo/list/test.c new file mode 100644 index 0000000..fb90660 --- /dev/null +++ b/demo/list/test.c @@ -0,0 +1,103 @@ + +#include + +#include "list.h" + +typedef struct test { + int val1; + float val2; +} test_t; + +void handle(void *data) { + test_t *test = (test_t *) data; + printf("val1:%d, val2:%f\n", test->val1, test->val2); +} + +int compare_int(const void *s1, const void *s2) { + test_t *data1 = (test_t *) s1; + int *data2 = (int *) s2; + + return (data1->val1 - *data2); +} + +int compare_int_sort(const void *s1, const void *s2) { + test_t *data1 = (test_t *) s1; + test_t *data2 = (test_t *) s2; + + return (data1->val1 - data2->val1); +} + +void print(List *list) { + printf("list len = %ld\n", list_get_lenth(list)); + if (!list_is_empty(list)) { + //test list_reverse + list_traverse(list, handle); + } else { + printf("\tthe list is empty\n"); + } +} + +void Test_List() { + List list; + list_init(&list); + test_t test1 = {10, 10.5}; + test_t test2 = {20, 20.5}; + test_t test3 = {30, 30.5}; + test_t test4 = {40, 40.5}; + test_t test5 = {50, 50.5}; + + //test list_insert + printf("------insert(_at_tail)----\n"); + list_insert(&list, &test1); + list_insert(&list, &test2); + list_insert(&list, &test3); + print(&list); + + //test list_delete + printf("------delete----\n"); + list_delete(&list, &test1.val1, compare_int); + print(&list); + + //test list_insert_at_head + printf("------insert_at_head----\n"); + list_insert_at_head(&list, &test4); + print(&list); + + //test list_insert_at_index + printf("------insert_at_index(2)----\n"); + list_insert_at_index(&list, &test5, 2); + print(&list); + + //test list_reverse + printf("------reverse----\n"); + list_reverse(&list); + print(&list); + + //test list_search + int key = 20; + test_t *ret; + printf("------search----\n"); + ret = list_search(&list, &key, compare_int); + printf("%d:%f\n", ret->val1, ret->val2); + key = 50; + ret = list_search(&list, &key, compare_int); + printf("%d:%f\n", ret->val1, ret->val2); + + //test list_get_element + printf("------list_get_element----\n"); + ret = list_get_element(&list, 2); + printf("%d:%f\n", ret->val1, ret->val2); + ret = list_get_element(&list, 3); + printf("%d:%f\n", ret->val1, ret->val2); + + //test list_sort + printf("-----sort----\n"); + list_sort(&list, compare_int_sort); + print(&list); + + //test list_destroy + printf("-----destroy----\n"); + list_destroy(&list, NULL); + + return 0; +} \ No newline at end of file diff --git a/demo/task/t_task.h b/demo/task/t_task.h index c827453..2cbc5c6 100644 --- a/demo/task/t_task.h +++ b/demo/task/t_task.h @@ -5,6 +5,6 @@ #ifndef HW_LIB_T_TASK_H #define HW_LIB_T_TASK_H -void Test_task(); +_Noreturn void Test_task(); #endif //HW_LIB_T_TASK_H diff --git a/lib/inc/list/array.h b/lib/inc/list/array.h new file mode 100644 index 0000000..43350ed --- /dev/null +++ b/lib/inc/list/array.h @@ -0,0 +1,32 @@ +#ifndef HW_LIB_ARRAY_H +#define HW_LIB_ARRAY_H +#ifdef __cplusplus +extern "C" { +#endif + +// 在数组的索引 index 处插入元素 num +// nums: 操作数组 +// size: 数组大小 +// num: 操作数 +// index: 操作位置 +void insert(int *nums, int size, int num, int index); + +// 删除索引 index 处的元素 +// nums: 操作数组 +// size: 数组大小 +// index: 索引位置 +// 注意:stdio.h 占用了 remove 关键词 +void removeItem(int *nums, int size, int index); + +// 在数组中查找指定元素 +// nums: 操作数组 +// size: 数组大小 +// target: 查找元素 +int find(int *nums, int size, int target); + +/* 扩展数组长度 */ +int *extend(int *nums, int size, int enlarge); +#ifdef __cplusplus +} +#endif +#endif //HW_LIB_ARRAY_H diff --git a/lib/inc/list/list.h b/lib/inc/list/list.h new file mode 100644 index 0000000..6d7f234 --- /dev/null +++ b/lib/inc/list/list.h @@ -0,0 +1,148 @@ +#ifndef HW_LIB_LIST_H +#define HW_LIB_LIST_H +#ifdef __cplusplus +extern "C" { +#endif + +#include + +typedef struct node { //节点结构 + void *data; + struct node *next; +} node; + +typedef struct { //链表结构 + struct node *head; + struct node *tail; + long len; +} List; + +/** + * @brief 初始化链表 + * @param list: [输入] 链表指针 + * @return void + * @example list_init(&myList); + */ +extern void list_init(List *list); + +/** + * @brief 检查链表是否为空 + * @param list: [输入] 链表指针 + * @return bool 若链表为空返回true,否则返回false + * @example if (list_is_empty(&myList)) { // do something } + */ +extern bool list_is_empty(List *list); + +/** + * @brief 在链表尾部插入元素 + * @param list: [输入] 链表指针 + * @param data: [输入] 待插入的数据指针 + * @return void + * @example list_insert(&myList, newData); + */ +extern void list_insert(List *list, void *data); + +/** + * @brief 在链表头部插入元素 + * @param list: [输入] 链表指针 + * @param data: [输入] 待插入的数据指针 + * @return void + * @example list_insert_at_head(&myList, newData); + */ +extern void list_insert_at_head(List *list, void *data); + +/** + * @brief 在链表尾部插入元素 + * @param list: [输入] 链表指针 + * @param data: [输入] 待插入的数据指针 + * @return void + * @example list_insert_at_tail(&myList, newData); + */ +extern void list_insert_at_tail(List *list, void *data); + +/** + * @brief 在指定位置插入元素 + * @param list: [输入] 链表指针 + * @param data: [输入] 待插入的数据指针 + * @param idx: [输入] 插入位置索引 + * @return void + * @example list_insert_at_index(&myList, newData, 2); + */ +extern void list_insert_at_index(List *list, void *data, long idx); + +/** + * @brief 删除链表中指定元素 + * @param list: [输入] 链表指针 + * @param key: [输入] 待删除的数据指针 + * @param compare: [输入] 比较函数指针 + * @return void* 返回被删除元素的数据,若未找到返回NULL + * @example deletedData = list_delete(&myList, keyData, compareFunc); + */ +extern void *list_delete(List *list, void *key, int (*compare)(const void *, const void *)); + +/** + * @brief 在链表中查找指定元素 + * @param list: [输入] 链表指针 + * @param key: [输入] 待查找的数据指针 + * @param compare: [输入] 比较函数指针 + * @return void* 返回找到的元素的数据,若未找到返回NULL + * @example foundData = list_search(&myList, keyData, compareFunc); + */ +extern void *list_search(List *list, void *key, int (*compare)(const void *, const void *)); + +/** + * @brief 对链表进行排序 + * @param list: [输入] 链表指针 + * @param compare: [输入] 比较函数指针 + * @return void + * @example list_sort(&myList, compareFunc); + */ +extern void list_sort(List *list, int (*compare)(const void *, const void *)); + +/** + * @brief 遍历链表并对每个元素执行指定操作 + * @param list: [输入] 链表指针 + * @param handle: [输入] 处理函数指针 + * @return void + * @example list_traverse(&myList, handleFunc); + */ +extern void list_traverse(List *list, void (*handle)(void *)); + +/** + * @brief 反转链表 + * @param list: [输入] 链表指针 + * @return void + * @example list_reverse(&myList); + */ +extern void list_reverse(List *list); + +/** + * @brief 获取链表长度 + * @param list: [输入] 链表指针 + * @return long 返回链表中元素个数 + * @example length = list_get_lenth(&myList); + */ +extern long list_get_lenth(List *list); + +/** + * @brief 获取链表指定位置的元素 + * @param list: [输入] 链表指针 + * @param idx: [输入] 元素索引 + * @return void* 返回指定位置的元素指针,若索引无效返回NULL + * @example element = list_get_element(&myList, 3); + */ +extern void *list_get_element(List *list, int idx); + +/** + * @brief 销毁链表 + * @param list: [输入] 链表指针 + * @param destroy: [输入] 数据销毁函数指针 + * @return void + * @example list_destroy(&myList, destroyFunc); + */ +extern void list_destroy(List *list, void (*destroy)(void *data)); + +#ifdef __cplusplus +} +#endif +#endif //HW_LIB_LIST_H diff --git a/lib/inc/tool.h b/lib/inc/tool.h index ca0ba68..2b51cc5 100644 --- a/lib/inc/tool.h +++ b/lib/inc/tool.h @@ -44,9 +44,29 @@ typedef enum { // 定义枚举类型Type_t,包含不同数据类型 #define TYPE_T(v) _Generic((v), \ u8 *:0,u16 *:1,u32 *:2, \ char *:3,short *:4,int *:5, \ - float *:6,double *:10, \ + float *:6,double *:7, \ default: ((void)0)) +#define MESSAGE(err) \ + ( err==ERROR_NO_MEMORY ? MSG_NO_MEMORY \ + : err==ERROR_INVALID_INDEX ? MSG_INVALID_INDEX \ + : err==ERROR_INVALID_VALUE ? MSG_INVALID_VALUE \ + : 0 ) + +#define TYPE_U8 (unsigned char *) + +#define TYPE_ptr(type) \ + (type==0 ? TYPE_U8 \ + : type==1 ? (unsigned short *) \ + : type==2 ? (unsigned int *) \ + : type==3 ? (char *) \ + : type==4 ? (short *) \ + : type==5 ? (int *) \ + : type==6 ? (float *) \ + : type==7 ? (double *) \ + : ((void)0))\ + + #define ARRAY_SIZE(arr) (sizeof(arr) / sizeof(arr[0])) // 计算数组的元素个数 #define in , // 定义逗号为in diff --git a/lib/src/list/array.cpp b/lib/src/list/array.cpp new file mode 100644 index 0000000..f3470b3 --- /dev/null +++ b/lib/src/list/array.cpp @@ -0,0 +1,43 @@ +#include +#include "array.h" + + +void insert(int *nums, int size, int num, int index) { + // 把索引 index 以及之后的所有元素向后移动一位 + for (int i = size - 1; i > index; i--) { + nums[i] = nums[i - 1]; + } + // 将 num 赋给 index 处的元素 + nums[index] = num; +} + +void removeItem(int *nums, int size, int index) { + // 把索引 index 之后的所有元素向前移动一位 + for (int i = index; i < size - 1; i++) { + nums[i] = nums[i + 1]; + } +} + +int find(int *nums, int size, int target) { + for (int i = 0; i < size; i++) { + if (nums[i] == target) + return i; + } + return -1; +} + +/* 扩展数组长度 */ +int *extend(int *nums, int size, int enlarge) { + // 初始化一个扩展长度后的数组 + int *res = (int *) malloc(sizeof(int) * (size + enlarge)); + // 将原数组中的所有元素复制到新数组 + for (int i = 0; i < size; i++) { + res[i] = nums[i]; + } + // 初始化扩展后的空间 + for (int i = size; i < size + enlarge; i++) { + res[i] = 0; + } + // 返回扩展后的新数组 + return res; +} diff --git a/lib/src/list/list.cpp b/lib/src/list/list.cpp new file mode 100644 index 0000000..4b0a22e --- /dev/null +++ b/lib/src/list/list.cpp @@ -0,0 +1,285 @@ +#include +#include +#include + +#include "list.h" + +void list_init(List *list) { + list->head = NULL; + list->tail = NULL; + list->len = 0; +} + +bool list_is_empty(List *list) { + return (list->head == NULL); +} + +static struct node *make_node(void *data) //把用户传递过来的数据打包为一个链表节点 +{ + struct node *n; + + n = (struct node *) malloc(sizeof(struct node)); + assert(n != NULL); + + n->next = NULL; + n->data = data; + + return n; +} + +void list_insert_at_head(List *list, void *data) //头插法 +{ + struct node *n; + n = make_node(data); + + if (list->head == NULL) { //如果是空链表 + list->head = n; + list->tail = n; + } else { //如果不是非空链表 + n->next = list->head; + list->head = n; + } + list->len++; +} + +void list_insert_at_index(List *list, void *data, long index) //定插法 +{ + long i = 1; //从1开始算 + struct node *p, *n; + + p = list->head; + + while (p && i < index) { + p = p->next; + i++; + } + + if (p) { //如果链表遍历完了,计数i还没到index,说明第index个节点不存在。 + n = make_node(data); + n->next = p->next; + p->next = n; + list->len++; + } +} + +void list_insert_at_tail(List *list, void *data) //尾插法 +{ + struct node *n; + n = make_node(data); + + if (list_is_empty(list)) { //如果是空链表 + list->head = n; + list->tail = n; + } else { //如果不是非空链表 + list->tail->next = n; + list->tail = n; + } + list->len++; +} + +//void list_insert(List *list, void *data) //默认采用尾插法 +//{ +//#if 0 +// list_insert_at_tail(list, data); +//#else +// struct node *n; +// n = make_node(data); +// if(list->head == NULL){ +// list->head = n; +// list->tail = n; +// } else { +// list->tail->next = n; +// list->tail = n; +// } +// list->len++; +//#endif +//} + + +void list_insert(List *list, void *data) { + struct node *n; + + n = make_node(data); + + if (list->head == NULL) { + list->head = n; + list->tail = n; + } else { + list->tail->next = n; + list->tail = n; + } + list->len++; +} + +void *list_delete(List *list, void *key, int (*compare)(const void *, const void *)) { + void *data; + struct node *n, *t; + n = list->head; + + if (!compare(n->data, key)) { //如果要删除的节点为首节点 + t = n; + data = n->data; + list->head = n->next; + free(t); + list->len--; + return data; + } + + while (n->next != NULL) { //遍历查找符合条件的节点,删除之 + if (compare(n->next->data, key) == 0) { //只删除第一个符合条件的节点。 + t = n->next; + if (n->next == list->tail) { + list->tail = n; + } + n->next = n->next->next; + data = t->data; + free(t); + list->len--; + return data; //把删除的数据返回给用户,供用户后续的处理使用。 + } + n = n->next; + } + return NULL; //没找到匹配的节点,返回NULL +} + +void *list_search(List *list, void *key, int (*compare)(const void *, const void *)) { + struct node *n; + n = list->head; + + while (n) { + if (!compare(n->data, key)) { //找到了,返回找到的数据 + return n->data; + } + n = n->next; + } + + return NULL; //找不到,返回NULL +} + +static struct node *find_min_node(List *list, + int (*compare)(const void *, const void *)) { + struct node *min, *n; + + n = list->head; + min = list->head; + + while (n) { + if (compare(min->data, n->data) > 0) { + min = n; + } + n = n->next; + } + + return min; +} + +static void delete_node(List *list, struct node *key) { + struct node *n; + + n = list->head; + + if (n == key) { + list->head = n->next; + return; + } + + while (n->next) { + if (n->next == key) { + if (key == list->tail) { + list->tail = n; + } + n->next = n->next->next; + return; + } + n = n->next; + } +} + +static void insert_node(List *list, struct node *key) { + if (list->head == NULL) { + list->head = key; + list->tail = key; + } else { + list->tail->next = key; + list->tail = key; + } +} + +void list_sort(List *list, + int (*compare)(const void *, const void *)) { + List tmp; + struct node *n; + + list_init(&tmp); + + while (!list_is_empty(list)) { + n = find_min_node(list, compare); + delete_node(list, n); + n->next = NULL; + insert_node(&tmp, n); + } + list->head = tmp.head; + list->tail = tmp.tail; +} + +void list_traverse(List *list, void (*handle)(void *)) { + struct node *p; + p = list->head; + + while (p) { + handle(p->data); + p = p->next; + } +} + +void list_reverse(List *list) { + struct node *pre = NULL, *next, *p = list->head; + + list->tail = list->head; //tail指向head; + while (p) { + next = p->next; + if (!next) { //当p->next为最后一个节点时,让head指向p->next + list->head = p; + } + //记录当前节点为pre,作为下一个节点的next.第一个节点为NULL,初始化时已定义。 + p->next = pre; + pre = p; + p = next; + } +} + +long list_get_lenth(List *list) { + return (list->len); +} + +void *list_get_element(List *list, int idx) { + int i = 1; + struct node *n; + n = list->head; + + while (n && i < idx) { + i++; + n = n->next; + } + + if (n) { + return n->data; + } + + return NULL; +} + +void list_destroy(List *list, void (*destroy)(void *)) { + list->len = 0; + struct node *n, *t; + n = list->head; + + while (n) { + t = n->next; //t只起一个记录n->next的功能,否则后面把n free掉之后,就找不到n->next了。 + if (destroy) { //传递用户自定义的数据处理函数,为0时不执行 + destroy(n->data); //使用用户提供的destroy函数来释放用户传递过来的数据。 + } + free(n); + n = t; //把n free掉之后,再把t给n,相当于把n->next给n,如此循环遍历链表,挨个删除, + } +} \ No newline at end of file diff --git a/main.c b/main.c index 748ceb2..320c95f 100644 --- a/main.c +++ b/main.c @@ -5,6 +5,7 @@ #include "t_iic.h" #include "t_task.h" #include "t_arg.h" +#include "t_list.h" #include "tool.h" #include @@ -12,14 +13,15 @@ int main() { srand((unsigned) time(NULL)); int i = 1; - POUT((++i) + (++i)); +// POUT((++i) + (++i)); - char str[] = "123.456"; - float result = Str2Float(str); - printf("Result: %.3f\n", result); - Test_RunTime("SPI", Test_spi); +// char str[] = "123.456"; +// float result = Str2Float(str); +// printf("Result: %.3f\n", result); +// Test_RunTime("SPI", Test_spi); // Test_RunTime("IIC", Test_iic); // Test_RunTime("ArgPase", Test_argpase); // Test_RunTime("Task", Test_task); + Test_RunTime("List", Test_List); return 0; }