队列
队列和链表比较类似 不同之处在于队列仅允许从队列头部(front)删除节点
从队列尾部(rear)增加节点
可以将队列看作是栈的反例
队列:先入先出(FIFO)
栈:先入后出(LIFO)
前文已经分析过栈的原理:
http://blog.csdn.net/qq_21358401/article/details/79348642
侵入式队列
侵入式结构用来实现通用数据结构的例子已经分析过很多遍了 好处就是通用.
队列和链表一样 每一个节点应该能够访问前后的节点
so..
struct queue {
struct queue *prev;
struct queue *next;
};
初始化队列:
#define INIT_QUEUE(front,rear) \
{(front)->next = (rear);\
(front)->prev = NULL;\
(rear)->next = NULL;\
(rear)->prev = (front);}
判断是否为空队列:
static inline int queue_empty(struct queue *front, struct queue *rear) {
return front->next == rear && rear->prev == front;
}
入队:
static inline void enqueue(struct queue *rear, struct queue *new_node) {
assert(rear != NULL);
assert(new_node != NULL);
new_node->next = rear;
new_node->prev = rear->prev;
rear->prev->next = new_node;
rear->prev = new_node;
}
出队:
static inline struct queue * _dequeue(struct queue *front, struct queue *rear) {
assert(front != NULL);
struct queue *tmp = NULL;
tmp = front->next;
if (queue_empty(front, rear)) {
return NULL;
} else {
front->next = tmp->next;
tmp->next->prev = front;
}
return tmp;
}
出队操作的是queue结构节点 还应该增加对应的包装结构的出队
#define queu_entry(ptr,type,member) \
((type *)((char *)(ptr)-(unsigned long)(&((type *)0)->member)))
#define dequeue(front,rear,type,member) queue_entry(_dequeue(front,rear),type,member)
示例代码
#ifndef CODINGUTILS_QUEUE_H
#define CODINGUTILS_QUEUE_H
#include <stdio.h>
#include <stdlib.h>
#include <assert.h>
struct queue {
struct queue *next;
struct queue *prev;
};
#define INIT_QUEUE(front,rear) {(front)->next = (rear);(front)->prev = NULL;(rear)->next = NULL;(rear)->prev = (front);}
#define list_entry(ptr,type,member) \
((type *)((char *)(ptr)-(unsigned long)(&((type *)0)->member)))
#define queue_entry(ptr,type,member) list_entry(ptr,type,member)
static inline int queue_empty(struct queue *front, struct queue *rear) {
return front->next == rear && rear->prev == front;
}
static inline void enqueue(struct queue *rear, struct queue *new_node) {
assert(rear != NULL);
assert(new_node != NULL);
new_node->next = rear;
new_node->prev = rear->prev;
rear->prev->next = new_node;
rear->prev = new_node;
}
static inline struct queue * _dequeue(struct queue *front, struct queue *rear) {
assert(front != NULL);
struct queue *tmp = NULL;
tmp = front->next;
if (queue_empty(front, rear)) {
return NULL;
} else {
front->next = tmp->next;
tmp->next->prev = front;
}
return tmp;
}
#define dequeue(front,rear,type,member) queue_entry(_dequeue(front,rear),type,member)
#endif
#include "queue.h"
#define log(fmt,...)\
do {\
printf(fmt,##__VA_ARGS__);\
printf("\n");\
} while (0)
struct queue_node {
struct queue node;
int val;
};
int main() {
log("queue test");
struct queue front, rear;
INIT_QUEUE(&front, &rear);
int i = 0;
for (i = 0; i < 5; i++) {
struct queue_node *tmp = NULL;
tmp = malloc(sizeof(struct queue_node));
if (!tmp) {
log("failed to alloc queue node");
return -1;
}
tmp->val = i;
enqueue(&rear, &tmp->node);
log("enqueue node val:%d", tmp->val);
}
while (!queue_empty(&front, &rear)) {
struct queue_node *val = NULL;
val = dequeue(&front, &rear, struct queue_node, node);
log("dequeue node val:%d", val->val);
free(val);
}
return 0;
}
git repo:
https: