目录
一、队列基础知识
队列跟栈类似都是“操作受限”的线性表,只不过队列是先进先出结构,队列也有两个基本的操作:入队 enqueue(),放一个数据到队列尾部;出队 dequeue(),从队列头部取一个元素。根据实现方式不同,也可以分为两种:使用数组来实现的顺序队列,和使用链表来实现的链式队列。
对于栈来说,我们只需要一个栈顶指针就可以了。但是队列需要两个指针:一个是 head 指针,指向队头;一个是 tail 指针,指向队尾;
在数组实现队列的时候,会有数据搬移操作,要想解决数据搬移的问题,我们就需要像环一样的循环队列。那么如何判断循环队列满和空呢? 如下【右图】会发现:
1、队列满时:head = tail,队列空时:(tail+1)%n = head,这样的话循环队列会浪费一个数组的存储空间。
2、但如果用size来表示队列的总大小,num来记录队列的当前元素个数,则可以这样判断:队列满时:num = size,队列空时:num = 0,这样就能将队列全部空间用来存储数据,这也是最常用的做法
二、顺序队列数据结构
#define ARRAY_QUEUE_SIZE(pqueue) (pqueue->size)
#define ARRAY_QUEUE_NUM(pqueue) (pqueue->used)
#define ARRAY_QUEUE_IS_EMPTY(pqueue) (pqueue->num == 0)
#define ARRAY_QUEUE_IS_FULL(pqueue) (pqueue->num == pqueue->size)
struct array_queue
{
int size; /* queue total size */
int num; /* queue used size rang:1-(size-1) */
int head; /* points to the location where the next dequeue data store */
int tail; /* points to the location where the next enqueue data store */
int tpsz; /* data type size */
void *p; /* queue space */
};
三、顺序队列函数声明
extern struct array_queue* array_queue_creat(int size, int tpsz);
extern int array_queue_init (struct array_queue *queue, int size, int tpsz);
extern int array_queue_empty (struct array_queue *queue);
extern int array_queue_destory(struct array_queue *queue);
extern int array_queue_enqueue(struct array_queue *queue, void *in_data);
extern int array_queue_dequeue(struct array_queue *queue, void *out_data);
extern void array_queue_test(void);
四、创建顺序队列
1、队列头部动态创建
/**
* dynamically creat and init an array queue.
*
* @param size: array size
* @param tpsz: data type size
* @return result: array queue or NULL
*/
struct array_queue* array_queue_creat(int size, int tpsz)
{
struct array_queue *queue = NULL;
if (size <= 0 || tpsz <= 0)
return NULL;
/* malloc an array queue struct */
queue = ARRAY_QUEUE_MALLOC(sizeof(*queue));
if (queue == NULL)
return NULL;
/* calloc an array queue */
void *p = ARRAY_QUEUE_CALLOC(1, (size * tpsz));
if (p == NULL)
return NULL;
queue->size = size;
queue->num = 0;
queue->head = 0;
queue->tail = 0;
queue->tpsz = tpsz;
queue->p = p;
return queue;
}
2、队列头部静态创建
/**
* init a static array queue.
*
* @param queue:
* @param size: array size
* @param tpsz: array data type length
* @return -1:queue is null or malloc fail
* 0:success
*/
int array_queue_init(struct array_queue *queue, int size, int tpsz)
{
if (queue == NULL)
return -1;
/* calloc an array queue */
void *p = ARRAY_QUEUE_CALLOC(1, (size * tpsz));
if (p == NULL)
return NULL;
queue->size = size;
queue->num = 0;
queue->head = 0;
queue->tail = 0;
queue->tpsz = tpsz;
queue->p = p;
return 0;
}
五、出队列
/**
* dequeue data from the array queue.
*
* @param array_queue: array queue
* @return -1: fail
* -2: queue is empty
* 0: success
*/
int array_queue_dequeue(struct array_queue *queue, void *out_data)
{
char *phead = NULL;
if (queue == NULL)
return -1;
/* queue is empty */
if(ARRAY_QUEUE_IS_EMPTY(queue))
return -2;
phead = queue->p;
phead = phead + queue->tpsz * queue->head;
memcpy(out_data, phead, queue->tpsz);
queue->num--;
queue->head = (queue->head + 1) % queue->size;
return 0;
}
六、入队列
/**
* enqueue data to the array queue.
*
* @param queue: array queue
* @return -1: fail
* -2: queue is full
* 0: success
*/
int array_queue_enqueue(struct array_queue *queue, void *in_data)
{
char *ptail = NULL;
if (queue == NULL)
return -1;
/* queue is full */
if(ARRAY_QUEUE_IS_FULL(queue))
return -2;
ptail = queue->p;
ptail = ptail + queue->tpsz * queue->tail;
memcpy(ptail, in_data, queue->tpsz);
queue->num++;
queue->tail = (queue->tail + 1) % queue->size;
return 0;
}
七、队列删除
/**
* delete array queue space.
*
* @param array_queue: array queue
* @return -1: fail
* 0:success
*/
int array_queue_empty(struct array_queue *queue)
{
if (queue == NULL)
return -1;
/* free array queue space */
if (queue->p != NULL)
{
ARRAY_QUEUE_FREE(queue->p);
queue->size = 0;
queue->num = 0;
queue->head = 0;
queue->tail = 0;
queue->tpsz = 0;
queue->p = NULL;
}
return 0;
}
八、队列销毁
/**
* delete and destroy an array queue.
*
* @param array_queue: array queue
* @return -1: fail
* 0:success
*/
int array_queue_destory(struct array_queue *queue)
{
if (array_queue_empty(queue) != 0)
return -1;
ARRAY_QUEUE_FREE(queue);
queue = NULL;
return 0;
}
九、验证程序
struct array_queue *array_queue_head;
int array_queue_w[6] = {11,22,33,44,55,66};
int array_queue_r[6] = {0};
void array_queue_test(void)
{
array_queue_head = array_queue_creat(5, sizeof(int));
array_queue_enqueue(array_queue_head, (void*)&array_queue_w[0]);
array_queue_enqueue(array_queue_head, (void*)&array_queue_w[1]);
array_queue_enqueue(array_queue_head, (void*)&array_queue_w[2]);
array_queue_enqueue(array_queue_head, (void*)&array_queue_w[3]);
array_queue_enqueue(array_queue_head, (void*)&array_queue_w[4]);
array_queue_enqueue(array_queue_head, (void*)&array_queue_w[5]);
array_queue_dequeue(array_queue_head, (void*)&array_queue_r[0]);
array_queue_dequeue(array_queue_head, (void*)&array_queue_r[1]);
array_queue_dequeue(array_queue_head, (void*)&array_queue_r[2]);
array_queue_dequeue(array_queue_head, (void*)&array_queue_r[3]);
array_queue_dequeue(array_queue_head, (void*)&array_queue_r[4]);
array_queue_dequeue(array_queue_head, (void*)&array_queue_r[5]);
}