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; intcapacity; intelemsize; intfront; intrear; intsize; PfCbFreefreefn;} *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);
2.Implementation
/* 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]處.