参考书籍 << 数据结构 严蔚敏版>>
队列实现的意义
假设当前队列分配的最大空间为5,当队列处于上图所示的状态时不能再插入新的队尾元素,否则会出现溢出现象(这里指的是tt尾指针超出数组下标范围)事实上,此时队列的实际可用空间并没有占满,此时称这种现象为"假溢出".
当我们要最大限度的利用一个定长的队列时(解决假溢出问题),能够将一个顺序队列抽象为一个环状空间,称这样的队列为循环队列 .
实现循环队列
头尾指针以及队列之间元素的关系不变,只是当头指针或尾指针越过数组范围时,会立即返回合法位置,这样的操作可以通过用"模"运算实现.
代码实现
队列结构
typedef struct {
int* a;
int size;//容量
int cnt;//当前元素数量
int hh;//指向头节点
int tt;//指向尾节点
} MyCircularQueue;
初始化队列
MyCircularQueue* myCircularQueueCreate(int k) {
MyCircularQueue* obj = (MyCircularQueue*)malloc(sizeof(MyCircularQueue));
obj->a = (int*)malloc(sizeof(int)*k);
obj->hh = 0;
obj->tt = -1;
obj->size = k;
obj->cnt = 0;
return obj;
}
判断队列是否为空
通过判断当前元素的个数是否为0来判断队列是否为空
bool myCircularQueueIsEmpty(MyCircularQueue* obj) {
return obj->cnt == 0;
}
判断队列是否已满
通过队列容量与当前元素个数是否相等来判断是否已满
bool myCircularQueueIsFull(MyCircularQueue* obj) {
return obj->size == obj->cnt;
}
队列元素入队
注:每次元素入队时需要判断队列是否已满
bool myCircularQueueEnQueue(MyCircularQueue* obj, int value) {
if (!myCircularQueueIsFull(obj))
{
obj->tt++;
obj->tt=obj->tt%obj->size;
obj->a[obj->tt] = value;
obj->cnt++;
return true;
}
else return false;
}
队列元素出队
bool myCircularQueueDeQueue(MyCircularQueue* obj) {
if (!myCircularQueueIsEmpty(obj))
{
obj->hh++;
obj->hh %= obj->size;
obj->cnt--;
return true;
}
return false;
}
弹出队头元素
注:先判断队列是否不空,当没有元素入队时tt=-1会出现数组越界,当后续有元素入队但弹出时队列变空再次进行弹出操作可能弹出重复相同元素
int myCircularQueueRear(MyCircularQueue* obj) {
if (!myCircularQueueIsEmpty(obj))
{
return obj->a[obj->tt];
}
else return -1;
}