赞
踩
相信有一定编程经验的你,在项目中经常会遇到队列、链表、ringbuffer等问题。刚开始的时候,都有过自己编写代码(造轮子)的经验。但随着工作经验的提升,经常会发现:
那在这种情况下,我们应该怎么办呢?我的建议是:
我这里讲解的queue.h就是一个非常经典的文件。它定义了一系列宏操作,实现了队列、尾队列、单向链表、双向链表以及树形结构的封装,效率非常高。更关键的是它仅仅只是一个头文件,加入项目也是非常的简单。你可以在很多地方见到queue.h的身影:
queue.h定义了5个基本的数据类型:
引入的方法非常简单,只需要在你的源码里面加入:
#include <sys/queue.h>
如果不是在Linux系统下,也可以字节拷贝Linux系统/usr/include/sys/queue.h文件到你的项目。
queue相关链表/队列的使用流程为:
注意:如果遇到多个线程同时操作链表/队列时,需要对队列加锁以保证正确性;且应该是只对队列加锁,而不对结构体的数据内容加锁(浅锁),以便提高运行效率;
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.
与单向链表相关的宏、方法和函数有:
// definitions SLIST_HEAD(name, type) SLIST_HEAD_INITIALIZER(head) SLIST_ENTRY(type) // access methods SLIST_FIRST(head) SLIST_END(head) SLIST_EMPTY(head) SLIST_NEXT(elm, field) LIST_FOREACH(var, head, field) SLIST_FOREACH_PREVPTR(var, varp, head, field) // functions SLIST_INIT(head) SLIST_INSERT_AFTER(slistelm, elm, field) SLIST_INSERT_HEAD(head, elm, field) SLIST_REMOVE_NEXT(head, elm, field) SLIST_REMOVE_HEAD(head, field) SLIST_REMOVE(head, elm, type, field)
与单向链表相关的宏定义只有三个:
#define SLIST_HEAD(name, type) \
struct name { \
struct type *slh_first; /* first element */ \
}
#define SLIST_HEAD_INITIALIZER(head) \
{ NULL }
#define SLIST_ENTRY(type) \
struct { \
struct type *sle_next; /* next element */ \
}
通过命名,可以很明确的知道其用法:
与单向链表相关的访问方法有6个:
#define SLIST_FIRST(head) ((head)->slh_first)
#define SLIST_END(head) NULL
#define SLIST_EMPTY(head) (SLIST_FIRST(head) == SLIST_END(head))
#define SLIST_NEXT(elm, field) ((elm)->field.sle_next)
#define SLIST_FOREACH(var, head, field) \
for((var) = SLIST_FIRST(head); \
(var) != SLIST_END(head); \
(var) = SLIST_NEXT(var, field))
#define SLIST_FOREACH_PREVPTR(var, varp, head, field) \
for ((varp) = &SLIST_FIRST((head)); \
((var) = *(varp)) != SLIST_END(head); \
(varp) = &SLIST_NEXT((var), field))
通过命名,可以很明确的知道其用法:
与单向链表相关的函数有6个:
#define SLIST_INIT(head) { \ SLIST_FIRST(head) = SLIST_END(head); \ } #define SLIST_INSERT_AFTER(slistelm, elm, field) do { \ (elm)->field.sle_next = (slistelm)->field.sle_next; \ (slistelm)->field.sle_next = (elm); \ } while (0) #define SLIST_INSERT_HEAD(head, elm, field) do { \ (elm)->field.sle_next = (head)->slh_first; \ (head)->slh_first = (elm); \ } while (0) #define SLIST_REMOVE_NEXT(head, elm, field) do { \ (elm)->field.sle_next = (elm)->field.sle_next->field.sle_next; \ } while (0) #define SLIST_REMOVE_HEAD(head, field) do { \ (head)->slh_first = (head)->slh_first->field.sle_next; \ } while (0) #define SLIST_REMOVE(head, elm, type, field) do { \ if ((head)->slh_first == (elm)) { \ SLIST_REMOVE_HEAD((head), field); \ } else { \ struct type *curelm = (head)->slh_first; \ \ while (curelm->field.sle_next != (elm)) \ curelm = curelm->field.sle_next; \ curelm->field.sle_next = \ curelm->field.sle_next->field.sle_next; \ _Q_INVALIDATE((elm)->field.sle_next); \ } \ } while (0)
通过命名,可以很明确的知道其用法:
#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; //static SLIST_HEAD(,SLIST_ITEM) slist_head = SLIST_HEAD_INITIALIZER(); 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 += 1) { item = (struct SLIST_ITEM *)malloc(sizeof(struct SLIST_ITEM)); item->value = i; SLIST_INSERT_HEAD(&slist_head, item, entry); } printf("after insert 10 item to single list:\n"); SLIST_FOREACH(item, &slist_head, entry) printf("item value = %d\n", item->value); SLIST_FOREACH(tmp_item, &slist_head, entry) { if(tmp_item->value % 2 != 0) SLIST_REMOVE(&slist_head, tmp_item,
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。