Linux的链表sys/queue.h

环境

Ubuntu16.04 x86_64 GNU/Linux , 4.15.0-43-generic

介绍

<sys/queue.h> 实现了5种数据结构 :

	singly-linked list  
	list 
	simple queue 
	tail queue 
	circular queue

下面对他们分别进行介绍

List

List是双向链表 : head节点不包含指向最后一个节点的指针,其结构如下图 :

在这里插入图片描述

Description :

	A list is headed by a single forward pointer (or an array of forward 
	pointers for a hash table header). The elements are doubly linked 
	so that an arbitrary element can be removed without a need to 
	traverse the list. New elements can be added to the list before
	or after an existing element or at the head of the list. A list
	may only be traversed in the forward direction.

Interface :

	LIST_INIT(head) :对head进行初始化
	LIST_INSERT_HEAD(head, elm, field) : 从list头部插入elm
	LIST_REMOVE(elm, field) : 将elm从list中删除
	LIST_INSERT_AFTER(listelm, elm, field) : 将elm插入到listelm后面
	LIST_INSERT_BEFORE(listelm, elm, field) : 将elm插入到liistelm之前
	LIST_FOREACH(var, head, field) : 循环遍历所有节点, var为中间变量 
	LIST_EMPTY(head) : 判断list是否为空
	LIST_FIRST(head) : 获取第一个节点
	LIST_NEXT(elm, field) : 获取elm的下一个节点

Example:

#include <sys/queue.h>
#include <stdlib.h>
#include <stdio.h>

struct node {
	LIST_ENTRY(node) next;
	int num;
};

LIST_HEAD(head, node);

struct head* lhead = NULL;


int main(int argc, char* argv[]){
	lhead = (struct head*)malloc(sizeof(struct head));
	LIST_INIT(lhead);
	
	struct node *var;
	struct node *num_1 = (struct node *)malloc(sizeof(struct node));
	num_1->num = 1;
	LIST_INSERT_HEAD(lhead, num_1, next);
	LIST_FOREACH(var, lhead, next){
		printf("%d->", var->num);
	}
	printf("null\n");

	struct node *num_2 = (struct node *)malloc(sizeof(struct node));
	num_2->num = 2;
	struct node *num_3 = (struct node *)malloc(sizeof(struct node));
	num_3->num = 3;
	LIST_INSERT_HEAD(lhead, num_2, next);
	LIST_INSERT_HEAD(lhead, num_3, next);
	LIST_FOREACH(var, lhead, next){
		printf("%d->", var->num);
	}
	printf("null\n");
	
	struct node *num_4 = (struct node *)malloc(sizeof(struct node));
	num_4->num = 4;
	struct node *num_5 = (struct node *)malloc(sizeof(struct node));
	num_5->num = 5;
	LIST_INSERT_BEFORE(num_3, num_4, next);
	LIST_INSERT_AFTER(num_3, num_5, next);
	LIST_FOREACH(var, lhead, next){
		printf("%d->", var->num);
	}
	printf("null\n");
	
	LIST_REMOVE(num_3, next);
	LIST_FOREACH(var, lhead, next){
		printf("%d->", var->num);
	}
	printf("null\n");
	var = LIST_NEXT(num_4, next);
	printf("4's next is %d\n", var->num);
	return 0;
}

Singly-linked list

singly-linked list 是单向链表,head不包含指向最后一个元素的指针,其结构如下图:
在这里插入图片描述

Description :

	* A singly-linked list is headed by a single forward pointer. The
	* elements are singly linked for minimum space and pointer manipulation
	* overhead at the expense of O(n) removal for arbitrary elements. New
	* elements can be added to the list after an existing element or at the
	* head of the list.  Elements being removed from the head of the list
	* should use the explicit macro for this purpose for optimum
	* efficiency. A singly-linked list may only be traversed in the forward
	* direction.  Singly-linked lists are ideal for applications with large
	* datasets and few or no removals or for implementing a LIFO queue.

Interface :

	SLIST_INIT(head) : 对head进行初始化
	SLIST_INSERT_HEAD(head, elm, field) : 从list头部插入elm
	SLIST_INSERT_AFTER(slistelm, elm, field) : 将elm 插入到slistelm后面
	SLIST_REMOVE_HEAD(head, field) : 从list的头部删除一个节点
	SLIST_REMOVE(head, elm, type, field) : 从list中删除elm
	SLIST_FOREACH(var, head, field) : 循环遍历所有节点, var为中间变量 
	SLIST_EMPTY(head) : 判断list是否为空
	SLIST_FIRST(head) : 获取第一个节点
	SLIST_NEXT(elm, field) : 获取elm的下一个节点

Example:

#include <sys/queue.h>
#include <stdlib.h>
#include <stdio.h>

struct node{
	SLIST_ENTRY(node) next;
	int num;
};
SLIST_HEAD(head, node);
struct head *lhead = 0;
int main(int argc, char* argv[]){
	lhead = (struct head*)malloc(sizeof(struct head));
	SLIST_INIT(lhead);
	
	struct node *var;

	struct node* num_1 = (struct node*)malloc(sizeof(struct node));
	num_1->num = 1;
	SLIST_INSERT_HEAD(lhead, num_1, next);
	SLIST_FOREACH(var, lhead, next){
		printf("%d->",var->num);
	}
	printf("null\n");

	struct node* num_2 = (struct node*)malloc(sizeof(struct node));
	num_2->num = 2;
	struct node* num_3 = (struct node*)malloc(sizeof(struct node));
	num_3->num = 3;	
	struct node* num_4 = (struct node*)malloc(sizeof(struct node));
	num_4->num = 4;
	SLIST_INSERT_AFTER(num_1, num_2, next);
	SLIST_INSERT_AFTER(num_1, num_3, next);
	SLIST_INSERT_AFTER(num_1, num_4, next);
	SLIST_FOREACH(var, lhead, next){
		printf("%d->",var->num);
	}
	printf("null\n");

	SLIST_REMOVE_HEAD(lhead, next);
	SLIST_FOREACH(var, lhead, next){
		printf("%d->",var->num);
	}
	printf("null\n");

	SLIST_REMOVE(lhead, num_3, node, next);
	SLIST_FOREACH(var, lhead, next){
		printf("%d->",var->num);
	}
	printf("null\n");
	return 0;
}

Singly-linked tail queue(Simple queue)

Simple queue同Singly-linked tail queue, 将接口前缀改为SIMPLEQ_ , 并且没有CONCAT方法,下面的description使用的为simple queue的description,两者的实现几乎完全一致。
Singly-linked tail queue是单向链表,head节点包含指向最后一个节点的指针,其结构图如下:
在这里插入图片描述

Description :

	* A simple queue is headed by a pair of pointers, one the head of the
	* list and the other to the tail of the list. The elements are singly
	* linked to save space, so elements can only be removed from the
	* head of the list. New elements can be added to the list after
	* an existing element, at the head of the list, or at the end of the
	* list. A simple queue may only be traversed in the forward direction.

Interface :

	STAILQ_INIT(head) : 对head进行初始化
	STAILQ_INSERT_HEAD(head, elm, field) : 从queue头部插入elm
	STAILQ_INSERT_TAIL(head, elm, field) : 从queue尾部插入elm
	STAILQ_INSERT_AFTER(head, listelm, elm, field) : 将elm 插入到listelm后面
	STAILQ_REMOVE_HEAD(head, field) : 从queue头部删去一个节点
	STAILQ_REMOVE(head, elm, type, field) : 将queue中的elm删除
	STAILQ_FOREACH(var, head, field) : 循环遍历所有节点, var为中间变量 
	STAILQ_CONCAT(head1, head2) : 将两个queue拼接,head1为拼接后的queue的头部,head2被重新初始化
	STAILQ_EMPTY(head): 判断queue是否为空
	STAILQ_FIRST(head): 获取第一个节点
	STAILQ_NEXT(elm, next): 获取elm的下一个节点

Example:

#include <sys/queue.h>
#include <stdlib.h>
#include <stdio.h>

struct node{
	STAILQ_ENTRY(node) next;
	int num;
};
STAILQ_HEAD(head, node);
struct head *lhead = 0;
struct head *llhead = 0;

int main(int argc, char* argv[]){
	lhead = (struct head*)malloc(sizeof(struct head));
	STAILQ_INIT(lhead);
	
	struct node* var = 0;
	struct node* num[9];
	for(int i=0; i<9; i++){
		num[i] = (struct node*)malloc(sizeof(struct node));
		num[i]->num = i;
	}
	STAILQ_INSERT_HEAD(lhead, num[0], next);
	STAILQ_INSERT_HEAD(lhead, num[1], next);
	STAILQ_INSERT_TAIL(lhead, num[2], next);
	STAILQ_INSERT_AFTER(lhead, num[1], num[3], next);
	STAILQ_INSERT_TAIL(lhead, num[4], next);
	STAILQ_FOREACH(var, lhead, next){
		printf("%d->", var->num);
	}
	printf("null\n");
	
	llhead = (struct head*)malloc(sizeof(struct head));
	STAILQ_INIT(llhead);
	
	STAILQ_INSERT_TAIL(llhead, num[5], next);
	STAILQ_INSERT_TAIL(llhead, num[6], next);
	STAILQ_INSERT_TAIL(llhead, num[7], next);
	STAILQ_INSERT_TAIL(llhead, num[8], next);
	STAILQ_FOREACH(var, llhead, next){
		printf("%d->", var->num);
	}
	printf("null\n");
	
	STAILQ_REMOVE(llhead, num[6], node, next);
	STAILQ_FOREACH(var, llhead, next){
		printf("%d->", var->num);
	}
	printf("null\n");
	
	STAILQ_REMOVE_HEAD(llhead, next);
	STAILQ_FOREACH(var, llhead, next){
		printf("%d->", var->num);
	}
	printf("null\n");

	STAILQ_CONCAT(lhead, llhead);
	STAILQ_FOREACH(var, lhead, next){
		printf("%d->", var->num);
	}
	printf("null\n");
	return 0;
}

Tail queue

Tail queue是 双向链,head节点包含指向最后一个节点的指针,其结构图如下:
在这里插入图片描述

Description :

	* A tail queue is headed by a pair of pointers, one to the head of the
	* list and the other to the tail of the list. The elements are doubly
	* linked so that an arbitrary element can be removed without a need to
	* traverse the list. New elements can be added to the list before or
	* after an existing element, at the head of the list, or at the end of
	* the list. A tail queue may be traversed in either direction

Interface :

	TAILQ_INIT(head) : 对head进行初始化
	TAILQ_INSERT_HEAD(head, elm, field) : 从queue头部插入elm
	TAILQ_INSERT_TAIL(head, elm, field) : 从queue尾部插入elm
	TAILQ_INSERT_AFTER(head, listelm, elm, field) :将elm 插入到listelm后面
	TAILQ_INSERT_BEFORE(listelm, elm, field) :将elm 插入到listelm前面
	TAILQ_REMOVE(head, elm, field) : 将queue中的elm删除
	TAILQ_FOREACH(var, head, field) : 正向遍历所有节点, var为中间变量
	TAILQ_FOREACH_REVERSE(var, head, headname, field): 反向遍历所有节点, var为中间变量
	TAILQ_CONCAT(head1, head2, field):将两个queue拼接,head1为拼接后的queue的头部,head2被重新初始化
	TAILQ_EMPTY(head) :判断queue是否为空
	TAILQ_FIRST(head) :获取第一个节点
	TAILQ_NEXT(elm, field) : 获取elm的下一个节点
	TAILQ_LAST(elm, headname) :获取最后一个节点
	TAILQ_PREV(elm, headname, field) : 获取elm的前一个节点

Example:

#include <sys/queue.h>
#include <stdlib.h>
#include <stdio.h>


struct node{
	TAILQ_ENTRY(node) next;
	int num;
};
TAILQ_HEAD(head, node);
struct head *lhead = 0;
struct head *llhead = 0;

int main(int argc, char* argv[]){
	lhead = (struct head*)malloc(sizeof(struct head));
	TAILQ_INIT(lhead);
	
	struct node* var = 0;
	struct node* num[9];
	for(int i=0; i<9; i++){
		num[i] = (struct node*)malloc(sizeof(struct node));
		num[i]->num = i;
	}
	TAILQ_INSERT_HEAD(lhead, num[0], next);
	TAILQ_INSERT_HEAD(lhead, num[1], next);
	TAILQ_INSERT_TAIL(lhead, num[2], next);
	TAILQ_INSERT_AFTER(lhead, num[1], num[3], next);
	TAILQ_INSERT_BEFORE(num[2], num[4], next);
	TAILQ_FOREACH(var, lhead, next){
		printf("%d->", var->num);
	}
	printf("null\n");
	
	llhead = (struct head*)malloc(sizeof(struct head));
	TAILQ_INIT(llhead);

	TAILQ_INSERT_TAIL(llhead, num[5], next);
	TAILQ_INSERT_TAIL(llhead, num[6], next);
	TAILQ_INSERT_TAIL(llhead, num[7], next);
	TAILQ_INSERT_TAIL(llhead, num[8], next);
	TAILQ_FOREACH(var, llhead, next){
		printf("%d->", var->num);
	}
	printf("null\n");
	
	TAILQ_REMOVE(llhead, num[6], next);
	TAILQ_FOREACH(var, llhead, next){
		printf("%d->", var->num);
	}
	printf("null\n");
	
	TAILQ_FOREACH_REVERSE(var, lhead, head, next){
		printf("%d->", var->num);
	}
	printf("null\n");
		
	TAILQ_CONCAT(lhead, llhead, next);
	TAILQ_FOREACH(var, lhead, next){
		printf("%d->", var->num);
	}
	printf("null\n");
	return 0;
}

Circular queue

Circular queue是环状双向链表, head节点包含指向最后一个节点的指针,最后一个节点的next指向head节点, 其结构图如下:
在这里插入图片描述

Description :

	* A circle queue is headed by a pair of pointers, one to the head of the
	* list and the other to the tail of the list. The elements are doubly
	* linked so that an arbitrary element can be removed without a need to
	* traverse the list. New elements can be added to the list before or after
	* an existing element, at the head of the list, or at the end of the list.
	* A circle queue may be traversed in either direction, but has a more
	* complex end of list detection.

Interface :

	CIRCLEQ_INIT(head) : 对head进行初始化
	CIRCLEQ_INSERT_AFTER(head, listelm, elm, field) : 将elm 插入到listelm后面
	CIRCLEQ_INSERT_BEFORE(head, listelm, elm, field) : 将elm 插入到listelm前面
	CIRCLEQ_INSERT_HEAD(head, elm, field):从queue头部插入elm
	CIRCLEQ_INSERT_TAIL(head, elm, field):从queue尾部插入elm
	CIRCLEQ_REMOVE(head, elm, field) : 将queue中的elm删除
	CIRCLEQ_FOREACH(var, head, field) : 正向遍历所有节点, var为中间变量
	CIRCLEQ_FOREACH_RESERVE(var, head, field) : 反向遍历所有节点, var为中间变量
	CIRCLEQ_EMPTY(head) : 判断queue是否为空
	CIRCLEQ_FIRST(head) : 获取第一个节点
	CIRCLEQ_LAST(head) : 获取最后一个节点
	CIRCLEQ_NEXT(elm, field) : 获取elm的下一个节点
	CIRCLEQ_PREV(elm, field) : 获取elm的上一个节点
	CIRCLEQ_LOOP_NEXT(head, elm, field) : 获取elm的下一个节点(会跳过头节点)
	CIRCLEQ_LOOP_PREV(head, elm, field) : 获取elm的上一个节点(会跳过头节点)

Example:

#include <sys/queue.h>
#include <stdlib.h>
#include <stdio.h>

struct node{
	CIRCLEQ_ENTRY(node) next;
	int num;
};
CIRCLEQ_HEAD(head, node);
struct head *lhead = 0;

int main(int argc, char* argv[]){
	lhead = (struct head*)malloc(sizeof(struct head));
	CIRCLEQ_INIT(lhead);
	
	struct node* var = 0;
	struct node* num[9];
	for(int i=0; i < 9; i++){
		num[i] = (struct node*)malloc(sizeof(struct node));
		num[i]->num = i; 
	}
	
	CIRCLEQ_INSERT_HEAD(lhead, num[0], next);
	CIRCLEQ_INSERT_HEAD(lhead, num[1], next);
	CIRCLEQ_INSERT_TAIL(lhead, num[2], next);
	CIRCLEQ_INSERT_AFTER(lhead, num[1], num[3], next);
	CIRCLEQ_INSERT_BEFORE(lhead, num[2], num[4], next);
	CIRCLEQ_FOREACH(var, lhead, next){
		printf("%d->", var->num);
	}
	printf("null\n");
	
	CIRCLEQ_REMOVE(lhead, num[0], next);
	CIRCLEQ_FOREACH(var, lhead, next){
		printf("%d->", var->num);
	}
	printf("null\n");
	
	CIRCLEQ_FOREACH_REVERSE(var, lhead, next){
		printf("%d->", var->num);
	}
	printf("null\n");
	return 0;
}
  • 0
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值