关于SLIST,STAILQ,LIST,TAILQ,CIRCLEQ图示详解

一,前述

由于接触蓝牙协议栈相关工作,涉及很多mbuf,mqueue的操作,其中不乏Berkeley queue的身影,故因此,深入了解一下链表以及队列相关操作,九几年的代码放在现在依旧经典,需要深入琢磨多次!该部分包含5个部分,单向链表,双向链表,队列,尾队列,环形队列。

(注:在此之后,将依赖此深入了解mbuf与mqueue)

文件索引地址:https://github.com/torvalds/linux/blob/master/drivers/scsi/aic7xxx/queue.h

二,Singly-Linked List,SLIST

俗称:单向链表

1,声明
// 用于定义一个单向链表数据结构体的头变量,该结构体只有一个指针成员slh_first,指向第一个type类型的数据结构;
#define	SLIST_HEAD(name, type)                          \
struct name {                                           \
    struct type *slh_first;	/* first element */         \
}

// 用于在定义时初始化SLIST_HEAD定义的数据结构体的头变量;
#define	SLIST_HEAD_INITIALIZER(head)                    \
    { NULL }

// 用于定义一个(用户)结构体的成员变量,该成员变量只包含一个指向type类型的指针sle_next;
#define	SLIST_ENTRY(type)                               \
struct {                                                \
    struct type *sle_next;  /* next element */          \
}
2,函数
// 用于判断单向链表是否为空:空则返回true,否则返回false;
#define SLIST_EMPTY(head)   ((head)->slh_first == NULL)

// 用于获取单向链表的第一个元素;
#define SLIST_FIRST(head)   ((head)->slh_first)

// 用于遍历单向链表,var是临时变量,head是链表头指针(SLIST_HEAD定义的变量),field是SLIST_ENTRY定义的成员变量名;
#define SLIST_FOREACH(var, head, field)                 \
    for ((var) = SLIST_FIRST((head));                   \
        (var);                                          \
        (var) = SLIST_NEXT((var), field))

// 用于初始化SLIST_HEAD定义的头指针变量;
#define SLIST_INIT(head) do {                           \
        SLIST_FIRST((head)) = NULL;                     \
} while (0)

// 用于将元素elm插入到当前链表元素slistelm的后面;
#define SLIST_INSERT_AFTER(slistelm, elm, field) do {           \
    SLIST_NEXT((elm), field) = SLIST_NEXT((slistelm), field);   \
    SLIST_NEXT((slistelm), field) = (elm);                      \
} while (0)

// 用于将元素elm插入到当前链表head的头部;head是SLIST_HEAD定义的链表头指针;
#define SLIST_INSERT_HEAD(head, elm, field) do {            \
    SLIST_NEXT((elm), field) = SLIST_FIRST((head));         \
    SLIST_FIRST((head)) = (elm);                            \
} while (0)

// 用于获取elm元素的下一个元素,field是前面用SLIST_ENTRY定义的成员变量名;
#define SLIST_NEXT(elm, field)	((elm)->field.sle_next)

// 用于从head链表中删除elm元素;注意首先判断elm元素是否在head链表中,否则会崩溃;
#define SLIST_REMOVE(head, elm, type, field) do {           \
    if (SLIST_FIRST((head)) == (elm)) {                     \
        SLIST_REMOVE_HEAD((head), field);                   \
    }                                                       \
    else {                                                  \
        struct type *curelm = SLIST_FIRST((head));          \
        while (SLIST_NEXT(curelm, field) != (elm))          \
            curelm = SLIST_NEXT(curelm, field);             \
        SLIST_NEXT(curelm, field) =                         \
            SLIST_NEXT(SLIST_NEXT(curelm, field), field);   \
    }                                                       \
} while (0)

// 用于删除第一个元素;注意删除时判断head是否为空,否则会崩溃;
#define SLIST_REMOVE_HEAD(head, field) do {                         \
    SLIST_FIRST((head)) = SLIST_NEXT(SLIST_FIRST((head)), field);   \
} while (0)
3,模型

SLIST

4,验证例程
#include <stdio.h>
#include <stdlib.h>
#include <sys/queue.h>

struct SLIST_ITEM {
	int value;
	SLIST_ENTRY(SLIST_ITEM) entry;
};

static SLIST_HEAD(,SLIST_ITEM) slist_head;

int main(int argc, char *argv[])
{
	int i = 0;
	struct SLIST_ITEM *item;
	struct SLIST_ITEM *tmp_item;

	SLIST_INIT(&slist_head);

	if (SLIST_EMPTY(&slist_head)) {
		printf("single list is empty\n");
    }

	for( i = 0; i < 10; i ++) {
		item = (struct SLIST_ITEM *)malloc(sizeof(struct SLIST_ITEM));
		item->value = i;
        // 头部插入:即9,8,7,6,5,4,3,2,1,0
        // 用于将元素item插入到当前链表slist_head的头部
		SLIST_INSERT_HEAD(&slist_head, item, entry);
	}
    
    for( i = 0; i < 10; i ++) {
		tmp_item = (struct SLIST_ITEM *)malloc(sizeof(struct SLIST_ITEM));
		tmp_item->value = i + 10;
        // 尾部插入:即9,10,11,12...19,8,7,..1,0
        // 用于将元素tmp_item插入到item的后面
		SLIST_INSERT_AFTER(item, tmp_item, entry);
        // 置换位置,让下一个元素在当前元素之后
        item = tmp_item;
	}
    
	printf("after insert 10 item to single list:\n");
	SLIST_FOREACH(item, &slist_head, entry)
        printf("Has Item pointer = %p, item value = %d\n", item, item->value);

	SLIST_FOREACH(tmp_item, &slist_head, entry) {
	    // 将删除1.3.5.7.9...
	    // 用于从slist_head链表中删除tmp_item元素
		if(tmp_item->value % 2 != 0) {
            printf("Remove item pointer = %p, item value = %d\n", tmp_item, tmp_item->value);
			SLIST_REMOVE(&slist_head, tmp_item, SLIST_ITEM, entry);
            free(tmp_item);
		}
	}

	printf("after delete items from single list, the rest:\n");
	SLIST_FOREACH(item, &slist_head, entry)
        printf("Has Item pointer = %p, item value = %d\n", item, item->value);

    SLIST_FOREACH(tmp_item, &slist_head, entry) {
        // 删除slist_head链表中头部元素
        printf("Remove head item pointer = %p, item value = %d\n", tmp_item, tmp_item->value);
        SLIST_REMOVE_HEAD(&slist_head, entry);
        free(tmp_item);
    }
    
    if (SLIST_EMPTY(&slist_head)) {
		printf("single list is empty!!!\n");
    }

	return 0;
}

三,Singly-linked Tail Queue,STAILQ

俗称:单向有尾队列

1,声明
// 用于定义一个单向有尾队列数据结构体的头变量,该结构体有两个指针成员stqh_first和stqh_last,分别指向第一个type类型的数据结构,和最后一个type类型的数据结构;
#define	STAILQ_HEAD(name, type)						\
struct name {								\
	struct type *stqh_first;/* first element */			\
	struct type **stqh_last;/* addr of last next element */		\
}

// 用于在定义时初始化STAILQ_HEAD定义的数据结构体的头变量;
#define	STAILQ_HEAD_INITIALIZER(head)					\
	{ NULL, &(head).stqh_first }

// 用于定义一个(用户)结构体的成员变量,该成员变量只包含一个指向type类型的指针stqe_next;
#define	STAILQ_ENTRY(type)						\
struct {								\
	struct type *stqe_next;	/* next element */			\
}
2,函数
// 用于判断单向有尾队列是否为空:空则返回true,否则返回false;
#define	STAILQ_EMPTY(head)	((head)->stqh_first == NULL)

// 用于返回单向有尾队列的第一个元素;
#define	STAILQ_FIRST(head)	((head)->stqh_first)

// 用于遍历单向有尾队列,var是临时变量,head是链表头指针(STAILQ_HEAD定义的变量指针),field是STAILQ_ENTRY定义的成员变量名,headname是用户自定义的数据类型;
#define	STAILQ_FOREACH(var, head, field)				\
	for((var) = STAILQ_FIRST((head));				\
	   (var);							\
	   (var) = STAILQ_NEXT((var), field))

// 用于初始化STAILQ_HEAD定义的头指针变量;
#define	STAILQ_INIT(head) do {						\
	STAILQ_FIRST((head)) = NULL;					\
	(head)->stqh_last = &STAILQ_FIRST((head));			\
} while (0)

// 用于将元素elm插入到单向有尾队列head的tqelm后面;head是STAILQ_HEAD定义的链表头指针;
#define	STAILQ_INSERT_AFTER(head, tqelm, elm, field) do {		\
	if ((STAILQ_NEXT((elm), field) = STAILQ_NEXT((tqelm), field)) == NULL)\
		(head)->stqh_last = &STAILQ_NEXT((elm), field);		\
	STAILQ_NEXT((tqelm), field) = (elm);				\
} while (0)

// 用于将元素elm插入到单向有尾队列head的头部;head是STAILQ_HEAD定义的链表头指针;
#define	STAILQ_INSERT_HEAD(head, elm, field) do {			\
	if ((STAILQ_NEXT((elm), field) = STAILQ_FIRST((head))) == NULL)	\
		(head)->stqh_last = &STAILQ_NEXT((elm), field);		\
	STAILQ_FIRST((head)) = (elm);					\
} while (0)

// 用于将元素elm插入到单向有尾队列head的尾部;head是STAILQ_HEAD定义的链表头指针;
#define	STAILQ_INSERT_TAIL(head, elm, field) do {			\
	STAILQ_NEXT((elm), field) = NULL;				\
	*(head)->stqh_last = (elm);					\
	(head)->stqh_last = &STAILQ_NEXT((elm), field);			\
} while (0)

// 用于获取单向有尾队列的最后一个元素;
#define	STAILQ_LAST(head, type, field)					\
	(STAILQ_EMPTY(head) ?						\
		NULL :							\
	        ((struct type *)					\
		((char *)((head)->stqh_last) - offsetof(struct type, field))))

// 用于获取单向有尾队列elm的下一个元素;field是前面用STAILQ_ENTRY定义的成员变量名;
#define	STAILQ_NEXT(elm, field)	((elm)->field.stqe_next)

// 用于单向有尾队列head中删除elm元素;
#define	STAILQ_REMOVE(head, elm, type, field) do {			\
	if (STAILQ_FIRST((head)) == (elm)) {				\
		STAILQ_REMOVE_HEAD(head, field);			\
	}								\
	else {								\
		struct type *curelm = STAILQ_FIRST((head));		\
		while (STAILQ_NEXT(curelm, field) != (elm))		\
			curelm = STAILQ_NEXT(curelm, field);		\
		if ((STAILQ_NEXT(curelm, field) =			\
		     STAILQ_NEXT(STAILQ_NEXT(curelm, field), field)) == NULL)\
			(head)->stqh_last = &STAILQ_NEXT((curelm), field);\
	}								\
} while (0)

// 用于单向有尾队列head中删除头部;
#define	STAILQ_REMOVE_HEAD(head, field) do {				\
	if ((STAILQ_FIRST((head)) =					\
	     STAILQ_NEXT(STAILQ_FIRST((head)), field)) == NULL)		\
		(head)->stqh_last = &STAILQ_FIRST((head));		\
} while (0)

// 用于单向有尾队列head中删除从头部至elm元素;
#define	STAILQ_REMOVE_HEAD_UNTIL(head, elm, field) do {			\
	if ((STAILQ_FIRST((head)) = STAILQ_NEXT((elm), field)) == NULL)	\
		(head)->stqh_last = &STAILQ_FIRST((head));		\
} while (0)

// 用于单向有尾队列head中删除elm之后的元素;
#define STAILQ_REMOVE_AFTER(head, elm, field) do {			\
	if ((STAILQ_NEXT(elm, field) =					\
	     STAILQ_NEXT(STAILQ_NEXT(elm, field), field)) == NULL)	\
		(head)->stqh_last = &STAILQ_NEXT((elm), field);		\
} while (0)
3,模型

STQILQ

4,验证例程
#include <stddef.h>
#include <stdio.h>
#include <stdlib.h>
#include <sys/queue.h>

struct entry {
    int value;
    STAILQ_ENTRY(entry) entries;        /* Singly linked tail queue */
};

static STAILQ_HEAD(stailhead, entry) stailq_head;

int
main(void)
{
    struct entry *item1, *item2, *item3, *item_temp;

    STAILQ_INIT(&stailq_head);                                  /* Initialize the queue */

    if(STAILQ_EMPTY(&stailq_head)) {
        printf("stailq_head is NULL\n");
    }

    item1 = malloc(sizeof(struct entry));
    item1->value = 1;
    STAILQ_INSERT_HEAD(&stailq_head, item1, entries);           /* Insert at the stailq_head */

    item1 = malloc(sizeof(struct entry));
    item1->value = 2;
    STAILQ_INSERT_TAIL(&stailq_head, item1, entries);           /* Insert at the tail */

    item2 = malloc(sizeof(struct entry));
    item2->value = 3;
    STAILQ_INSERT_AFTER(&stailq_head, item1, item2, entries);   /* Insert after */

    STAILQ_FOREACH(item_temp, &stailq_head, entries)
        printf("Has Item pointer = %p, item value = %d\n", item_temp, item_temp->value);

    STAILQ_REMOVE(&stailq_head, item2, entry, entries);         /* Deletion */
    free(item2);

    item3 = STAILQ_FIRST(&stailq_head);
    STAILQ_REMOVE_HEAD(&stailq_head, entries);                  /* Deletion from the stailq_head */
    free(item3);

    printf("After do STAILQ_INSERT_HEAD\n");

    item1 = STAILQ_FIRST(&stailq_head);
    item1->value = 0;

    for (int i = 1; i < 10; i++) {
        item1 = malloc(sizeof(struct entry));
        item1->value = i;

        // 头插:9,8, ... 4, 3, 2, 1, 0
        STAILQ_INSERT_HEAD(&stailq_head, item1, entries);
    }

    STAILQ_FOREACH(item_temp, &stailq_head, entries)
        printf("Has Item pointer = %p, item value = %d\n", item_temp, item_temp->value);

    printf("After do STAILQ_INSERT_TAIL\n");

    for (int i = 1; i < 10; i++) {
        item1 = malloc(sizeof(struct entry));
        item1->value = i + 10;

        // 头插:9,8, ... 4, 3, 2, 1, 0
        STAILQ_INSERT_TAIL(&stailq_head, item1, entries);
    }
    STAILQ_FOREACH(item_temp, &stailq_head, entries)
        printf("Has Item pointer = %p, item value = %d\n", item_temp, item_temp->value);

    printf("After do STAILQ_INSERT_AFTER\n");

    item_temp = item1;
    for (int i = 1; i < 10; i++) {
        item1 = malloc(sizeof(struct entry));
        item1->value = i + 20;

        // 头插:9,8, ... 4, 3, 2, 1, 0
        STAILQ_INSERT_AFTER(&stailq_head, item_temp, item1, entries);
        item_temp = item1;
    }
    STAILQ_FOREACH(item_temp, &stailq_head, entries)
        printf("Has Item pointer = %p, item value = %d\n", item_temp, item_temp->value);

    // printf("After do STAILQ_REMOVE_HEAD_UNTIL\n");

    // item_temp = STAILQ_FIRST(&stailq_head);
    // while (item_temp != NULL) {
    //     if(item_temp->value == 6) {
    //         // STAILQ_REMOVE_AFTER(&stailq_head, item_temp, entries);
    //         // STAILQ_REMOVE_HEAD(&stailq_head, entries); 
    //         // if ((STAILQ_FIRST((&stailq_head)) = STAILQ_NEXT((item_temp), entries)) == NULL)	
	// 	    //     (&stailq_head)->stqh_last = &STAILQ_FIRST((&stailq_head));
    //     }
    //     item_temp = STAILQ_NEXT(item_temp, entries);
    // }
    // STAILQ_FOREACH(item_temp, &stailq_head, entries)
    //     printf("Has Item pointer = %p, item value = %d\n", item_temp, item_temp->value);

    printf("After do DELETE ALL ELEMENTS\n");
    // 删除所有元素
    item1 = STAILQ_FIRST(&stailq_head);
    while (item1 != NULL) {
        item2 = STAILQ_NEXT(item1, entries);
        free(item1);
        item1 = item2;
    }
    STAILQ_INIT(&stailq_head);

    if(STAILQ_EMPTY(&stailq_head)) {
        printf("stailq_head is NULL\n");
    }

    exit(EXIT_SUCCESS);
}

四,Linked List,LIST

俗称:双向链表

1,声明
// 用于定义一个双向链表数据结构体的头变量,该结构体只有一个指针成员lh_first,指向第一个type类型的数据结构;
#define	LIST_HEAD(name, type)						\
struct name {								\
	struct type *lh_first;	/* first element */			\
}

// 用于在定义时初始化LIST_HEAD定义的数据结构体的头变量;
#define	LIST_HEAD_INITIALIZER(head)					\
	{ NULL }

// 用于定义一个(用户)结构体的成员变量,该成员变量包含两个指向type类型的指针le_next、le_prev;
#define	LIST_ENTRY(type)						\
struct {								\
	struct type *le_next;	/* next element */			\
	struct type **le_prev;	/* address of previous next element */	\
}

2,函数
// 用于判断双向链表是否为空:空则返回true,否则返回false;
#define	LIST_EMPTY(head)	((head)->lh_first == NULL)

// 用于获取双向链表的第一个元素;
#define	LIST_FIRST(head)	((head)->lh_first)

// 用于正向遍历双向链表,var是临时变量,head是链表头指针(LIST_HEAD定义的变量),field是LIST_ENTRY定义的成员变量名;
#define	LIST_FOREACH(var, head, field)					\
	for ((var) = LIST_FIRST((head));				\
	    (var);							\
	    (var) = LIST_NEXT((var), field))

// 用于初始化LIST_HEAD定义的头指针变量;当然也可以在使用LIST_HEAD定义头指针变量时同时使用
#define	LIST_INIT(head) do {						\
	LIST_FIRST((head)) = NULL;					\
} while (0)

// 用于将元素elm插入到当前链表元素listelm的后面;
#define	LIST_INSERT_AFTER(listelm, elm, field) do {			\
	if ((LIST_NEXT((elm), field) = LIST_NEXT((listelm), field)) != NULL)\
		LIST_NEXT((listelm), field)->field.le_prev =		\
		    &LIST_NEXT((elm), field);				\
	LIST_NEXT((listelm), field) = (elm);				\
	(elm)->field.le_prev = &LIST_NEXT((listelm), field);		\
} while (0)

// 用于将元素elm插入到当前链表元素listelm的前面;
#define	LIST_INSERT_BEFORE(listelm, elm, field) do {			\
	(elm)->field.le_prev = (listelm)->field.le_prev;		\
	LIST_NEXT((elm), field) = (listelm);				\
	*(listelm)->field.le_prev = (elm);				\
	(listelm)->field.le_prev = &LIST_NEXT((elm), field);		\
} while (0)

// 用于将元素elm插入到当前链表head的头部;head是LIST_HEAD定义的链表头指针;
#define	LIST_INSERT_HEAD(head, elm, field) do {				\
	if ((LIST_NEXT((elm), field) = LIST_FIRST((head))) != NULL)	\
		LIST_FIRST((head))->field.le_prev = &LIST_NEXT((elm), field);\
	LIST_FIRST((head)) = (elm);					\
	(elm)->field.le_prev = &LIST_FIRST((head));			\
} while (0)

// 用于获取elm元素的下一个元素,field是前面用LIST_ENTRY定义的成员变量名;
#define	LIST_NEXT(elm, field)	((elm)->field.le_next)

// 用于将elm元素从链表中删除;注意首先确定elm元素确实在链表中,否则会崩溃;
#define	LIST_REMOVE(elm, field) do {					\
	if (LIST_NEXT((elm), field) != NULL)				\
		LIST_NEXT((elm), field)->field.le_prev = 		\
		    (elm)->field.le_prev;				\
	*(elm)->field.le_prev = LIST_NEXT((elm), field);		\
} while (0)
3,模型

LIST

4,验证例程
#include <stdio.h>
#include <stdlib.h>
#include <sys/queue.h>

struct LIST_ITEM {
	int value;
	LIST_ENTRY(LIST_ITEM) entry;
};

static LIST_HEAD(,LIST_ITEM) slist_head;

int main(int argc, char *argv[])
{
	int i = 0;
	struct LIST_ITEM *item;
	struct LIST_ITEM *tmp_item;

	LIST_INIT(&slist_head);

	if (LIST_EMPTY(&slist_head))
		printf("List is empty\n");

	printf("after do LIST_INSERT_HEAD:\n");
	for( i = 0; i < 10; i ++) {
		item = (struct LIST_ITEM *)malloc(sizeof(struct LIST_ITEM));
		item->value = i;
		LIST_INSERT_HEAD(&slist_head, item, entry);
	}

	LIST_FOREACH(tmp_item, &slist_head, entry)
        printf("Has Item pointer = %p, item value = %d\n", tmp_item, tmp_item->value);

	printf("after do LIST_INSERT_AFTER:\n");
	for( i = 0; i < 10; i ++) {
		tmp_item = (struct LIST_ITEM *)malloc(sizeof(struct LIST_ITEM));
		tmp_item->value = i + 10;
		// LIST_INSERT_AFTER(item, tmp_item, entry);
		LIST_INSERT_BEFORE(item, tmp_item, entry);
		item = tmp_item;
	}

	LIST_FOREACH(tmp_item, &slist_head, entry)
        printf("Has Item pointer = %p, item value = %d\n", tmp_item, tmp_item->value);

	printf("after do LIST_REMOVE:\n");
	LIST_FOREACH(tmp_item, &slist_head, entry) {
		LIST_REMOVE(tmp_item, entry);
		free(tmp_item);
	}

	LIST_FOREACH(tmp_item, &slist_head, entry)
        printf("Has Item pointer = %p, item value = %d\n", tmp_item, tmp_item->value);

	if (LIST_EMPTY(&slist_head))
		printf("List is empty\n");

    exit(EXIT_SUCCESS);

	return 0;
}

五,Tail Queue,TAILQ

俗称:尾队列

1,声明
// 用于定义一个尾队列数据结构体的头变量,该结构体有两个指针成员tqh_first和tqh_last,分别指向第一个type类型的数据结构,和最后一个type类型的数据结构;
#define	TAILQ_HEAD(name, type)						\
struct name {								\
	struct type *tqh_first;	/* first element */			\
	struct type **tqh_last;	/* addr of last next element */		\
}

// 用于在定义时初始化TAILQ_HEAD定义的数据结构体的头变量;
#define	TAILQ_HEAD_INITIALIZER(head)					\
	{ NULL, &(head).tqh_first }


// 用于定义一个(用户)结构体的成员变量,该成员变量包含两个指向type类型的指针tqe_next和tqe_prev;
#define	TAILQ_ENTRY(type)						\
struct {								\
	struct type *tqe_next;	/* next element */			\
	struct type **tqe_prev;	/* address of previous next element */	\
}
2,函数
// 用于判定尾队列是否为空,空则返回true,非空则为false
#define	TAILQ_EMPTY(head)	((head)->tqh_first == NULL)

// 用于获取尾队列的第一个元素;
#define	TAILQ_FIRST(head)	((head)->tqh_first)

// 用于正向遍历尾队列,var是临时变量,head是链表头指针(TAILQ_HEAD定义的变量指针),field是TAILQ_ENTRY定义的成员变量名,headname是用户自定义的数据类型;
#define	TAILQ_FOREACH(var, head, field)					\
	for ((var) = TAILQ_FIRST((head));				\
	    (var);							\
	    (var) = TAILQ_NEXT((var), field))

// 用于正向遍历尾队列,var是临时变量,head是链表头指针(TAILQ_HEAD定义的变量指针),field是TAILQ_ENTRY定义的成员变量名,headname是用户自定义的数据类型;
#define	TAILQ_FOREACH_REVERSE(var, head, headname, field)		\
	for ((var) = TAILQ_LAST((head), headname);			\
	    (var);							\
	    (var) = TAILQ_PREV((var), headname, field))

// 用于正向遍历尾队列,var是临时变量,head是链表头指针(TAILQ_HEAD定义的变量指针),field是TAILQ_ENTRY定义的成员变量名,headname是用户自定义的数据类型;
#define	TAILQ_INIT(head) do {						\
	TAILQ_FIRST((head)) = NULL;					\
	(head)->tqh_last = &TAILQ_FIRST((head));			\
} while (0)

// 用于将元素elm插入到尾队列head的listelm后面;head是TAILQ_HEAD定义的链表头指针;
#define	TAILQ_INSERT_AFTER(head, listelm, elm, field) do {		\
	if ((TAILQ_NEXT((elm), field) = TAILQ_NEXT((listelm), field)) != NULL)\
		TAILQ_NEXT((elm), field)->field.tqe_prev = 		\
		    &TAILQ_NEXT((elm), field);				\
	else								\
		(head)->tqh_last = &TAILQ_NEXT((elm), field);		\
	TAILQ_NEXT((listelm), field) = (elm);				\
	(elm)->field.tqe_prev = &TAILQ_NEXT((listelm), field);		\
} while (0)

// 用于将元素elm插入到尾队列中listelm元素前面;
#define	TAILQ_INSERT_BEFORE(listelm, elm, field) do {			\
	(elm)->field.tqe_prev = (listelm)->field.tqe_prev;		\
	TAILQ_NEXT((elm), field) = (listelm);				\
	*(listelm)->field.tqe_prev = (elm);				\
	(listelm)->field.tqe_prev = &TAILQ_NEXT((elm), field);		\
} while (0)

// 用于将元素elm插入到尾队列head的头部;head是TAILQ_HEAD定义的链表头指针;
#define	TAILQ_INSERT_HEAD(head, elm, field) do {			\
	if ((TAILQ_NEXT((elm), field) = TAILQ_FIRST((head))) != NULL)	\
		TAILQ_FIRST((head))->field.tqe_prev =			\
		    &TAILQ_NEXT((elm), field);				\
	else								\
		(head)->tqh_last = &TAILQ_NEXT((elm), field);		\
	TAILQ_FIRST((head)) = (elm);					\
	(elm)->field.tqe_prev = &TAILQ_FIRST((head));			\
} while (0)

// 用于将元素elm插入到尾队列head的尾部;head是TAILQ_HEAD定义的链表头指针;
#define	TAILQ_INSERT_TAIL(head, elm, field) do {			\
	TAILQ_NEXT((elm), field) = NULL;				\
	(elm)->field.tqe_prev = (head)->tqh_last;			\
	*(head)->tqh_last = (elm);					\
	(head)->tqh_last = &TAILQ_NEXT((elm), field);			\
} while (0)

// 用于获取尾队列的最后一个元素,headname是用户自定义的数据类型;
#define	TAILQ_LAST(head, headname)					\
	(*(((struct headname *)((head)->tqh_last))->tqh_last))

// 用于获取elm元素的下一个元素,field是前面用TAILQ_ENTRY定义的成员变量名;
#define	TAILQ_NEXT(elm, field) ((elm)->field.tqe_next)

// 用于获取elm元素的前面一个元素,headname是用户自定义的数据类型;
#define	TAILQ_PREV(elm, headname, field)				\
	(*(((struct headname *)((elm)->field.tqe_prev))->tqh_last))

// 用于尾队列head中删除elm元素;
#define	TAILQ_REMOVE(head, elm, field) do {				\
	if ((TAILQ_NEXT((elm), field)) != NULL)				\
		TAILQ_NEXT((elm), field)->field.tqe_prev = 		\
		    (elm)->field.tqe_prev;				\
	else								\
		(head)->tqh_last = (elm)->field.tqe_prev;		\
	*(elm)->field.tqe_prev = TAILQ_NEXT((elm), field);		\
} while (0)
3,模型

TAILQ

4,验证例程
#include <stdio.h>
#include <stdlib.h>
#include <sys/queue.h>

struct QUEUE_ITEM {
	int value;
	TAILQ_ENTRY(QUEUE_ITEM) entry;
};

static TAILQ_HEAD(,QUEUE_ITEM) queue_head;

int main(int argc, char *argv[])
{
	int i = 0;
	struct QUEUE_ITEM *item;
	struct QUEUE_ITEM *tmp_item;

	TAILQ_INIT(&queue_head);

	if (TAILQ_EMPTY(&queue_head))
		printf("queue is empty\n");

	printf("after do TAILQ_INSERT_HEAD\n");
	for( i = 0; i < 10; i ++) {
		item = (struct QUEUE_ITEM *)malloc(sizeof(struct QUEUE_ITEM));
		item->value = i;
		TAILQ_INSERT_HEAD(&queue_head, item, entry);
	}
	TAILQ_FOREACH(tmp_item, &queue_head, entry)
        printf("Has Item pointer = %p, item value = %d\n", tmp_item, tmp_item->value);

	printf("after do TAILQ_INSERT_TAIL\n");
	for( i = 0; i < 10; i ++) {
		item = (struct QUEUE_ITEM *)malloc(sizeof(struct QUEUE_ITEM));
		item->value = i + 10;
		TAILQ_INSERT_TAIL(&queue_head, item, entry);
	}
	TAILQ_FOREACH(tmp_item, &queue_head, entry)
        printf("Has Item pointer = %p, item value = %d\n", tmp_item, tmp_item->value);

	printf("after do TAILQ_REMOVE\n");
	TAILQ_FOREACH(tmp_item, &queue_head, entry) {
		TAILQ_REMOVE(&queue_head, tmp_item, entry);
		free(tmp_item);
	}

	if (TAILQ_EMPTY(&queue_head))
		printf("queue is empty\n");

    exit(EXIT_SUCCESS);

	return 0;
}

六,Circular Queue,CIRCLEQ

俗称:环形队列

1,声明
// 用于定义一个环形队列数据结构体的头变量,该结构体有两个指针成员cqh_first和cqh_last,分别指向第一个type类型的数据结构,和最后一个type类型的数据结构;
#define	CIRCLEQ_HEAD(name, type)					\
struct name {								\
	struct type *cqh_first;		/* first element */		\
	struct type *cqh_last;		/* last element */		\
}

// 用于在定义时初始化CIRCLEQ_HEAD定义的数据结构体的头变量;
#define	CIRCLEQ_HEAD_INITIALIZER(head)					\
	{ (void *)&(head), (void *)&(head) }

// 则用于定义一个(用户)结构体的成员变量,该成员变量包含两个指向type类型的指针cqe_next和cqe_prev;
#define	CIRCLEQ_ENTRY(type)						\
struct {								\
	struct type *cqe_next;		/* next element */		\
	struct type *cqe_prev;		/* previous element */		\
}

2,函数
// 用于判断环形队列是否为空:空则返回true,否则返回false;
#define	CIRCLEQ_EMPTY(head)	((head)->cqh_first == (void *)(head))

// 用于获取环形队列的第一个元素;
#define	CIRCLEQ_FIRST(head)	((head)->cqh_first)

// 用于正向遍历环形队列,var是临时变量,head是链表头指针(CIRCLEQ_HEAD定义的变量指针),field是CIRCLEQ_ENTRY定义的成员变量名;
#define	CIRCLEQ_FOREACH(var, head, field)				\
	for ((var) = CIRCLEQ_FIRST((head));				\
	    (var) != (void *)(head) || ((var) = NULL);			\
	    (var) = CIRCLEQ_NEXT((var), field))

// 用于逆向遍历环形队列,var是临时变量,head是链表头指针(CIRCLEQ_HEAD定义的变量指针),field是CIRCLEQ_ENTRY定义的成员变量名;
#define	CIRCLEQ_FOREACH_REVERSE(var, head, field)			\
	for ((var) = CIRCLEQ_LAST((head));				\
	    (var) != (void *)(head) || ((var) = NULL);			\
	    (var) = CIRCLEQ_PREV((var), field))

// 用于初始化CIRCLEQ_HEAD定义的头指针变量;当然也可以在使用CIRCLEQ_HEAD定义头指针变量时同时使用CIRCLEQ_HEAD_INITIALIZER进行初始化;
#define	CIRCLEQ_INIT(head) do {						\
	CIRCLEQ_FIRST((head)) = (void *)(head);				\
	CIRCLEQ_LAST((head)) = (void *)(head);				\
} while (0)

// 用于将元素elm插入到环形队列head的listelm元素后面;head是CIRCLEQ_HEAD定义的链表头指针;
#define	CIRCLEQ_INSERT_AFTER(head, listelm, elm, field) do {		\
	CIRCLEQ_NEXT((elm), field) = CIRCLEQ_NEXT((listelm), field);	\
	CIRCLEQ_PREV((elm), field) = (listelm);				\
	if (CIRCLEQ_NEXT((listelm), field) == (void *)(head))		\
		CIRCLEQ_LAST((head)) = (elm);				\
	else								\
		CIRCLEQ_PREV(CIRCLEQ_NEXT((listelm), field), field) = (elm);\
	CIRCLEQ_NEXT((listelm), field) = (elm);				\
} while (0)

// 用于将元素elm插入到环形队列head的listelm元素前面;head是CIRCLEQ_HEAD定义的链表头指针;
#define	CIRCLEQ_INSERT_BEFORE(head, listelm, elm, field) do {		\
	CIRCLEQ_NEXT((elm), field) = (listelm);				\
	CIRCLEQ_PREV((elm), field) = CIRCLEQ_PREV((listelm), field);	\
	if (CIRCLEQ_PREV((listelm), field) == (void *)(head))		\
		CIRCLEQ_FIRST((head)) = (elm);				\
	else								\
		CIRCLEQ_NEXT(CIRCLEQ_PREV((listelm), field), field) = (elm);\
	CIRCLEQ_PREV((listelm), field) = (elm);				\
} while (0)

// 用于将元素elm插入到环形队列head的头部;head是CIRCLEQ_HEAD定义的链表头指针;
#define	CIRCLEQ_INSERT_HEAD(head, elm, field) do {			\
	CIRCLEQ_NEXT((elm), field) = CIRCLEQ_FIRST((head));		\
	CIRCLEQ_PREV((elm), field) = (void *)(head);			\
	if (CIRCLEQ_LAST((head)) == (void *)(head))			\
		CIRCLEQ_LAST((head)) = (elm);				\
	else								\
		CIRCLEQ_PREV(CIRCLEQ_FIRST((head)), field) = (elm);	\
	CIRCLEQ_FIRST((head)) = (elm);					\
} while (0)

// 用于将元素elm插入到环形队列head的尾部;head是CIRCLEQ_HEAD定义的链表头指针;
#define	CIRCLEQ_INSERT_TAIL(head, elm, field) do {			\
	CIRCLEQ_NEXT((elm), field) = (void *)(head);			\
	CIRCLEQ_PREV((elm), field) = CIRCLEQ_LAST((head));		\
	if (CIRCLEQ_FIRST((head)) == (void *)(head))			\
		CIRCLEQ_FIRST((head)) = (elm);				\
	else								\
		CIRCLEQ_NEXT(CIRCLEQ_LAST((head)), field) = (elm);	\
	CIRCLEQ_LAST((head)) = (elm);					\
} while (0)

// 用于获取环形队列的最后一个元素;
#define	CIRCLEQ_LAST(head)	((head)->cqh_last)

// 用于获取elm元素的下一个元素,field是前面用CIRCLEQ_ENTRY定义的成员变量名;
#define	CIRCLEQ_NEXT(elm,field)	((elm)->field.cqe_next)

// 用于获取elm元素的上一个元素,field是前面用CIRCLEQ_ENTRY定义的成员变量名;
#define	CIRCLEQ_PREV(elm,field)	((elm)->field.cqe_prev)

// 用于环形队列head中删除elm元素;
#define	CIRCLEQ_REMOVE(head, elm, field) do {				\
	if (CIRCLEQ_NEXT((elm), field) == (void *)(head))		\
		CIRCLEQ_LAST((head)) = CIRCLEQ_PREV((elm), field);	\
	else								\
		CIRCLEQ_PREV(CIRCLEQ_NEXT((elm), field), field) =	\
		    CIRCLEQ_PREV((elm), field);				\
	if (CIRCLEQ_PREV((elm), field) == (void *)(head))		\
		CIRCLEQ_FIRST((head)) = CIRCLEQ_NEXT((elm), field);	\
	else								\
		CIRCLEQ_NEXT(CIRCLEQ_PREV((elm), field), field) =	\
		    CIRCLEQ_NEXT((elm), field);				\
} while (0)
3,模型

CIRCLEQ

4,验证例程
#include <stdio.h>
#include <stdlib.h>
#include <sys/queue.h>

struct QUEUE_ITEM {
	int value;
	CIRCLEQ_ENTRY(QUEUE_ITEM) entry;
};

static CIRCLEQ_HEAD(,QUEUE_ITEM) queue_head;

int main(int argc, char *argv[])
{
	int i = 0;
	struct QUEUE_ITEM *item;
	struct QUEUE_ITEM *tmp_item;

	CIRCLEQ_INIT(&queue_head);

	if (CIRCLEQ_EMPTY(&queue_head))
		printf("queue is empty\n");

	printf("after do CIRCLEQ_INSERT_HEAD:\n");
	for( i = 0; i < 10; i ++) {
		item = (struct QUEUE_ITEM *)malloc(sizeof(struct QUEUE_ITEM));
		item->value = i;
		CIRCLEQ_INSERT_HEAD(&queue_head, item, entry);
	}

	CIRCLEQ_FOREACH(tmp_item, &queue_head, entry)
        printf("Has Item pointer = %p, item value = %d\n", tmp_item, tmp_item->value);


	printf("after do CIRCLEQ_INSERT_BEFORE:\n");
	for( i = 0; i < 10; i ++) {
		tmp_item = (struct QUEUE_ITEM *)malloc(sizeof(struct QUEUE_ITEM));
		tmp_item->value = i + 10;
		CIRCLEQ_INSERT_BEFORE(&queue_head, item, tmp_item, entry);
		item = tmp_item;
	}

	CIRCLEQ_FOREACH(tmp_item, &queue_head, entry)
        printf("Has Item pointer = %p, item value = %d\n", tmp_item, tmp_item->value);

	CIRCLEQ_FOREACH(tmp_item, &queue_head, entry) {
		CIRCLEQ_REMOVE(&queue_head, tmp_item, entry);
	}

	CIRCLEQ_FOREACH(tmp_item, &queue_head, entry)
        printf("Has Item pointer = %p, item value = %d\n", tmp_item, tmp_item->value);

	if (CIRCLEQ_EMPTY(&queue_head))
		printf("queue is empty\n");

	exit(EXIT_SUCCESS);

	return 0;
}
  • 2
    点赞
  • 17
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 1
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Tim-Cheng

你的鼓励是我最大的动力,奥利给

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值