题目描述题目分析使用数组的方式来解题使用链表的方式
题目描述设计你的循环队列实现。 循环队列是一种线性数据结构,其操作表现基于 FIFO(先进先出)原则并且队尾被连接在队首之后以形成一个循环。它也被称为“环形缓冲器”。
循环队列的一个好处是我们可以利用这个队列之前用过的空间。在一个普通队列里,一旦一个队列满了,我们就不能插入下一个元素,即使在队列前面仍有空间。但是使用循环队列,我们能使用这些空间去存储新的值。
你的实现应该支持如下操作:
MyCircularQueue(k): 构造器,设置队列长度为 k 。
Front: 从队首获取元素。如果队列为空,返回 -1 。
Rear: 获取队尾元素。如果队列为空,返回 -1 。
enQueue(value): 向循环队列插入一个元素。如果成功插入则返回真。
deQueue(): 从循环队列中删除一个元素。如果成功删除则返回真。
isEmpty(): 检查循环队列是否为空。
isFull(): 检查循环队列是否已满。
链接:https://leetcode-cn.com/problems/design-circular-queue
题目分析这里稍微有点复杂的就是判空和判满的操作,所以要多一个空间(可以多画图理解)
删除的时候head向前走就行,插入的时候在tail的位置
然后那个多出来的为空的是动态的,是不断在发生变化的
typedef struct
{
int *a;
int head;
int tail;
int k; //可以存放元素的个数
} MyCircularQueue;
bool myCircularQueueIsEmpty(MyCircularQueue* obj);
bool myCircularQueueIsFull(MyCircularQueue* obj);
MyCircularQueue* myCircularQueueCreate(int k)
{
MyCircularQueue* obj=(MyCircularQueue*)malloc(sizeof(MyCircularQueue));
assert(obj);
obj->a=(int*)malloc(sizeof(int)*(k+1)); //多开一个空间哦
obj->head=obj->tail=0;
obj->k=k;
return obj;
}
bool myCircularQueueEnQueue(MyCircularQueue* obj, int value)
{
assert(obj);
if(myCircularQueueIsFull(obj)) //满了就报错了
return false;
obj->a[obj->tail]=value;
if(obj->tail==obj->k) //如果tail在最后一个位置就要重新回到0的位置
{
obj->tail=0;
}
else
{
obj->tail++;
}
return true;
}
bool myCircularQueueDeQueue(MyCircularQueue* obj)
{
assert(obj);
if(myCircularQueueIsEmpty(obj)) //为空就不用删除了
return false;
if(obj->head==obj->k)
{
obj->head=0;
}
else
{
obj->head++;
}
return true;
}
int myCircularQueueFront(MyCircularQueue* obj)
{
assert(obj);
if(myCircularQueueIsEmpty(obj))
return -1;
return obj->a[obj->head]; //头肯定就是head所在的下标
}
int myCircularQueueRear(MyCircularQueue* obj)
{
assert(obj);
if(myCircularQueueIsEmpty(obj))
return -1;
//队尾元素,是tail的前一个,但是tail为0的时候就是下标为k
if(obj->tail==0)
{
return obj->a[obj->k];
}
else
{
return obj->a[obj->tail-1];
}
}
bool myCircularQueueIsEmpty(MyCircularQueue* obj)
{
assert(obj);
//head和tail指向同一个位置的时候才是空
return obj->head==obj->tail;
}
bool myCircularQueueIsFull(MyCircularQueue* obj)
{
//判满有两种情况 1,tail在下标为k的位置,head在0
//2tail的前一个位置是head
if((obj->tail==obj->k) && (obj->head==0))
{
return true;
}
if(obj->tail+1==obj->head)
{
return true;
}
return false;
}
void myCircularQueueFree(MyCircularQueue* obj)
{
free(obj->a);
free(obj);
}
使用链表的方式
使用链表的方式有点难的地方主要还是去构造一个循环的单链表
但是我觉得还是以链表的方式构造简单一些
typedef struct QNode
{
int data;
struct QNode* next;
}QNode;
typedef struct
{
QNode* head;
QNode* tail;
} MyCircularQueue;
bool myCircularQueueIsEmpty(MyCircularQueue* obj) ;
bool myCircularQueueIsFull(MyCircularQueue* obj);
MyCircularQueue* myCircularQueueCreate(int k)
{
MyCircularQueue* obj =(MyCircularQueue*)malloc(sizeof(MyCircularQueue));
obj->tail=obj->head=NULL;
k=k+1; //多开辟一个空间哦
while(k) //搞一个循环的单链表出来
{
QNode* node=(QNode*)malloc(sizeof(QNode));
if(obj->tail==NULL && obj->head==NULL)
{
obj->tail=obj->head=node;
}
else
{
obj->tail->next=node;
obj->tail=node;
}
k--;
}
obj->tail->next=obj->head;
obj->tail=obj->head;
return obj;
}
bool myCircularQueueEnQueue(MyCircularQueue* obj, int value)
{
if(myCircularQueueIsFull(obj)) //满了就报错
return false;
obj->tail->data=value;
obj->tail=obj->tail->next;
return true;
}
bool myCircularQueueDeQueue(MyCircularQueue* obj)
{
if(myCircularQueueIsEmpty(obj)) //为空就报错
return false;
obj->head=obj->head->next;
return true;
}
int myCircularQueueFront(MyCircularQueue* obj)
{
if(myCircularQueueIsEmpty(obj))
return -1;
return obj->head->data;
}
int myCircularQueueRear(MyCircularQueue* obj)
{
if(myCircularQueueIsEmpty(obj))
return -1;
//是tail的前一个节点哦
QNode* cur=obj->head;
while(cur->next!=obj->tail)
{
cur=cur->next;
}
return cur->data;
}
bool myCircularQueueIsEmpty(MyCircularQueue* obj)
{
return obj->tail==obj->head; //tail和head相等就是空
}
bool myCircularQueueIsFull(MyCircularQueue* obj)
{
return obj->tail->next==obj->head; //tail的下一个节点是head就是空
}
void myCircularQueueFree(MyCircularQueue* obj)
{
QNode* cur=obj->head;
while(cur->next!=obj->head)
{
QNode* save=cur->next;
free(cur);
cur=save;
}
free(cur);
free(obj);
}



