美文网首页
C语言链表

C语言链表

作者: louyang | 来源:发表于2019-03-25 15:41 被阅读0次
1 准备

在Fedora 29中,使用下述命令安装内核源代码.

$ sudo dnf install kernel-devel
2 例子1

编写一个最简单的链表程序,3个节点依次加入链表后遍历:

#include <stdio.h>
#include "linux/list.h"

struct foo {
    int data;
    struct list_head list;
};

int main()
{
    struct foo first = {
        .data = 10,
        .list = LIST_HEAD_INIT(first.list)
    };

    struct foo second = {
        .data = 20,
        .list = LIST_HEAD_INIT(second.list)
    };
    
    struct foo third = {
        .data = 30,
        .list = LIST_HEAD_INIT(third.list)
    };
    
    LIST_HEAD(head);

    list_add(&first.list, &head);
    list_add(&second.list, &head);
    list_add(&third.list, &head);

    struct foo *ptr = NULL;
    list_for_each_entry(ptr, &head, list) {
        printf("%d ", ptr->data);
    }
    printf("\n");
}

运行:

$ gcc a.c -I/usr/src/kernels/4.20.16-200.fc29.x86_64/tools/include/ && ./a.out
30 20 10 

稍微改变一下:

...
    list_add(&first.list, &head);
    list_add(&second.list, &first.list);
    list_add(&third.list, &second.list);
...

运行结果有所不同:

$ gcc a.c -I/usr/src/kernels/4.20.16-200.fc29.x86_64/tools/include/ && ./a.out
10 20 30 
3 代码分析
3.1 首先,我们有个简单的数据结构
struct foo {
    int data;
};
3.2 我们想把它变成一个链表

只需要在数据结构中加入struct list_head list

struct foo {
    int data;
    struct list_head list;
};

struct list_head定义在linux/types.h头文件中:

struct list_head {
        struct list_head *next, *prev;
};

现在数据结构可以理解为如下图:


image.png

list_head也许在这里叫list_hook更合适。

3.3 实例化某个节点

定义一个 变量,变量名叫first.

    struct foo first = {
        .data = 10,
        .list = LIST_HEAD_INIT(first.list)
    };

LIST_HEAD_INIT定义在list.h中,

#define LIST_HEAD_INIT(name) { &(name), &(name) }

所以first这个变量看上去这个样子:


image.png

同样的道理,我们有secondthird

image.png image.png
3.4 定义链表头
LIST_HEAD(head);

LIST_HEAD定义在list.h中:

#define LIST_HEAD(name) \
        struct list_head name = LIST_HEAD_INIT(name)
image.png
3.5 把3个节点串成一串
    list_add(&first.list, &head);
    list_add(&second.list, &first.list);
    list_add(&third.list, &second.list);

list_add定义在list.h文件中:

/**
 * 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.
 */
static inline void list_add(struct list_head *new, struct list_head *head)
{
        __list_add(new, head, head->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(&first.list, &head);
    list_add(&second.list, &first.list);
    list_add(&third.list, &second.list);
image.png
4 例子2

另外一种写法:

#include <stdio.h>
#include "linux/list.h"

struct foo {
    int data;
    struct list_head list;
};

int main()
{
    struct foo first, second, third;
    first.data = 10,
    second.data = 20,
    third.data = 30,

    INIT_LIST_HEAD(&first.list);
    INIT_LIST_HEAD(&second.list);
    INIT_LIST_HEAD(&third.list);

    LIST_HEAD(head);

    list_add(&first.list, &head);
    list_add(&second.list, &head);
    list_add(&third.list, &head);

    struct foo *ptr = NULL;
    list_for_each_entry(ptr, &head, list) {
        printf("%d ", ptr->data);
    }
    printf("\n");
}

运行:

$ gcc b.c -I/usr/src/kernels/4.20.16-200.fc29.x86_64/tools/include/ && ./a.out
30 20 10
5 例子3

使用安全接口遍历,就算是同时有节点被删除,也OK。

    struct foo *ptr, *tmp = NULL;
    list_for_each_entry_safe(ptr, tmp, &head, list) {
        printf("%d ", ptr->data);
    }

参考
  1. https://www.cs.uic.edu/~hnagaraj/articles/linked-list/
  2. https://kernelnewbies.org/FAQ/LinkedLists

相关文章

  • 链表逆置C语言完整代码

    链表逆置C语言完整代码

  • Java实现简单的链表-面向初学者

    很久之前用C语言实现过链表,现在已经太久没用C语言。就先用JAVA实现一个简单链表好了,还是使用最原始的C语言实现...

  • 链表(C语言)

    LinkList.h LinkList.c

  • C语言链表

    链表 链表用于解决合理利用存储空间的问题 malloc在没有连续内存空间的时候分配会失败 解决方案:不要一次性开辟...

  • C语言链表

    链表 作业 include "stdio.h" typedef struct Home{int fridge;in...

  • C语言- 链表

    C语言面向对象设计链表。可以储存任何类型使用函数指针 遍历,寻找最大值,和排序

  • 链表(c语言)

    链表的概念 创建数组时,我们会直接分配出所有我们需要的内存。但是对于链表,我们每次只分配出一个节点(node) 的...

  • C语言-链表

    线性表 线性表定义:由n个(n>=0)个数据特性相同的元素构成的有限序列称为线性表。 线性表特点:每个节点有一个直...

  • C语言链表

    1 准备 在Fedora 29中,使用下述命令安装内核源代码. 2 例子1 编写一个最简单的链表程序,3个节点依次...

  • C语言 - 链表

网友评论

      本文标题:C语言链表

      本文链接:https://www.haomeiwen.com/subject/eqquvqtx.html