此题需要实现一个循环队列,那么在此之前我们得知道队列的概念和结构
队列:只允许在一端插入,另一端删除操作的特殊线性表,具有先进先出后进后出的特性
出队列:删除的一端叫队头
入队列:插入的一端叫队尾
知道了队列的概念和结构就能开始做此题了。
题目链接
题目描述:
思路:首先先找到,队列是空的条件和队列是满的条件,找到这两个条件就很容易的做出来了,队列为空的条件我给的是当队头和队尾相等的时候说明,这个队列为空。队列满的条件这个队列和队尾的下一个相等的时候就是满的,看到这里细心的朋友可能已经看出来了,这样的话岂不是要少一个数据?事实确实是也是这样但是为了解决这一问题我决定队列的最后一个空间用来作为结束条件,但是我又不希望传过来的数据丢失一个,于是我直接在创建的时候多开一个空间来用于结束判断,这样就完美的解决了数据不少又能判断队列是否满了的问题
首先我们需要一个循环队列的结构,我是这样定义的如下:
typedef struct {
int* a;
int k;//队列总大小
int front;//队头
int tail;//队尾
} MyCircularQueue;
大概是这个样子的:
我们来实现一个初始化函数MyCircularQueue* myCircularQueueCreate(int k);
MyCircularQueue* myCircularQueueCreate(int k) {
//一个队列
MyCircularQueue* obj = (MyCircularQueue*)malloc(sizeof(MyCircularQueue));
//初始化队列
//这里要多开一个空间用于判断队列是否满了
obj->a = (int*)malloc(sizeof(int) * (k + 1));
obj->front = 0;
obj->tail = 0;
obj->k = k;
//返回队列的地址
return obj;
}
实现好了上面这个函数我们开始实现一个判断队列是否为空的函数bool myCircularQueueIsEmpty(MyCircularQueue* obj);
和判断队列是否满了的函数bool myCircularQueueIsFull(MyCircularQueue* obj);
bool myCircularQueueIsEmpty(MyCircularQueue* obj) {
//如果front和tail相等说明是空的
return obj->front == obj->tail;
}
bool myCircularQueueIsFull(MyCircularQueue* obj) {
//队尾的下一个坐标给tailNext;
int tailNext = obj->tail + 1;
//如果它和最后一个空间的坐标相等说明此时的队列已经满了
if (tailNext == obj->k + 1)
{
//把它置为头的坐标
tailNext = 0;
}
return tailNext == obj->front;
}
有了这两个函数我们就可以开始实现队列的插入函数
根据上面的步骤我们可以很快的实现出插入函数
bool myCircularQueueEnQueue( MyCircularQueue* obj, int value) {
//判断是否满了,如果满了就不插入
if (myCircularQueueIsFull(obj))
{
return false;
}
else
{
//插入到tail位置,并自增
obj->a[obj->tail] = value;
obj->tail++;
//用于防止越界,当tail大于k的时候,就置成0以此来完成循环队列
obj->tail %= (obj->k + 1);
return true;
}
}
由于删除队列的删除函数和插入类似这里就不一一赘述了,我相信你们看懂了插入的逻辑删除应该很简单就能实现。
所有的代码:
typedef struct {
int* a;
int k;//队列总大小
int front;//队头
int tail;//队尾
} MyCircularQueue;
MyCircularQueue* myCircularQueueCreate(int k) {
//一个队列
MyCircularQueue* obj = (MyCircularQueue*)malloc(sizeof(MyCircularQueue));
//初始化队列
//这里要多开一个空间用于判断队列是否满了
obj->a = (int*)malloc(sizeof(int) * (k + 1));
obj->front = 0;
obj->tail = 0;
obj->k = k;
//返回队列的地址
return obj;
}
bool myCircularQueueIsEmpty(MyCircularQueue* obj) {
//如果front和tail相等说明是空的
return obj->front == obj->tail;
}
bool myCircularQueueIsFull(MyCircularQueue* obj) {
//队尾的下一个坐标给tailNext;
int tailNext = obj->tail + 1;
//如果它和最后一个空间的坐标相等说明此时的队列已经满了
if (tailNext == obj->k + 1)
{
//把它置为头的坐标
tailNext = 0;
}
return tailNext == obj->front;
}
bool myCircularQueueEnQueue( MyCircularQueue* obj, int value) {
//判断是否满了,如果满了就不插入
if (myCircularQueueIsFull(obj))
{
return false;
}
else
{
//插入到tail位置,并自增
obj->a[obj->tail] = value;
obj->tail++;
//用于防止越界,当tail大于k的时候,就置成0以此来完成循环队列
obj->tail %= (obj->k + 1);
return true;
}
}
bool myCircularQueueDeQueue(MyCircularQueue* obj) {
if ( myCircularQueueIsEmpty(obj))
{
return false;
}
else
{
//每自增一次头相当于出一个队列的数据
obj->front++;
//用于防止越界,当front大于k时就置0,以此完成循环队列
obj->front %= (obj->k + 1);
return true;
}
}
int myCircularQueueFront(MyCircularQueue* obj) {
//判断是否为空,如果为空返回-1
if (myCircularQueueIsEmpty(obj))
{
return -1;
}
else//如果不为空返回队头数据
{
return obj->a[obj->front];
}
}
int myCircularQueueRear(MyCircularQueue* obj) {
//如果队列为空返回-1
if (myCircularQueueIsEmpty(obj))
{
return -1;
}
//tail是前一个才是最后一个数据
int tailPrev = obj->tail - 1;
//如果tailPrev等于-1说明此时的tail是0
if (tailPrev == -1)
{
tailPrev = obj->k;
}
//返回tailPrev的数据
return obj->a[tailPrev];
}
void myCircularQueueFree(MyCircularQueue* obj) {
//释放队列
free(obj->a);
free(obj);
}
/**
* Your MyCircularQueue struct will be instantiated and called as such:
* MyCircularQueue* obj = myCircularQueueCreate(k);
* bool param_1 = myCircularQueueEnQueue(obj, value);
* bool param_2 = myCircularQueueDeQueue(obj);
* int param_3 = myCircularQueueFront(obj);
* int param_4 = myCircularQueueRear(obj);
* bool param_5 = myCircularQueueIsEmpty(obj);
* bool param_6 = myCircularQueueIsFull(obj);
* myCircularQueueFree(obj);
*/