数据结构和算法 第六天内核链表是链表的终结者

  • 第一章 内核链表图文讲解
  • 第二章 内核链表代码详解
    • 【1】list.h
    • 【2】list.c

内核链表不过是双向链表的封装,学起来

第一章 内核链表图文讲解

第二章 内核链表代码详解

【1】list.h

//
//
//  Copyright(C), 2013-2016, GEC Tech. Co., Ltd.
//
//  File name: GPLE/ch03/3.1/list.h
//
//  Author: Linux Kernel
//
//  Date: 2016-3
//
//  Description: Linux内核链表源代码
//
//  GitHub: github.com/vincent040   Bug Report: 2437231462@qq.com
//
//#ifndef __DLIST_H
#define __DLIST_H/* This file is from Linux Kernel (include/linux/list.h)
* and modified by simply removing hardware prefetching of list items.
* Here by copyright, credits attributed to wherever they belong.
* Kulesh Shanmugasundaram (kulesh [squiggly] isis.poly.edu)
*//*
* Simple doubly linked list implementation.
*
* Some of the internal functions (“__xxx”) are useful when
* manipulating whole lists rather than single entries, as
* sometimes we already know the next/prev entries and we can
* generate better code by using them directly rather than
* using the generic single-entry routines.
*/
/*** container_of - cast a member of a structure out to the containing structure*   * @ptr: the pointer to the member.* @type:  the type of the container struct this is embedded in.* @member: the name of the member within the struct.**///统计小个结构体距离大个结构体的偏移量是多少
#define offsetof(TYPE, MEMBER) ((size_t) &((TYPE *)0)->MEMBER)//获取大个结构体的地址,并不是很通用
#define container_of(ptr, type, member) ({\const typeof( ((type *)0)->member ) *__mptr = (ptr);\(type *)( (char *)__mptr - offsetof(type,member) );})
/** These are non-NULL pointers that will result in page faults* under normal circumstances, used to verify that nobody uses* non-initialized list entries.*///在内核当中的两个非法地址
#define LIST_POISON1  ((void *) 0x00100100)
#define LIST_POISON2  ((void *) 0x00200)/*内核链表小个结构体的声明
*/
struct list_head {struct list_head *next, *prev;
};//为了配合小个结构体的初始化,就是小个结构体变量的声明
#define LIST_HEAD_INIT(name) { &(name), &(name) }
//诞生一个小个结构体变量,并且让里面prev指针跟next都指向自己
#define LIST_HEAD(name)\
struct list_head name = LIST_HEAD_INIT(name)/*初始化头节点
*/
#define INIT_LIST_HEAD(ptr) do {\(ptr)->next = (ptr); (ptr)->prev = (ptr);\
} while (0)/*
* Insert a new entry between two known consecutive entries.
*
* This is only for internal list manipulation where we know
* the prev/next entries already!
*///插入节点,new是新节点,prev上一个节点是谁,next下一个节点是谁
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;
}/**
* list_add – add a new entry
* @new: new entry to be added
* @head: list head to add it after
*
* Insert a new entry after the specified head.
* This is good for implementing stacks.
*/
//插入new节点到head后面去
static inline void list_add(struct list_head *new, struct list_head *head)
{__list_add(new, head, head->next);
}/**
* list_add_tail – add a new entry
* @new: new entry to be added
* @head: list head to add it before
*
* Insert a new entry before the specified head.
* This is useful for implementing queues.
*///插入new节点到head前面去
static inline void list_add_tail(struct list_head *new, struct list_head *head)
{__list_add(new, head->prev, head);
}/*
* Delete a list entry by making the prev/next entries
* point to each other.
*
* This is only for internal list manipulation where we know
* the prev/next entries already!
*/
//移除prev跟next两个节点中间的节点
static inline void __list_del(struct list_head *prev, struct list_head *next)
{next->prev = prev;prev->next = next;
}/**
* list_del – deletes entry from list.
* @entry: the element to delete from the list.
* Note: list_empty on entry does not return true after this, the entry is in an undefined state.
*/
//将entry节点从链表当中移除,将entry节点里面的上下个指针指向NULL
static inline void list_del(struct list_head *entry)
{__list_del(entry->prev, entry->next);entry->next = (void *) 0;entry->prev = (void *) 0;
}/**
* list_del_init – deletes entry from list and reinitialize it.
* @entry: the element to delete from the list.
*/
//将entry节点从链表当中移除,将entry节点里面的上下个指针指向entry
static inline void list_del_init(struct list_head *entry)
{__list_del(entry->prev, entry->next);INIT_LIST_HEAD(entry);
}/**
* list_move – delete from one list and add as another’s head
* @list: the entry to move
* @head: the head that will precede our entry
*/
//将链表中的list节点移动到head后面去
static inline void list_move(struct list_head *list,struct list_head *head)
{__list_del(list->prev, list->next);list_add(list, head);
}/**
* list_move_tail – delete from one list and add as another’s tail
* @list: the entry to move
* @head: the head that will follow our entry
*/
//将链表中的list节点移动到head前面去
static inline void list_move_tail(struct list_head *list,struct list_head *head)
{__list_del(list->prev, list->next);list_add_tail(list, head);
}/**
* list_empty – tests whether a list is empty
* @head: the list to test.
*/
//判断链表是否为空链表
static inline int list_empty(struct list_head *head)
{return head->next == head;
}
//接合list跟head两条链表
static inline void __list_splice(struct list_head *list,struct list_head *head)
{struct list_head *first = list->next;struct list_head *last = list->prev;struct list_head *at = head->next;first->prev = head;head->next = first;last->next = at;at->prev = last;
}/**
* list_splice – join two lists
* @list: the new list to add.
* @head: the place to add it in the first list.
*/
//将两条链表合并成为一条链表
static inline void list_splice(struct list_head *list, struct list_head *head)
{
if (!list_empty(list))
__list_splice(list, head);
}/**
* list_splice_init – join two lists and reinitialise the emptied list.
* @list: the new list to add.
* @head: the place to add it in the first list.
*
* The list at @list is reinitialised
*/
//将两条链表合并成为一条链表,顺便将list这个头节点初始化成为指向自己的头节点
static inline void list_splice_init(struct list_head *list,
struct list_head *head)
{
if (!list_empty(list)) {
__list_splice(list, head);
INIT_LIST_HEAD(list);
}
}/**
* list_entry – get the struct for this entry通过小个结构体地址获取大个结构体地址的方式
* @ptr:    the &struct list_head pointer.小个结构体地址
* @type:    the type of the struct this is embedded in.大个结构体类型名字
* @member:    the name of the list_struct within the struct.小个结构体元素名字
*/
//通过小个结构体地址获取大个结构体地址的方式
#define list_entry(ptr, type, member)\
((type *)((char *)(ptr)-(unsigned long)(&((type *)0)->member)))/**
* list_for_each    -    iterate over a list
* @pos:    the &struct list_head to use as a loop counter.
* @head:    the head for your list.
*/
//不安全遍历方式,向下遍历
#define list_for_each(pos, head)\
for (pos = (head)->next; pos != (head);\
pos = pos->next)
/**
* list_for_each_prev    -    iterate over a list backwards
* @pos:    the &struct list_head to use as a loop counter.
* @head:    the head for your list.
*/
//不安全遍历方式,向上遍历
#define list_for_each_prev(pos, head)\
for (pos = (head)->prev; pos != (head);\
pos = pos->prev)/**
* list_for_each_safe    -    iterate over a list safe against removal of list entry
* @pos:    the &struct list_head to use as a loop counter.
* @n:        another &struct list_head to use as temporary storage
* @head:    the head for your list.
*/
//安全的遍历方式
#define list_for_each_safe(pos, n, head)\
for (pos = (head)->next, n = pos->next; pos != (head);\
pos = n, n = pos->next)/**
* list_for_each_entry    -    iterate over list of given type
* @pos:    the type * to use as a loop counter.
* @head:    the head for your list.
* @member:    the name of the list_struct within the struct.
*/
//以不安全的形式遍历链表的每个元素,并且获取大个结构体放到pos里面
#define list_for_each_entry(pos, head, member)\
for (pos = list_entry((head)->next, typeof(*pos), member);\
&pos->member != (head);\
pos = list_entry(pos->member.next, typeof(*pos), member))/**
* list_for_each_entry_safe – iterate over list of given type safe against removal of list entry
* @pos:    the type * to use as a loop counter.
* @n:        another type * to use as temporary storage
* @head:    the head for your list.
* @member:    the name of the list_struct within the struct.
*/
//以安全的形式遍历链表的每个元素,并且获取大个结构体放到pos里面
#define list_for_each_entry_safe(pos, n, head, member)\
for (pos = list_entry((head)->next, typeof(*pos), member),\
n = list_entry(pos->member.next, typeof(*pos), member);\
&pos->member != (head);\
pos = n, n = list_entry(n->member.next, typeof(*n), member))#endif

小结构体形如双向链表的prev,next上下指针,大结构体存储数据
小结构体被大结构体所包含

【2】list.c

/** @Author: your name* @Date: 2021-09-01 17:01:47* @LastEditTime: 2021-09-01 17:35:15* @LastEditors: Please set LastEditors* @Description: In User Settings Edit* @FilePath: \Desktop\kernel_list\main.c*/
#include <stdio.h>
#include <stdlib.h>
#include "list.h"//大结构体
typedef struct big{int data;//存储数据struct list_head list;//小结构体变量
}node_t;typedef struct one{int data;struct list_head list;
}node_one_t;typedef struct two{int data;struct list_head list;
}node_two_t;//第一种写法:申请节点空间
node_t *request_list_node(void)
{node_t *new_node;//大结构体指针new_node = malloc(sizeof(node_t));if(new_node == NULL){perror("申请节点出错");return NULL;}INIT_LIST_HEAD(&new_node->list);//初始化小结构体return new_node;
}//第二种写法:宏函数方式申请节点空间
#define request_list_node(new_node)({\
\new_node = malloc(sizeof(typeof(new_node)));\if(new_node == NULL)\{\perror("申请节点出错");\}\
\INIT_LIST_HEAD(&(new_node->list));\
})//显示链表
void display_list_node(node_t *list_head)
{struct list_head *pos;//小个结构体的posnode_t *bpos;//大结构体指针printf("表格已有数据:");//不安全的遍历方式list_for_each(pos, &list_head->list)//这就是跟之前一样的for循环,只是里面循环的是小个结构体的地址{bpos = list_entry(pos, node_t, list);//通过小个结构体获取大个结构体的地址//因为大结构才是真正存储数据的大宝贝printf("%d ", bpos->data);}printf("\n");}int main(void)
{int input_value;node_t *list_head, *new_node;//申明两个链表节点的指针变量,其中list_head用来存放链表的头节点,new_node用来临时存放一下新申请的节点node_t *find_node;//新建链表头节点list_head = request_list_node();while(1){scanf("%d", &input_value);if(input_value > 0){//新建一个节点new_node = request_list_node();new_node->data = input_value;//插入表格list_add(&new_node->list, &list_head->list);}else if(input_value < 0){if(list_empty(&list_head->list))continue;find_node = list_entry(list_head->list.next, node_t, list);//通过小个结构体获取大个结构体的地址//移除出链表list_del(list_head->list.next);free(find_node);}else    break;//遍历表格display_list_node(list_head);}//销毁链表return 0;
}

数据结构和算法 第六天内核链表是链表的终结者相关推荐

  1. 常见数据结构和算法实现(排序/查找/数组/链表/栈/队列/树/递归/海量数据处理/图/位图/Java版数据结构)

    常见数据结构和算法实现(排序/查找/数组/链表/栈/队列/树/递归/海量数据处理/图/位图/Java版数据结构) 数据结构和算法作为程序员的基本功,一定得稳扎稳打的学习,我们常见的框架底层就是各类数据 ...

  2. 黑马程序员 C语言数据结构与算法之线性表(链表/栈/队列/顺序表)

    C语言 链表基础知识清晰讲解(黑马) 讲的蛮好,就是音质不太好,有时听不清讲的啥! [黑马]数据结构与算法之线性表(链表/栈/队列/顺序表)[配套源码 嘛蛋,看错了,这是java的... 文章目录 链 ...

  3. java环形链表_数据结构和算法(四)Java实现环形链表

    1. 数据结构和算法(四)Java实现环形链表 1.1 约瑟夫问题 约瑟夫问题:公元66年,约瑟夫不情愿地参与领导了犹太同胞反抗罗马统治的起义,后来起义失败,他和一些宁死不降的起义者被困于一个山洞之中 ...

  4. Python数据结构与算法(附录)——块状链表的动态调整

    Python数据结构与算法(附录)--块状链表的动态调整 块状链表的动态调整 违反规则 1 违反规则 2 相关链接 块状链表的动态调整 我们已经知道块状链表的块的最大容量会随着链表长度的变化动态改变, ...

  5. Python数据结构与算法(2.3)——链表

    Python数据结构与算法(2.3)--链表 0. 学习目标 1. 线性表的链式存储结构 1.1 指针相关概念 1.2 指针结构 1.2 结点 1.3 结点类 2. 单链表的实现 2.1 单链表的初始 ...

  6. java数据结构与算法之顺序表与链表深入分析

    转载请注明出处(万分感谢!): http://blog.csdn.net/javazejian/article/details/52953190 出自[zejian的博客] 关联文章: java数据结 ...

  7. 数据结构与算法(六)- 单向链表的反转

    数据结构与算法(六)- 单向链表的反转 一.头节点插入法 /*** 反转单向链表(头插法)** 1.先定义一个节点reverseHead = new HeroNode()* 2.从头到尾遍历原来的链表 ...

  8. 数据结构和算法(四)之链表结构

    数据结构和算法(四)之链表结构 一. 认识链表 链表和数组一样,可以用来存储一系列的元素,但是链表和数组的实现机制完全不同. 这一章中,我们就来学习一下另外一种非常常见的用于存储数据的线性结构:链表! ...

  9. 06_JavaScript数据结构与算法(六)单向链表

    JavaScript 数据结构与算法(六)单向链表 认识链表 链表和数组 链表和数组一样,可以用于存储一系列的元素,但是链表和数组的实现机制完全不同. 数组 存储多个元素,数组(或列表)可能是最常用的 ...

最新文章

  1. Modus串行链路系统电气特性:2线-Modus、4线-Modus、RS232-Modus和RS485-Modus的特性
  2. mysql8.0 linux安装自启动_Linux系统安装部署MySQL8.0.12特详细教程
  3. Winform中实现设置ZedGraph的GraphPane的大小匹配ZedGraphControl
  4. hadoop日常运维
  5. java面向方面编程_面向方面编程的介绍----基本概念
  6. xbox手柄接收器驱动_xbox手柄连接 win10电脑
  7. 95-136-041-源码-Operator-TwoInputStreamOperator
  8. PHP导出成word文档
  9. 获得一个日期在当周是否有节日并返回日期
  10. java测试步骤_java测试框架的方法
  11. jQuery鼠标事件整理
  12. win10不自带扫雷,想玩扫雷怎么办?自己造一个扫雷
  13. Word在生成PDF后,PDF左侧导航书签没有目录
  14. mini2440的串口在Qt上实现
  15. 直流屏电源模块GF22007-2高频充电模块R22007
  16. windows下安装redis并设置自启动
  17. Symmetric Matrices
  18. 做一个最简单的上位机
  19. mt4服务器显示无连接,MT4登录显示“无效账户”,“无法连接”怎么解决
  20. 最简洁的Git的基本操作

热门文章

  1. 信息安全工程师学习笔记《第二章》
  2. html页面调用微信扫一扫功能,微信JSSDK调用微信扫一扫功能的方法
  3. mysql task06(结营)
  4. 说说IO(七)- RAID
  5. 历经一个月的时间,在大家的共同努力下新星计划圆满结束,让我们看一下详细数据吧!
  6. 含文档+PPT+源码等]精品基于ssm的足球联赛管理系统的设计与实现vue[包运行成功]计算机Java毕业设计SSM项目源码
  7. lisp调用qleader端点_常用函数.lsp - AutoLISP/Visual LISP 编程技术 - CAD论坛 - 明经CAD社区 - Powered by Discuz!...
  8. iOS开发(一)——Object-c语言基础(2、数据类型与表达式)
  9. 【Linux】工具使用
  10. 贵卅大学计算机研究生院导师,贵州大学机械工程学院研究生导师:罗绍华