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;
} 我的书签
 我的书签
                                 添加书签
 添加书签 移除书签
 移除书签