内核链表
内核链表与传统链表不一样,传统链表数据域与指针域都是用户自定义的,而是内核链表数据域是用户定义,但是指针域是内核链表头文件中已经定义好的了。
内核链表 :头节点无效,双向循环链表
指针域结构体的结构
内核链表头文件:kernel_list.h
struct list_head {
struct list_head *next; -> 后继指针 -> 指向下一个节点指针域的结构体的地址
struct list_head *prev; -> 前驱指针 -> 指向上一个节点指针域的结构体的地址
};
设计节点模型
struct list_node{
//数据域
int a;
//指针域
struct list_head list; -> 里面已经包含了两个指针。
};
学习内核链表的增删改查
- 初始化空链表?
1)为头节点申请堆空间
head = (struct list_node *)malloc(sizeof(struct list_node));
2)为头节点指针域赋值
INIT_LIST_HEAD(&(head->list));
解析:
kernel_list.h ->49行:
#define INIT_LIST_HEAD(ptr)
do{
(ptr)->next = (ptr); -> 头节点指针域的后继指针指向头节点的指针域结构体
(ptr)->prev = (ptr); -> 头节点指针域的前驱指针指向头节点的指针域结构体
}while(0)
- 插入数据到链表中
1)为新的节点申请空间
struct list_node *Node = NULL;
Node = (struct list_node *)malloc(sizeof(struct list_node));
2)为数据域赋值
Node->a = num
3)调用尾插/头插的函数
尾插:list_add_tail(&(Node->list),&(head->list));
头插:list_add(&(Node->list),&(head->list));
分析插入数据函数接口:
函数一: 将一个节点new插入两个节点next与prev之间。
static inline void __list_add(struct list_head *new, -> 新节点的指针域结构体的地址
struct list_head *prev, -> 新节点前一个节点的指针域结构体的地址
struct list_head *next) -> 新节点后一个节点的指针域结构体的地址
{
next->prev = new;
new->next = next;
new->prev = prev;
prev->next = new;
}
函数二: 尾插