linux内核的xdr实现,Linux内核链表复用实现队列

3701a88193d686d944fd8cd1a91171df.png

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

/* main.c */

#include

#include

#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

#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_ */

运行结果:

ba9cd35024bbede38533fe7769d0e8dc.png

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

Linux内核链表复用实现栈

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

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

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

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

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

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

//Linux内核链表(企业级链表) #define _CRT_SECURE_NO_WARNINGS #include #include ...

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

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

Linux 内核链表

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

linux内核链表分析

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

深入分析 Linux 内核链表

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

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

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

随机推荐

Application Engine

Exit(1) : Terminate the AE immediately and rollback all DB changes madeexit(0) : Terminate the AE im ...

Java线程面试题 Top 50 (转载)

转载自:http://www.cnblogs.com/dolphin0520/p/3958019.html 原文链接:http://www.importnew.com/12773.html   本文由 ...

Spring容器的工具类

代码实现: package com.ht.util; import java.util.Map; import org.springframework.beans.BeansException; im ...

Session()

如何使用 Session Java Api 只给我们一种方式来 获取 当前会话相关的 session: HttpSession session = request.getSession(); //或 ...

java -D參数简化增加多个jar【简化设置classpath】

1.-D= set a system property  设置系统属性. java命令引入jar时能够-cp參数,但时-cp不能用通配符(多个jar时 ...

delphi字符串操作函数一览

首部 function SameText(const S1, S2: string): Boolean; $[SysUtils.pas 功能 返回两个字符串是否相等 说明 不区分大小写 参考 < ...

HDU 5608 function &lbrack;杜教筛&rsqb;

HDU 5608 function 题意:数论函数满足\(N^2-3N+2=\sum_{d|N} f(d)\),求前缀和 裸题-连卷上\(1\)都告诉你了 预处理\(S(n)\)的话反演一下用枚举倍数 ...

HTML5 拖拽实现

简介: 最早在网页中引入JavaScript拖放功能是IE4.当时,网页中只有两种对象可以拖放:图像和某些文本.拖放图像时,把鼠标放到图像上,按住鼠标不放就可以拖放它.拖放文本时,要先选中文本,然后可 ...

Linux强制杀进程命令行工具

需求, 有时候我们会有手动启动程序, 但是又在后台, 没有像服务那样有start, 和stop的程序, 这时候需要用强制杀进程方式 涉及工具, awk, sed, xargs, kill 需求一: 已 ...

windows7 安装IIS没有default web site 解决方法

因当时是第一次在Windows 7上使用IIS,不小心把default web site删除了,后来无论怎么重装IIS都不行,最后想到能不能直接把别人安装好后的IIS相关文件夹拷过来使用,用宿舍一哥们 ...

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值