文章目录
- 1.题目描述
- 2.原题链接
- 3.思路分析
- 4.接口实现 :
- Front
- Rear
- enQueue(value):
- deQueue():
- isEmpty(): 检查循环队列是否为空
- isFull():
- myCircularQueueFree
- 5.代码实现
1.题目描述
设计你的循环队列实现。 循环队列是一种线性数据结构,其操作表现基于 FIFO(先进先出)原则并且队尾被连接在队首之后以形成一个循环。它也被称为“环形缓冲器”。
循环队列的一个好处是我们可以利用这个队列之前用过的空间。在一个普通队列里,一旦一个队列满了,我们就不能插入下一个元素,即使在队列前面仍有空间。但是使用循环队列,我们能使用这些空间去存储新的值。
需要实现的接口:
MyCircularQueue(k): 构造器,设置队列长度为 k 。
Front: 从队首获取元素。如果队列为空,返回 -1 。
Rear: 获取队尾元素。如果队列为空,返回 -1 。
enQueue(value): 向循环队列插入一个元素。如果成功插入则返回真。
deQueue(): 从循环队列中删除一个元素。如果成功删除则返回真。
isEmpty(): 检查循环队列是否为空。
isFull(): 检查循环队列是否已满。
示例 :
2.原题链接
Leetcode 622. 设计循环队列
3.思路分析
循环队列也是队列 ,自然拥有队列的特性 : 先进先出 , 但是循环队列它的优势表现在,如果队列满了之后,我们可以直接覆盖继续增加元素。
构造一个循环队列,可以采用两种不同形式的队列:顺序表和链表的方式去实现循环队列 ,这里我们采用顺序表实现
具体步骤 :
1 定义两个指针, front 表示头, tail 表示尾。创建数组 a, k 表示当前队列的长度 ,将这些变量分装成结构体
4.接口实现 :
Front
获取队首元素是相对比较简单的。直接返回当前 front 所在的元素即可。
int myCircularQueueFront(MyCircularQueue* obj)
{
if( myCircularQueueIsEmpty(obj)==true)
return -1 ;
else
return obj->a[obj->front]; ;
}
Rear
拿到obj->rear-1 的元素
int myCircularQueueRear(MyCircularQueue* obj)
{
if( myCircularQueueIsEmpty(obj)==true)
return -1 ;
else
{
//return obj->a[ (obj->rear-1+obj->k+1) % (obj->k+1) ];
int x = obj->rear == 0 ? obj->k : obj->rear-1 ;
assert( x < obj->k+1) ;
return obj->a[x];
}
}
enQueue(value):
bool myCircularQueueEnQueue(MyCircularQueue* obj, int value) //入队
{
//队列已满
if(myCircularQueueIsFull(obj))
return false ;
//队列未满
obj->a[obj->rear++] = value;
obj->rear %= obj->k+1 ;
return true ;
}
deQueue():
如果不取模 ,front可能越界 , 走到数组下标k+1的位置 ,所以我们取模可以让front绕回去
bool myCircularQueueDeQueue(MyCircularQueue* obj) //出队
{
//空队列
if( myCircularQueueIsEmpty(obj)==true)
return false;
obj->front ++ ;
obj->front %=( obj->k+1); //如果不取模 ,front可能越界 , 走到数组下标k+1的位置 ,所以我们取模可以让front绕回去
return true ;
}
isEmpty(): 检查循环队列是否为空
假设 k == 4 , 但是需要开辟了 k+1 个空间 ,也就是5个空间
当前队列的长度是k ,为什么要多开辟一个空间 ?
如果不多开辟一个空间 ,如下图 :
如果没有多开辟一个空间 , 就会发现无法判断循环队列是否为空
为了解决上述问题 , 我们选择多开辟一个空间便与判断循环队列是否为空, 如下图 :
bool myCircularQueueIsEmpty(MyCircularQueue* obj)
{
return obj->front == obj->rear ;
}
isFull():
bool myCircularQueueIsFull(MyCircularQueue* obj)
{
return (obj->rear + 1) % (obj->k + 1) == obj->front;
}
如果不取模 ,rear可能越界 , 走到数组下标k+1的位置 ,所以我们取模可以让rear绕回去
myCircularQueueFree
void myCircularQueueFree(MyCircularQueue* obj)
{
free( obj->a);
free(obj) ;
}
5.代码实现
typedef struct
{
int k ;
int *a ;
int front ;
int rear ;
} MyCircularQueue;
MyCircularQueue* myCircularQueueCreate(int k)
{
// 顺序表
MyCircularQueue*obj = (MyCircularQueue*)malloc ( sizeof( MyCircularQueue));
obj->rear =obj->front = 0 ;
obj->k = k ;
obj->a = (int*)malloc (sizeof( int) *(k+1)) ; //多开辟一个空间 ,好判断队列是否为空
return obj ;
}
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->k+1 ;
return true ;
}
bool myCircularQueueDeQueue(MyCircularQueue* obj) //出队
{
//空队列
if( myCircularQueueIsEmpty(obj)==true)
return false;
obj->front ++ ;
obj->front %=( obj->k+1); //如果不取模 ,front可能越界 , 走到数组下标k+1的位置 ,所以我们取模可以让front绕回去
return true ;
}
int myCircularQueueFront(MyCircularQueue* obj)
{
if( myCircularQueueIsEmpty(obj)==true)
return -1 ;
else
return obj->a[obj->front]; ;
}
int myCircularQueueRear(MyCircularQueue* obj)
{
if( myCircularQueueIsEmpty(obj)==true)
return -1 ;
else
{
//return obj->a[ (obj->rear-1+obj->k+1) % (obj->k+1) ];
int x = obj->rear == 0 ? obj->k : obj->rear-1 ;
assert( x < obj->k+1) ;
return obj->a[x];
}
}
void myCircularQueueFree(MyCircularQueue* obj)
{
free( obj->a);
free(obj) ;
}
如果你觉得这篇文章对你有帮助,不妨动动手指给点赞收藏加转发,给鄃鳕一个大大的关注
你们的每一次支持都将转化为我前进的动力!!