一.定义:
- 队列:上一篇博文讲过队列的基本定义以及简单实现。
参考地址:https://blog.csdn.net/weixin_42357849/article/details/105469908 - 循环队列:为充分利用向量空间,克服"假溢出"现象的方法是:将向量空间想象为一个首尾相接的圆环,并称这种向量为循环向量。存储在其中的队列称为循环队列(Circular Queue)。循环队列是把顺序队列首尾相连,把存储队列元素的表从逻辑上看成一个环。
- 示意图:
二.循环队列的实现
- 再循环队列中,当队列为空时,有front=tail,而当所有队列空间全占满时,也有front=tail。为了区别这两种情况,规定循环队列最多只能有MaxSize-1个队列元素,当循环队列中只剩下一个空存储单元时,队列就已经满了。因此,队列判空的条件是front=tail,而队列判满的条件是tailfront=(tail+1)%MaxSize。
以数组形式实现循环队列
- 循环队列的管理(和队列管理一样)
typedef struct CircleQueue
{
DataType *base;//数组
size_t capacity;//队列容量
size_t front;//头下标
size_t tail;//尾下标
}CircleQueue;
- 循环队列的操作(和队列操作基本相同)
#define DEFAULT_QUEUE_SIZE 8
bool CircleQueueIsFull(Queue *q)//判满
{
if ((q->tail + 1) % (q->capacity) == q->front)
return TRUE;
return FALSE;
}
bool CircleQueueIsEmpty(Queue *q)//判空
{
if (q->tail == q->front)
return TRUE;
return FALSE;
}
void CircleQueueInit(Queue *q, int sz);//初始化大小
void CircleQueuePush(Queue *q, DataType x);//入队
void CircleQueuePop(Queue *q);//出队
DataType CircleQueueFront(Queue *q);//取对头
void CircleQueueShow(Queue *q);//打印循环队列
- 各个模块的操作。
1.初始化大小
void CircleQueueInit(Queue *q, int sz)
{
q->capacity = sz > DEFAULT_QUEUE_SIZE ? sz : DEFAULT_QUEUE_SIZE;//队列大小
q->base = (DataType *)malloc(sizeof(DataType)*(q->capacity));
assert(q->base != NULL);
q->front = q->tail = 0;
}
2.入队操作
void CircleQueuePush(Queue *q, DataType x)
{
if (CircleQueueIsFull(q))
{
printf("队列已满, %d 不能入队.\n", x);
return;
}
q->base[q->tail] = x;
q->tail = (q->tail + 1) % q->capacity;//确定tail大小
}
3.出队操作
void CircleQueuePop(Queue *q)
{
if (CircleQueueIsEmpty(q))
{
printf("队列已空, 不能出队.\n");
return;
}
q->front = (q->front + 1) % q->capacity;//确定front的位置
}
4.取队头
DataType CircleQueueFront(Queue *q)
{
if (CircleQueueIsEmpty(q))
{
printf("队列已空, 不能去对头元素.\n");
return;
}
return q->base[q->front];//取队头
}
5.打印队列
void CircleQueueShow(Queue *q)
{
for (int i = q->front; i != q->tail;)
{
printf("%d ", q->base[i]);
i = (i + 1) % q->capacity;
}
printf("\n");
}