循环队列,也叫“环形队列”。
它指的是:将队列抽象成一个环形,如果队头前面有空间,我们可以继续使用。环形队列可以用数组、链表实现,以下我们使用数组实现。环形队列的队头front表示第一个入队的元素下标,队尾rear代表最后一个有效元素的下一个位置下标。因此,环形队列判空条件是front==rear,判满的条件是(rear+1)%n==front.n表示数组总大小(n=k+1,k表示有效元素个数)。
以下是环形队列的设计,以及一些接口的实现:
typedef struct
{
int* queue;
int front;
int rear;
int k;//队列长度
}MyCircleQueue;
void* myCircleQueueCreate(MyCircleQueue* q, int k)//初始化
{
assert(q);
q->queue = (int*)malloc(sizeof(int)*(k+1));//注意要多开一个大小,队列长度为k指的是有效元素个数,而rear始终指向的是一个空的位置,所以这个多余的空间是给它留的
q->k = k;
q->front = q->rear = 0;
}
int myCircleQueuePush(MyCircleQueue* q, int x)//插入,返回0说明插入失败,返回1说明插入成功
{
assert(q);
if ((q->rear + 1) % (q->k + 1) == q->front)//满了
{
return 0;
}
//来到这说明未满,直接插入
q->queue[q->rear++] = x;
if (q->rear == q->k + 1)//最后一个位置的下一个位置应该是0,让其循环起来
q->rear = 0;
return 1;
}
int myCircleQueuePop(MyCircleQueue* q)//删除返回0说明插入失败,返回1说明插入成功
{
assert(q);
if (q->front == q->rear)//空
{
return 0;
}
//来到这,说明非空,直接删除
q->front++;
if (q->front == q->k + 1)
q->front = 0;//与上一个题解释相同,让其循环起来
return 1;
}
int myCircleQueueFront(MyCircleQueue* q)//取队头元素,队列空返回-1
{
assert(q);
if (q->front == q->rear)//队空
{
return -1;
}
else
{
return q->queue[q->front];
}
}
int myCircleQueueRear(MyCircleQueue* q)//取队尾元素,队列空返回-1
{
assert(q);
if (q->front == q->rear)//队空
{
return -1;
}
//来到这,说明不空,不空的情况下,如果队尾==0,说明真正有效的元素是前一个
if (q->rear == 0)
{
return q->queue[q->k];
}
else
{
return q->queue[q->rear - 1];
}
}
int myCircleQueueEmpty(MyCircleQueue* q)//判空,空返回0,非空返回1
{
assert(q);
if (q->front == q->rear)
{
return 0;
}
else
{
return 1;
}
}
int myCircleQueueFull(MyCircleQueue* q)//判满,满返回0,不满返回1
{
assert(q);
if ((q->rear + 1) % (q->k + 1) == q->front)
{
return 0;
}
else
{
return 1;
}
}
void myCircleQueueFree(MyCircleQueue* q)//销毁
{
assert(q);
free(q->queue);
free(q);
}