libevent 学习----------尾队列 tail queue
来源:互联网 发布:公众号运营知乎 编辑:程序博客网 时间:2024/06/12 20:02
libevent里面的尾队列TAILQ
一、TAILQ的队列头
TAILQ把整个队列头单独抽象为一个结构体TAILQ_HEAD,如下:
#ifndef TAILQ_HEAD#define TAILQ_HEAD(name, type) \struct name { \ struct type *tqh_first; /* first element*/ \ struct type **tqh_last; /* address of last next element*/ \}#endif
tqh_first是一个一级指针,指向队列的第一个元素;tqh_last是一个二级指针,它指向最后一个元素中的tqe_next的地址。
上面的定义中不需要在最后的}后添加分行(;)
TAILQ_HEAD(queue_head_s, queue_entry_s) queue_head_t;
宏展开后就成了:
struct queue_head_s { struct queue_entry_s *tqh_first; struct queue_entry_s **tqh_last;} queue_head_t;
初始化队列头:
#define TAILQ_FIRST(head) ((head)->tqh_first)#define TAIL_INIT(head) do { \ TAILQ_FIRST((head)) = NULL; \ head->last = &TAILQ_FIRST((head)); \} while(0)
二、TAILQ的队列元素
#ifndef TAILQ_ENTRY#define TAILQ_ENTRY(type) \struct { \ struct type *tqe_next; /*next element*/ \ struct type **tqe_prev; /*address of previous next element*/ \}#endif
和前面的TAILQ_HEAD相比,TAILQ_ENTRY参数里面没有了name,即没有结构体名,所以该结构体只能作为一个匿名结构体,所以它一般都是另外一个结构体或者联合体的成员。如:
struct queue_entry_s { int element; TAILQ_ENTRY(queue_entry_s) entry;};展开后就变成struct queue_entry_s { int element; struct { struct queue_entry_s *tqe_next; struct queue_entry_s *tqe_prev; } entry;};
三、插入队列元素
考虑到队列是先进先出,这里研究从尾部插入新节点, 从头部删除节点。
1. 尾部插入
head: 队列头结点
elm: 实际节点对象
field: 队列节点元素
#define TAILQ_INSERT_TAIL(head, elm, field) do { \ (elm)->field.tqe_next = NULL; \ (elm)->field.tqe_prev = (head)->tqh_last; \ *(head)->tqh_last = (elm); \ (head)->tqh_last = &((elm)->field.tqe_next); \} while(0)
TAILQ_INSERT_TAIL(head, queue_entry, entry);
展开后变成:
do {
(queue_entry)->entry.tqe_next = NULL;
(queue_entry)->entry.tqe_prev = (head)->tqh_last;
*(head)->tqh_last = (queue_entry);
(head)->tqh_last =& ((queue_entry)->entry.tqe_next);
} while(0);
1) (head)->tqh_last 指向最后一个节点的next指针,所以在队列最后添加一个节点的时候,
*(head)->tqh_last = elem
2) (head)->tqh_last 指向最后一个节点的next指针
(head)->tqh_last =& ((queue_entry)->entry.tqe_next);
初始化状态,一个已经初始化的队列头,和一个待插入的队列元素
对新插入的元素的指针进行赋值,tqe_prev指向前一个next指针的地址,在尾部插入的情况下,就是tqh_last,因为tqh_last指向最后一个next指针的地址
将tqe_prev赋值为tqh_last,则tqe_prev和tqh_last所指的都是tqh_first.
2.更新tqh_first
添加第一个元素的时候,tqh_last就是tqh_first,所以更新tqh_first可以统一为更新(tqh_last)
3.更新tqh_last
4.调整一下变成
再次插入新的一个元素
step 0
step 1step 2
四、删除队列元素
#define TAILQ_REMOVE(head, elm, field) do { \ if (((elm)->field.tqe_next) != NULL) \ (elm)->field.tqe_next->field.tqe_prev = (elm)->field.tqe_prev; \ else \ (head)->tqh_last = (elm)->field.tqe_prev; \ *(elm)->filed.tqe_prev = (elm)->filed.tqe_next; \} while(0)
队列的一个特点就是先进先出,那么考虑删除第一个节点元素
已知如下队列,从中删除元素1的节点
step1
step2
step 3
最后还应该调用另外的释放函数来释放elm节点
五、队列中的第一个元素
#define TAILQ_FIRST(head) ((head)->tqh_first)
六、当前元素的下一个元素
#define TAILQ_NEXT(elm, field) ((elm)->field.tqe_next)
七、列表队列中的每一个元素
#define TAILQ_FOREACH(var, head, field) \ for ((var) = TAILQ_FIRST(head); \ (var) != NULL; \ (var) = TAILQ_NEXT(var, field))
八、实例
gwwu@hz-dev2.aerohive.com:~/test/tailq>more queue.h#ifndef __QUEUE_H__#define __QUEUE_H__#ifndef TAILQ_HEAD#define TAILQ_HEAD(name, type) \struct name { \ struct type *tqh_first; /* first element*/ \ struct type **tqh_last; /* address of last next element*/ \}#endif#define TAILQ_FIRST(head) ((head)->tqh_first)#define TAILQ_INIT(head) do { \ (head)->tqh_first = NULL; \ (head)->tqh_last = &((head)->tqh_first); \} while(0)#ifndef TAILQ_ENTRY#define TAILQ_ENTRY(type) \struct { \ struct type *tqe_next; \ struct type **tqe_prev; \}#endif#define TAILQ_INSERT_TAIL(head, elm, field) do { \ (elm)->field.tqe_next = NULL; \ (elm)->field.tqe_prev = (head)->tqh_last; \ *(head)->tqh_last = (elm); \ (head)->tqh_last = &((elm)->field.tqe_next); \} while(0)#define TAILQ_REMOVE(head, elm, field) do { \ if ((elm)->field.tqe_next != NULL) \ (elm)->field.tqe_next->field.tqe_prev = (elm)->field.tqe_prev;\ else \ (head)->tqh_last = (elm)->field.tqe_prev; \ *(elm)->field.tqe_prev = (elm)->field.tqe_next; \} while(0)#define TAILQ_NEXT(elm, field) ((elm)->field.tqe_next)#define TAILQ_FOREACH(var, head, field) \ for((var) = TAILQ_FIRST(head); \ (var) != NULL; \ (var) = TAILQ_NEXT(var, field))#endif
gwwu@hz-dev2.aerohive.com:~/test/tailq>more int_queue.c #include <stdio.h>#include <stdlib.h>#include "queue.h"struct queue_entry_t { int value; TAILQ_ENTRY(queue_entry_t) entry;};TAILQ_HEAD(queue_head_t, queue_entry_t); //define queue_head_t structureint main(int argc, char *argv[]){ struct queue_head_t queue_head; struct queue_entry_t *p; int i; TAILQ_INIT(&queue_head); for (i = 0; i < 3; i++) { p = (struct queue_entry_t*)malloc(sizeof(struct queue_entry_t)); if (p == NULL) { printf("malloc queue entry(%d) failed\n", i); return -1; } p->value = i; TAILQ_INSERT_TAIL(&queue_head, p, entry); } TAILQ_FOREACH(p, &queue_head, entry) { printf("the %d node\n", p->value); } TAILQ_FOREACH(p, &queue_head, entry) { TAILQ_REMOVE(&queue_head, p, entry); } return 0;}
编译运行:
gwwu@hz-dev2.aerohive.com:~/test/tailq>gcc -g int_queue.c -o int_queue -Wallgwwu@hz-dev2.aerohive.com:~/test/tailq>./int_queue the 0 nodethe 1 nodethe 2 node
- libevent 学习----------尾队列 tail queue
- libevent中的tail queue详细分析
- 单向列表(single-linked lists)、单向尾队列(single-linked tail queue)、列表(lists)、尾队列(tail queues)
- libevent数据结构尾队列
- Queue队列学习资料
- jquery queue()队列学习
- TAIL Queue数据结构
- Tail queue definitions
- tail queue的理解
- python学习笔记---queue队列
- libevent代码阅读(2)——尾队列的学习
- linux C++ queue 队列 学习积累
- C++ STL--queue队列容器学习笔记
- Cpp的队列(Queue)学习笔记
- c++ STL学习之queue队列总结
- python学习之队列(Queue)
- 数据结构学习之队列(queue)
- Message Queue学习笔记 --- 消息队列入门
- Mac 下常用快捷键,常用功能
- Codeforces 217A Ice Skating 题解
- GITC 2017全球互联网技术大会 上海站日程抢先看!
- AVL树
- NumberPicker
- libevent 学习----------尾队列 tail queue
- Guice Names的模板来生成注解
- KVO
- android:给图片打水印
- extern "C" 解析
- java String中的compareTo
- OkHttp的简单使用
- SPOOLing系统
- Kotlin的第一行代码