1、动态内存申请链表
1.1 基本结构
如下是一个节点的定义,从中可以看出它是一个双向链表,包含指向前后的指针 head / tail,和指针指向空间的大小 size。
typedef uint8_t _node_p;
typedef struct linklist{
uint32 size;
_node_p *head;
_node_p *tail;
}Linklist_t
其想要实现的功能如下所示,通过 memory 的起始地址和空间大小 size 就可以确定和使用该空间。这样的做的好处就是,每一个节点空间的大小的可变的,就可以通过一个链表来适应不同的使用场景。

双向链表节点的组织形式如下,注意最后一个节点 node3 的 prev 为 NULL,第一个节点 node1 的 tail 为 NULL。

2、常用接口
- 2.1 主要是对链表的增删改查,在对链表进行增删改查前,首先要定义头结点并初始化。头结点的初始化如下。
Linklist_t Head; // 定义一个头结点 Head
void linklist_init(Linklist_t *h, uint32 size){
h->head = NULL;
h->tail = NULL;
h->size = size;
}
- 2.2 如下是链表的添加节点的逻辑,需要注意的是最后一个节点的 prev 为 NULL,第一个节点的 tail 为 NULL。
/**
* @param h 头结点
* @return void* 返回申请空间的起始地址
*/
void *linklist_insert(Linklist_t *h);

- 2.3 链表的节点的删除、修改和查询。
链表添加已经在上面说明,其它的操作同理就不展开了;下面给出连接,其中包括一些常用的数据结构,实现方式与本文介绍的一样,都是采用的动态内存申请的方式,包括的数据结构有双向链表、栈、循环队列等。
本文链表其它操作见 linklist_malloc.c 和 linklist_malloc.h,github 链接
3、应用
下面为一个应用的例子,可以同过一个链表去应对多种不同的情况。
// test
typedef struct info {
int id;
int age;
char name[16];
float soc;
} INFO;
typedef struct image {
int id;
int w;
int h;
struct pos {
int x;
int y;
};
} IMAGE;
// 定义两个链表的头结点
linklist2_t list_info;
linklist2_t list_image;
int main() {
// info
list_init_2(&list_info, sizeof(struct info)); // 初始化链表的头结点,size 为要存入元素的大小
INFO *info1 = list_ins_head_2(&list_info); // 插入一个节点
INFO *info2 = list_ins_head_2(&list_info);
if (info1 != NULL) {
info1->id = 0;
info1->age = 23;
strcpy(info1->name, "ZhangSan");
info1->soc = 19.3;
}
if (info2 != NULL) {
info2->id = 1;
info2->age = 25;
strcpy(info2->name, "LiSi");
info2->soc = 56.2;
}
// 遍历输出每个节点的信息
INFO *i;
_LV_LL_READ(&list_info, i) {
printf("id=%d, age=%d, name=%s, soc=%.2f\n", i->id, i->age, i->name, i->soc);
}
// image
list_init_2(&list_image, sizeof(struct image)); // 初始化链表的头结点,size 为要存入元素的大小
IMAGE *img1 = list_ins_head_2(&list_image);
IMAGE *img2 = list_ins_head_2(&list_image);
if (img1 != NULL) {
img1->id = 0;
img1->w = 100;
img1->h = 101;
img1->x = 50;
img1->y = 51;
}
if (img2 != NULL) {
img2->id = 1;
img2->w = 200;
img2->h = 201;
img2->x = 250;
img2->y = 251;
}
// 遍历输出每个节点的信息
IMAGE *m;
_LV_LL_READ_BACK(&list_image, m) {
printf("id=%d, w=%d, h=%d, x=%d, y=%d\n", m->id, m->w, m->h, m->x, m->y);
}
return 0;
}

2万+

被折叠的 条评论
为什么被折叠?



