在一个普通队列里,一旦一个队列满了,我们就不能插入下一个元素,即使在队列前面仍有空间。但是使用循环队列,我们能使用这些空间去存储新的值。
这里我通过一个数组进行模拟,通过操作数组的索引构建一个虚拟的首尾相连的环。
当然也可以使用链表指针连接。
设计接口:
MyCircularQueue(k)
: 构造器,设置队列长度为 k 。Front
: 从队首获取元素。如果队列为空,返回 -1 。Rear
: 获取队尾元素。如果队列为空,返回 -1 。enQueue(value)
: 向循环队列插入一个元素。如果成功插入则返回真。deQueue()
: 从循环队列中删除一个元素。如果成功删除则返回真。isEmpty()
: 检查循环队列是否为空。isFull()
: 检查循环队列是否已满。
为了区分空的情况和满的情况,我们设计的队列一定要保证一直空出一个位置
typedef struct {
int*_a;
int _front;
int _rear;
int _k;//循环队列的容量
} MyCircularQueue;
MyCircularQueue* myCircularQueueCreate(int k)
{
MyCircularQueue* q = (MyCircularQueue*)malloc(sizeof(MyCircularQueue));
//malloc一个结构体
q->_a = (int*)malloc(sizeof(int) * (k + 1));//malloc一个数组
q->_front = 0;
q->_rear = 0;
q->_k = k;
return q;
}
bool myCircularQueueIsEmpty(MyCircularQueue* obj)
{
return obj->_front == obj->_rear;
}
bool myCircularQueueIsFull(MyCircularQueue* obj)
{
return (obj->_rear + 1) % (obj->_k + 1) == obj->_front;
}
bool myCircularQueueEnQueue(MyCircularQueue* obj, int value)
{
if (myCircularQueueIsFull(obj))
return false;
obj->_a[obj->_rear] = value;
obj->_rear++;
obj->_rear %= (obj->_k + 1);//用模处理预防超出
return true;
}
bool myCircularQueueDeQueue(MyCircularQueue* obj)
{
if (myCircularQueueIsEmpty(obj))
return false;
obj->_front++;
obj->_front %= (obj->_k + 1);//用模处理预防超出
return true;
}
int myCircularQueueFront(MyCircularQueue* obj)
{
if (myCircularQueueIsEmpty(obj))
return -1;
else
return obj->_a[obj->_front];
}
int myCircularQueueRear(MyCircularQueue* obj)
{
if (myCircularQueueIsEmpty(obj))
{
return -1;
}
else
{
int tail = obj->_rear - 1;
if (tail == -1)//rear-1是队尾,但是rear的位置可能为0,tail就为-1,此时需要重新定义tail
tail = obj->_k;
return obj->_a[tail];
}
}
void myCircularQueueFree(MyCircularQueue* obj) {
free(obj->_a);
free(obj);
}