循环队列概念及结构
循环队列是一种特殊的队列,普通队列普遍使用单向链表来表示,所以整个队列在逻辑结构上是一条链,而循环队列是用数组来进行表示的,而且其逻辑结构上表示为一个环型结构。
逻辑结构
首先我们看一下循环队列的逻辑结构:
循环队列同普通的队列一样都有收尾指针,不同的是循环队列的尾指针是指向最后一个元素的下一个位置,所以循环队列的容量是比数组大小少了一位。
物理结构
实际上我们的循环队列就是一个一维数组:
对于这样一个循环队列,需要注意一下几点:
1、如何构成循环:
(1)当rear等于数组容量,再入队时,将rear置零;
(2)当front等于数组容量,再出队时,将front置零;
2、判空条件:front和rear相等;
3、判满条件分为两种情况:
(1)当rear是数组最后一位,front是数组第一位时,队列满了;
(2)当front不是数组第一位时,rear+1==front时,队列满了;
4、循环队列有效元素个数:
(1)当rear>front,有效元素个数为:rear-front;
(2)当rear<front,有效元素个数为:(rear-front + 容量 + 1)% (容量 + 1);
循环队列数据结构:
typedef int CDataType;
typedef struct CircleQueue
{
CDataType* array; //数组,大小为容量+1
int front; //头指针
int rear; //尾指针
int capacity; //容量
}CircleQueue;
代码实现
初始化
void CircleQueueInit(CircleQueue* cq, int k)
{
cq->array = (CDataType*)malloc(sizeof(CDataType) * (k + 1));
cq->capacity = k;
cq->front = cq->rear = 0;
}
入队
void CircleQueuePush(CircleQueue* cq, CDataType data)
{
if (cq->rear == cq->capacity)
{
cq->rear = 0;
cq->array[cq->rear++] = data;
}
else
{
cq->array[cq->rear++] = data;
}
}
出队
void CircleQueuePop(CircleQueue* cq)
{
if (cq->front == cq->capacity)
{
cq->front = 0;
}
else
{
cq->front++;
}
}
获取队首元素
CDataType GetFrontElement(CircleQueue* cq)
{
return cq->array[cq->front];
}
获取队尾元素
CDataType GetRearElement(CircleQueue* cq)
{
if (cq->rear == 0)
{
return cq->array[cq->capacity];
}
return cq->array[cq->rear - 1];
}
有效元素个数
int CircleQueueSize(CircleQueue* cq)
{
return (cq->rear - cq->front + cq->capacity + 1) % (cq->capacity + 1);
}
判空
int CircleQueueEmpty(CircleQueue* cq)
{
if (cq->front == cq->rear)
{
return 1;
}
return 0;
}
判满
int CircleQueueFull(CircleQueue* cq)
{
if ((cq->rear - cq->front + cq->capacity + 1) % (cq->capacity + 1) == cq->capacity)
{
return 1;
}
return 0;
}
销毁
void CircleQueueDestroy(CircleQueue* cq)
{
free(cq->array);
}