Model
------------------------------------------------------------------------------------------------------------------------
队列也是限制插入和删除位置的表.
主要操作是enqueue和dequeue操作.
enqueue:入队操作.在表的队尾(rear)插入一个元素.
dequeue:出队操作.删除表的队首(front)元素.
本文使用循环数组实现GenericQueue.需要指定capacity.缺点是超出容量,无法动态增长.当然,可以仿照list的方式克服这个问题.
完整代码详见我的github(https://github.com/gnudennis/ds_c)(genric-queue.h generic-queue.c generic-queue-test.c)
核心代码
------------------------------------------------------------------------------------------------------------------------
0. Generic Queue定义
typedef void *ElementAddr;
typedef void (*PfCbFree)(ElementAddr);
typedef struct QueueRecord
{
ElementAddr *array;
int capacity;
int elemsize;
int front;
int rear;
int size;
PfCbFree freefn;
} *Queue;
1. API
/* Create a new queue */
Queue queue_create(int elemsize, int capacity, PfCbFree freefn);
/* Dispose the queue */
void queue_dispose(Queue que);
/* Make the give queue empty */
void queue_make_empty(Queue que);
/* Return true if the queue is empty */
int queue_is_empty(Queue que);
/* Return true if the queue is full */
int queue_is_full(Queue que);
/* Insert a new element onto queue */
void queue_enqueue(Queue que, ElementAddr elemaddr);
/* Delete the front element off the queue */
void queue_dequeue(Queue que);
/* Fetch the front element from the queue */
void queue_front(Queue que, ElementAddr elemaddr);
/* Fetch and Delete the front element from the queue */
void queue_front_and_dequeue(Queue que, ElementAddr elemaddr);
/* Create a new queue with capacity */
Queue
queue_create(int elemsize, int capacity, PfCbFree freefn)
{
Queue que;
que = malloc(sizeof(struct QueueRecord));
if ( que == NULL ) {
fprintf(stderr, "Out of memory\n");
exit(1);
}
que->elemsize = elemsize;
que->capacity = capacity > MIN_QUEUE_SIZE ? capacity : MIN_QUEUE_SIZE;
que->array = malloc(elemsize * que->capacity);
if ( que->array == NULL ) {
fprintf(stderr, "Out of memory\n");
exit(1);
}
que->front = 1;
que->rear = 0;
que->size = 0;
que->freefn = freefn;
return que;
}
/* Dispose the queue */
void
queue_dispose(Queue que)
{
if (que != NULL) {
queue_make_empty(que);
free(que->array);
free(que);
}
}
/* Make the give queue empty */
void
queue_make_empty(Queue que)
{
if ( que->freefn ) {
int i;
for ( i = 0; i < que->size; ++i) {
free((char *)que->array +
que->elemsize * i);
}
}
que->size = 0;
que->front = 1;
que->rear = 0;
}
/* Return true if the queue is empty */
int
queue_is_empty(Queue que)
{
return que->size == 0;
}
/* Return true if the queue is full */
int
queue_is_full(Queue que)
{
return que->size == que->capacity;
}
static int
successor(Queue que, int index)
{
if ( ++index == que->capacity)
index = 0;
return index;
}
/* Insert a new element onto queue(rear) */
void
queue_enqueue(Queue que, ElementAddr elemaddr)
{
void *target;
if ( queue_is_full(que) ) {
fprintf(stderr, "Full queue\n");
exit(1);
}
que->rear = successor(que, que->rear);
target = (char *)que->array + que->elemsize * que->rear;
memcpy(target, elemaddr, que->elemsize);
que->size++;
}
/* Delete the front element off the queue */
void
queue_dequeue(Queue que)
{
if ( queue_is_empty(que) ) {
fprintf(stderr, "Empty queue\n");
exit(1);
}
if ( que->freefn ) {
void *target = (char *)que->array +
que->front * que->elemsize;
que->freefn(target);
}
que->size--;
que->front = successor(que, que->front);
}
/* Fetch the front element from the queue */
void
queue_front(Queue que, ElementAddr elemaddr)
{
void *target = (char *)que->array +
que->front * que->elemsize;
memcpy(elemaddr, target, que->elemsize);
}
/* Fetch and Delete the front element from the queue */
void
queue_front_and_dequeue(Queue que, ElementAddr elemaddr)
{
void *target;
if ( queue_is_empty(que) ) {
fprintf(stderr, "Empty queue\n");
exit(1);
}
target = (char *)que->array +
que->front * que->elemsize;
memcpy(elemaddr, target, que->elemsize);
que->size--;
que->front = successor(que, que->front);
}
分析
----------------
本文使用循环数组实现GenericQueue.需要指定capacity.既然是循环数组,就是围成一个圈.也就插入第一个元素没有必要非要放在0处啦.
初始状态:
{
que->size = 0;
que->front = 1;
que->rear = 0;
}
说明这样第一次enqueue操作放在array[1]处,当然:这不是必须的,取决于你想放在那里.
#define mxx
{
que->size = 0;
que->front =m+1;
que->rear = m;
}
就放在array[m+1]处.