1. 思路解析
循环队列就是在只有有限的空间时使用队列实现循环存储数据,有双向链表和数组两种选择,这里我们使用数组实现循环队列(因为链表我不会 >-<)
2. 相关函数及其实现
2.1 判空与判满
判空:直接返回头尾是否相等的结果,相等为空,反之不为空;
判满:判断tail+1==head的结果是否为真,是则满,反之不满,需要注意的是在tail指向数组最后一个元素时tail+1越界,所以要使用取模运算限制其范围。
bool myCircularQueueIsEmpty(MyCircularQueue* obj)
{
return obj->head == obj->tail;
}
bool myCircularQueueIsFull(MyCircularQueue* obj)
{
return (obj->tail + 1) % (obj->k + 1) == obj->head;
}
2.2 入队列与出队列
入队列:入队列要判断是否为满,满则不能插入,返回false,不满直接插入,tail++,同样取模防止越界;
出队列:出队列判断是否为空,为空不能出队列,返回false,不为空直接将head++,当然也要取模保证不越界。
bool myCircularQueueEnQueue(MyCircularQueue* obj, int value)
{
if(myCircularQueueIsFull(obj))
return false;
obj->a[obj->tail] = value;
obj->tail++;
obj->tail %= (obj->k+1);
return true;
}
bool myCircularQueueDeQueue(MyCircularQueue* obj)
{
if(myCircularQueueIsEmpty(obj))
return false;
++obj->head;
obj->head %= (obj->k+1);
return true;
}
2.3 取队首与队尾元素
取队首:判断队列是否为空,为空返回-1,不为空直接返回队头元素;
取队尾:判断队列是否为空,为空返回-1,不为空返回tail前一个元素,也就是队尾元素,这里由于不是直接返回tail所指元素,而是tail-1所指元素,所以要取模保证tail-1不越界。
int myCircularQueueFront(MyCircularQueue* obj)
{
if(myCircularQueueIsEmpty(obj))
return -1;
else
return obj->a[obj->head];
}
int myCircularQueueRear(MyCircularQueue* obj)
{
if(myCircularQueueIsEmpty(obj))
return -1;
else
return obj->a[(obj->tail -1 + obj->k + 1) % (obj->k + 1)];
}
2.4 释放队列
释放:先释放"小弟",再释放"大哥",即先释放obj->a所申请的数组,再释放obj,防止内存泄漏
void myCircularQueueFree(MyCircularQueue* obj)
{
free(obj->a);
free(obj);
}