有了前面Linux内核复用实现栈的基础,使用相同的思想实现队列,也是非常简单的。普通单链表复用实现队列,总会在出队或入队的时候有一个O(n)复杂度的操作,大多数采用增加两个变量,一个head,一个tail来将O(n)降成O(1)。但是在内核链表中,天然的双向循环链表,复用实现队列,无论出队还是入队,都是O(1)时间复杂度。

/* main.c   */

#include <stdio.h>
#include <stdlib.h> #include "queue.h" struct person
{
int age;
struct list_head list;
}; int main(int argc,char **argv)
{
int i;
int num =;
struct person *p;
struct person head;
struct person *pos,*n; queue_creat(&head.list); p = (struct person *)malloc(sizeof(struct person )*num); for (i = ;i < num;i++) {
p->age = i*;
in_queue(&p->list,&head.list);
p++;
}
printf("original==========>\n");
list_for_each_entry_safe(pos,n,&head.list,list) {
printf("age = %d\n",pos->age);
}
printf("size = %d\n",get_queue_size(&head.list));
struct person test;
test.age = ;
printf("out_queue %d\n",get_queue_head(pos,&head.list,list)->age);
out_queue(&head.list);
printf("out_queue %d\n",get_queue_head(pos,&head.list,list)->age);
out_queue(&head.list);
printf("in_queue %d\n",test.age);
in_queue(&test.list,&head.list); printf("current==========>\n");
list_for_each_entry_safe(pos,n,&head.list,list) {
printf("age = %d\n",pos->age);
}
printf("size = %d\n",get_queue_size(&head.list));
printf("all member out_queue\n");
list_for_each_entry_safe(pos,n,&head.list,list) {
out_queue(&head.list);
}
printf("size = %d\n",get_queue_size(&head.list));
if (is_empt_queue(&head.list)) {
printf("is_empt_queue\n");
} return ;
}
/*   queue.c  */

#include "queue.h"

void queue_creat(struct list_head *list)
{
INIT_LIST_HEAD(list);
} void in_queue(struct list_head *new, struct list_head *head)
{
list_add_tail(new,head);
} void out_queue(struct list_head *head)
{
struct list_head *list = head->next; /* 保存链表的最后节点 */ list_del(head->next);/* 头删法 */ INIT_LIST_HEAD(list); /* 重新初始化删除的最后节点,使其指向自身 */ } int get_queue_size(struct list_head *head)
{
struct list_head *pos;
int size = ; if (head == NULL) {
return -;
} list_for_each(pos,head) {
size++;
} return size; } bool is_empt_queue(struct list_head *head)
{
return list_empty(head);
}
/*  queue.h  */

#ifndef _QUEUE_H_
#define _QUEUE_H_ #include <stdbool.h>
#include "list.h" #define get_queue_head(pos, head, member) \
list_entry((head)->next, typeof(*pos), member) void queue_creat(struct list_head *list);
void in_queue(struct list_head *new, struct list_head *head);
void out_queue(struct list_head *entry);
int get_queue_size(struct list_head *head);
bool is_empt_queue(struct list_head *head); #endif /* _QUEUE_H_ */

运行结果:

复用Linux内核链表实现队列,时间复杂可以很简单的实现O(1),当然,其中的遍历队列长度是O(n),不过这个在之前的随笔中也说到了,根据具体的应用场景,可以在入队的时候在头结点中size+1,出队的时候在头结点中size-1,获取队列大小的函数就可以直接返回size了,是可以很轻易做到O(1)的时间复杂度的。掌握了Linux内核链表,链表,栈和队列这样的数据结构,就可以很容易的实现复用,并且可以应用在实际项目中。

Linux内核链表复用实现队列的更多相关文章

  1. Linux内核链表复用实现栈

    我们当然可以根据栈的特性,向实现链表一样实现栈.但是,如果能够复用已经经过实践证明的可靠数据结构来实现栈,不是可以更加高效吗? so,今天我们就复用Linux内核链表,实现栈这样的数据结构. 要实现的 ...

  2. Linux 内核 链表 的简单模拟(1)

    第零章:扯扯淡 出一个有意思的题目:用一个宏定义FIND求一个结构体struct里某个变量相对struc的编移量,如 struct student { int a; //FIND(struct stu ...

  3. 链表的艺术——Linux内核链表分析

    引言: 链表是数据结构中的重要成员之中的一个.因为其结构简单且动态插入.删除节点用时少的长处,链表在开发中的应用场景许多.仅次于数组(越简单应用越广). 可是.正如其长处一样,链表的缺点也是显而易见的 ...

  4. C语言 Linux内核链表(企业级链表)

    //Linux内核链表(企业级链表) #define _CRT_SECURE_NO_WARNINGS #include<stdio.h> #include<stdlib.h> ...

  5. 深入分析 Linux 内核链表--转

    引用地址:http://www.ibm.com/developerworks/cn/linux/kernel/l-chain/index.html 一. 链表数据结构简介 链表是一种常用的组织有序数据 ...

  6. Linux 内核链表

    一 . Linux内核链表 1 . 内核链表函数 1.INIT_LIST_HEAD:创建链表 2.list_add:在链表头插入节点 3.list_add_tail:在链表尾插入节点 4.list_d ...

  7. linux内核链表分析

    一.常用的链表和内核链表的区别 1.1  常规链表结构        通常链表数据结构至少应包含两个域:数据域和指针域,数据域用于存储数据,指针域用于建立与下一个节点的联系.按照指针域的组织以及各个节 ...

  8. 深入分析 Linux 内核链表

    转载:http://www.ibm.com/developerworks/cn/linux/kernel/l-chain/   一. 链表数据结构简介 链表是一种常用的组织有序数据的数据结构,它通过指 ...

  9. Linux 内核 链表 的简单模拟(2)

    接上一篇Linux 内核 链表 的简单模拟(1) 第五章:Linux内核链表的遍历 /** * list_for_each - iterate over a list * @pos: the & ...

随机推荐

  1. MyBatis面试题整理

    MyBatis面试题整理 1.什么是MyBatis? 答:MyBatis是一个可以自定义SQL.存储过程和高级映射的持久层框架. 2.讲下MyBatis的缓存 答:MyBatis的缓存分为一级缓存和二 ...

  2. 【转载】自定义View,有这一篇就够了

    为了扫除学习中的忙点,尽可能多的覆盖Android知识的边边角角,决定对自定义View做一个稍微全面一点的使用方法总结,在内容上面并没有什么独特的地方,其他大神们博客上面基本上都有讲这方面的内容,如果 ...

  3. LINUX基础学习之基础命令(4)和 文件的inode信息 --2019-11-28

    一.inode是什么? 理解inode,要从文件储存说起. 文件储存在硬盘上,硬盘的最小存储单位叫做”扇区”(Sector).每个扇区储存512字节(相当于0.5KB). 操作系统读取硬盘的时候,不会 ...

  4. Python pyc文件

    什么是pyc文件 pyc 是由py文件经过编译后二进制文件,py文件变成pyc文件后,加载的速度有所提高,而且pyc是一种跨平台的字节码,是由python 的虚 拟机来执行的.pyc的内容,是跟pyt ...

  5. C++学习(10)—— 对象模型和this指针

    1. 成员变量和成员函数分开存储 在C++中,类内的成员变量和成员函数分开存储 只有非静态成员变量才属于类的对象上 空对象占用内存空间为1 C++编译器会给每个空对象也分配一个字节空间,是为了区分空对 ...

  6. python正则表达式(4)--search方法

    1.re.search函数 re.search 扫描整个字符串并返回第一个成功的匹配,如果匹配失败search()就返回None. (1)函数语法: re.search(pattern, string ...

  7. 图论 - 二分图的判断(dfs染色法)

    二分图的判断(dfs染色法) 如何判断一个图是否为二分图 普通染色法模板 C++ 代码模板如下 思想:先将当前点染色,然后再将该点相连的结点进行染另外一种颜色 下面附上自己画的一张图假设我们从第一个点 ...

  8. 201671030120 王晶 实验十四 团队项目评审&课程学习总结

          项目 内容 课程名称 2016级计算机科学与工程学院软件工程(西北师范大学) 作业要求 实验十四 团队项目评审&课程学习总结 作业学习目标 (1)掌握软件项目评审会流程:(2)反思 ...

  9. 分析脚本搭建docker环境:python, R

    1. 搭建Anaconda Python3.6 FROM nvidia/cuda:8.0-cudnn6-devel-ubuntu16.04 MAINTAINER Tyan <tyan.liu.g ...

  10. Hbase扩展

    1 HBase在商业项目中的能力 每天: 1) 消息量:发送和接收的消息数超过60亿 2) 将近1000亿条数据的读写 3) 高峰期每秒150万左右操作 4) 整体读取数据占有约55%,写入占有45% ...