进阶链表(C实现)

background0002.jpg

大家好,又见面了,今天又要跟大家来个链表,链表实现的方式有很多,本文将使用线性表的方式实现链表

链表是什么

关于链表的定义,本文不再详细赘述,详情可查看两年前的文章-->https://mp.weixin.qq.com/s/yj3RBr2nSAyQwFV8JHoOKA

线性链表定义

首先定义链表

 1 #define _COMMON_VARIABLES  \
 2     void *free_pointer;   \
 3     u16_t data_numbers;   \
 4     u16_t data_free_numbers; \
 5     u32_t data_size
 6 
 7 typedef struct {
 8     _COMMON_VARIABLES;
 9     char datas[0];
10 }commonn_list_t;
11 
12 #define DEFINE_LIST_TYPE(list_type_name, data_numbers, data_size)  \
13     typedef struct {                                               \
14         _COMMON_VARIABLES;                                         \
15         char datas[data_numbers * data_size];                      \
16     }list_type_name

为什么要使用固定大小的链表,对于底层来说,空间性能等方面都是需要考虑的问题,在设计结构的同时必须考虑这些问题,对于不连续的内存来说,影响性能。

初始化

 1 void list_init(void* list, u16_t data_numbers ,u32_t data_size){
 2     commonn_list_t *comm_list = (commonn_list_t*)list;
 3     u64_t* p;
 4     u32_t i;
 5     //printf("list_init size %d\n", sizeof(p)); //because PC pointer size is 8 bytes, which is different from the arm platform
 6     comm_list->data_numbers = data_numbers;
 7     comm_list->data_size = data_size;
 8     p = (u64_t*)&comm_list->datas[0];
 9     comm_list->free_pointer = &comm_list->datas[0];
10 
11     for( i = 1; i < data_numbers; ++i){
12         *p = (u64_t)&comm_list->datas[i * data_size];
13         p = (u64_t*)&comm_list->datas[i * data_size];
14     }
15     comm_list->data_free_numbers = data_numbers;
16     *p = 0;
17 }

获取链表中的空间

1 void* list_get(void* list){
2     commonn_list_t* comm_list = (commonn_list_t*)list;
3     void* p = comm_list->free_pointer;
4     if(p){
5         comm_list->free_pointer = (void*)*((u64_t*)p);
6         --comm_list->data_free_numbers;
7     }
8     return p;
9 }

归还链表中的空间

1 void list_put(void* list, void* data){
2     commonn_list_t* comm_list = (commonn_list_t*)list;
3     *((u64_t*)data) = (u64_t)comm_list->free_pointer;
4     comm_list->free_pointer = data;
5     ++comm_list->data_free_numbers;
6 }
7 void list_put_use_index(void* list, u32_t index){
8     list_put(list, list_from_index_get_data(list, index));
9 }

累了,想划划水,写完代码之后就索然无味,本文链表的实现的本质是,当前链表保存下一个链表的地址,同时有一个头指针一直指向最开始的指针,仔细阅读init函数就可以明白本文链表的本质。

代码经过简单的测试,有问题请指正。

附全部代码

Makefile

 1 CC = gcc
 2 CFLAGS = -I.
 3 DEPS = list.h
 4 OBJ = main.o list.o 
 5 
 6 %.o: %.c $(DEPS)
 7 $(CC) -c -o $@ $< $(CFLAGS)
 8 
 9 list: $(OBJ)
10 $(CC) -o $@ $^ $(CFLAGS)
11 
12 .PHONY: clean
13 
14 clean:
15 rm -f list *.o

list.h

 1 /****************************************************************
 2   *@file       : list.h
 3   *@description: 
 4   *@time       : 2023/08/24 18:49:04
 5   *@author     : Nick Xia
 6   *@blog       : https://aeneag.xyz
 7 *****************************************************************/
 8 #ifndef _LIST_H
 9 #define _LIST_H
10 
11 typedef unsigned char u8_t;
12 typedef unsigned short u16_t;
13 typedef unsigned int u32_t;
14 typedef unsigned long long u64_t;
15 
16 #define _COMMON_VARIABLES  \
17     void *free_pointer;   \
18     u16_t data_numbers;   \
19     u16_t data_free_numbers; \
20     u32_t data_size
21 
22 typedef struct {
23     _COMMON_VARIABLES;
24     char datas[0];
25 }commonn_list_t;
26 
27 #define DEFINE_LIST_TYPE(list_type_name, data_numbers, data_size)  \
28     typedef struct {                                               \
29         _COMMON_VARIABLES;                                         \
30         char datas[data_numbers * data_size];                      \
31     }list_type_name
32 
33 void list_init(void* list, u16_t data_numbers ,u32_t data_size);
34 u16_t list_get_data_index(void* list, void* data);
35 void* list_from_index_get_data(void* list, u32_t index);
36 void* list_get(void* list);
37 void list_put(void* list, void* data);
38 void list_put_use_index(void* list, u32_t index);
39 u32_t list_free_numbers(void* list);
40 u32_t list_data_numbers(void* list);
41 u32_t list_used_numbers(void* list);
42 
43 #endif // I_LIST_H
44 

list.c

 1 /****************************************************************
 2   *@file       : list.c
 3   *@description: 
 4   *@time       : 2023/08/24 18:49:12
 5   *@author     : Nick Xia
 6   *@blog       : https://aeneag.xyz
 7 *****************************************************************/
 8 #include "list.h"
 9 // #include <stdio.h>
10 void list_init(void* list, u16_t data_numbers ,u32_t data_size){
11     commonn_list_t *comm_list = (commonn_list_t*)list;
12     u64_t* p;
13     u32_t i;
14     //printf("list_init size %d\n", sizeof(p)); //because PC pointer size is 8 bytes, which is different from the arm platform
15     comm_list->data_numbers = data_numbers;
16     comm_list->data_size = data_size;
17     p = (u64_t*)&comm_list->datas[0];
18     comm_list->free_pointer = &comm_list->datas[0];
19 
20     for( i = 1; i < data_numbers; ++i){
21         *p = (u64_t)&comm_list->datas[i * data_size];
22         p = (u64_t*)&comm_list->datas[i * data_size];
23     }
24     comm_list->data_free_numbers = data_numbers;
25     *p = 0;
26 }
27 u16_t list_get_data_index(void* list, void* data){
28     commonn_list_t* comm_list = (commonn_list_t*)list;
29     return (u16_t)((char*)data - (char*)comm_list->datas) / comm_list->data_size;
30 }
31 void* list_from_index_get_data(void* list, u32_t index){
32     commonn_list_t* comm_list = (commonn_list_t*)list;
33     return comm_list->datas + index * comm_list->data_size;
34 }
35 void* list_get(void* list){
36     commonn_list_t* comm_list = (commonn_list_t*)list;
37     void* p = comm_list->free_pointer;
38     if(p){
39         comm_list->free_pointer = (void*)*((u64_t*)p);
40         --comm_list->data_free_numbers;
41     }
42     return p;
43 }
44 void list_put(void* list, void* data){
45     commonn_list_t* comm_list = (commonn_list_t*)list;
46     *((u64_t*)data) = (u64_t)comm_list->free_pointer;
47     comm_list->free_pointer = data;
48     ++comm_list->data_free_numbers;
49 }
50 void list_put_use_index(void* list, u32_t index){
51     list_put(list, list_from_index_get_data(list, index));
52 }
53 u32_t list_free_numbers(void* list){
54     commonn_list_t* comm_list = (commonn_list_t*)list;
55     return (u32_t)comm_list->data_free_numbers;
56 }
57 u32_t list_data_numbers(void* list){
58     commonn_list_t* comm_list = (commonn_list_t*)list;
59     return (u32_t)comm_list->data_numbers;
60 }
61 u32_t list_used_numbers(void* list){
62     commonn_list_t* comm_list = (commonn_list_t*)list;
63     return (u32_t)(comm_list->data_numbers - comm_list->data_free_numbers);
64 }

main.c

 1 /****************************************************************
 2   *@file       : main.c
 3   *@description: 
 4   *@time       : 2023/08/24 19:05:56
 5   *@author     : Nick Xia
 6   *@blog       : https://aeneag.xyz
 7 *****************************************************************/
 8 #include "list.h"
 9 #include <stdio.h>
10 
11 typedef struct l_data{
12     /* data */
13     u8_t data1;
14     u8_t data2;
15     u16_t data3;
16     u32_t data4;
17     u64_t data5;
18 }__attribute__((packed)) l_data_t;
19 
20 #define MY_DATA_NUM 256
21 DEFINE_LIST_TYPE(my_list_t, MY_DATA_NUM, sizeof(l_data_t));
22 my_list_t my_list;
23 
24 int main(int argc, char **argv){
25     list_init(&my_list, MY_DATA_NUM, sizeof(l_data_t));
26     printf("free_numbers: %d\n", list_free_numbers(&my_list));
27     printf("used_numbers: %d\n", list_used_numbers(&my_list));
28     l_data_t* my_= list_get(&my_list);
29 
30     printf("\n");
31     printf("free_numbers: %d\n", list_free_numbers(&my_list));
32     printf("used numbers: %d\n", list_used_numbers(&my_list));
33     my_->data1 = 1;
34 
35     l_data_t* my_1;
36     list_get(&my_list);
37 
38     printf("\n");
39     printf("free numbers: %d\n", list_free_numbers(&my_list));
40     printf("used_numbers: %d\n", list_used_numbers(&my_list));
41     my_1->data2 = 2;
42     list_put_use_index(&my_list,list_get_data_index(&my_list, my_1));
43 
44     printf("\n");
45     printf("free_numbers: %d\n", list_free_numbers(&my_list));
46     printf("used_numbers: %d\n", list_used_numbers(&my_list));
47     list_put(&my_list, my_);
48     printf("\n");
49     printf("free_numbers: %d\n", list_free_numbers(&my_list));
50     printf("used_numbers: %d\n", list_used_numbers(&my_list));
51 }

原文链接


    


公众号'艾恩凝'
个人公众号
个人微信
个人微信
    吾心信其可行,
          则移山填海之难,
                  终有成功之日!
                                  ——孙文
    评论
    0 评论
avatar

取消