list.h 中的包含的代码如下:
#ifndef LIST_H
#define LIST_H
#include "darknet.h"
// 初始化链表
list *make_list();
// 按值查找,注意这里的值是 void类型空指针,emmmm, list.c未定义,
int list_find(list *l, void *val);
//
void list_insert(list *, void *);
void free_list_contents(list *l);
#endif
首先,我们分析list.h 中的源码,基础数据结构list 定义在 darknet.h 中,其定义如下:
typedef struct node{
void *val; // 当前节点的内容是一个void类型的空指针
struct node *next; //指向当前节点的下一节点
struct node *prev; //指向当前节点的上一节点
} node;
typedef struct list{
int size; // 当前list 的长度
node *front; // 头指针,指针链表第一个节点
node *back; //尾指针,指针链表最后一个节点
} list;
可以发现,list就是我们熟悉的链表,可以发现在 list.h 中定义了4个函数,下面我们分别对解析这4个函数,我们将注解写在 list.c中,如下:
#include <stdlib.h>
#include <string.h>
#include "list.h"
// 初始化链表
list *make_list()
{
// 分配存储空间
list *l = malloc(sizeof(list));
// 初始化链表长度、头指针、尾指针
l->size = 0;
l->front = 0;
l->back = 0;
return l;
}
/*
void transfer_node(list *s, list *d, node *n)
{
node *prev, *next;
prev = n->prev;
next = n->next;
if(prev) prev->next = next;
if(next) next->prev = prev;
--s->size;
if(s->front == n) s->front = next;
if(s->back == n) s->back = prev;
}
*/
// 链表的删除操作,删除尾指针所指节点,即最后一个节点
void *list_pop(list *l){
// 如果链表为空
if(!l->back) return 0;
// node *b 指向最后一个节点
node *b = l->back;
void *val = b->val;
// 更新尾指针,尾指针指向b的前一节点,即倒数第二节点。
l->back = b->prev;
// 如果倒数第二节点存在
if(l->back) l->back->next = 0; //尾指针next置为null
free(b); // 释放最后一个节点的存储空间
--l->size; // 链表长度 -1
return val; // 返回被删除节点保存的值
}
// 链表按序插入操作
void list_insert(list *l, void *val)
{
// 为新节点申请存储空间
node *new = malloc(sizeof(node));
// 赋值
new->val = val;
new->next = 0; // next置null
// 如果链表l 尾指针为空,则说明此时链表l长度为0
if(!l->back){
l->front = new; // 更新头指针
new->prev = 0; // 此时该节点为头节点,故头节点的上一节点为null
}else{ //如果链表l 尾指针非空,则说明此时l长度 >=1
l->back->next = new; // 更新当前节点的上一节点的next指针域
new->prev = l->back; // 更新当前节点的prev指针域
}
l->back = new; // 更新链表l的尾指针
++l->size; // 链表长度 +1
}
// 释放链表节点的存储空间,从节点n开始释放,一直释放到最后一个节点。
void free_node(node *n)
{
node *next;
while(n) {
next = n->next; // 获取下一节点地址
free(n); // 释放当前节点存储空间
n = next; //更新n,n指向下一节点
}
}
// 释放整个链表l的存储空间
void free_list(list *l)
{
free_node(l->front);
free(l);
}
// 对链表所有节点的值【节点中值为void 类型指针】 的存储空间释放
void free_list_contents(list *l)
{
node *n = l->front;
while(n){
free(n->val);
n = n->next;
}
}
// 二维指针,这里的操作是将链表l中所有节点的值进行保存,
// 因为每个节点里保存的值是 void类型的指针,故指针的指针,即二维指针
void **list_to_array(list *l)
{
// 分配存储空间,长度l-size, 每个空间大小为一个void类型指针
void **a = calloc(l->size, sizeof(void*));
int count = 0;
node *n = l->front; // 工作指针n指向头节点
while(n){
// 将工作指针n指向节点的值保存到a中
a[count++] = n->val;
n = n->next;// 更新工作指针
}
return a;
}