设计你的循环队列实现。 循环队列是一种线性数据结构,其操作表现基于 FIFO(先进先出)原则并且队尾被连接在队首之后以形成一个循环。它也被称为“环形缓冲器”。
循环队列的一个好处是我们可以利用这个队列之前用过的空间。在一个普通队列里,一旦一个队列满了,我们就不能插入下一个元素,即使在队列前面仍有空间。但是使用循环队列,我们能使用这些空间去存储新的值。
你的实现应该支持如下操作:
MyCircularQueue(k)
: 构造器,设置队列长度为 k 。Front
: 从队首获取元素。如果队列为空,返回 -1 。Rear
: 获取队尾元素。如果队列为空,返回 -1 。enQueue(value)
: 向循环队列插入一个元素。如果成功插入则返回真。deQueue()
: 从循环队列中删除一个元素。如果成功删除则返回真。isEmpty()
: 检查循环队列是否为空。isFull()
: 检查循环队列是否已满。
需要解决的问题:
1.如何判断循环队列是否为空?
在非空情况下,rear和front不会相遇(在同一个位置),所以当rear == front时,此循环对列为空,实例图如下:
2.怎么判断一个循环队列是满的?
2.1 定义一个usedSize(有效元素个数),usedSize==0时,即为空。
2.2可以通过维护一个 isFull
布尔值和一个 size
属性:
class CircularQueue {
private int[] queue;
private int front;
private int rear;
private int capacity;
private int size;
private boolean isFull;
public CircularQueue(int capacity) {
this.capacity = capacity;
this.queue = new int[capacity];
this.front = 0;
this.rear = -1;
this.size = 0;
this.isFull = false; // 初始化为空
}
public boolean isEmpty() {
return size == 0;
}
public boolean isFull() {
return size == capacity; // 或者直接返回 isFull
}
2.3浪费一个空间,通过rear的下一个元素是否为front来判断是否已满
这里的判满方法我们用第三种。
2.4: rear或front下标从7 位置 到0位置该怎么处理?如果直接rear+1,rear =8,不能重新进入循环,超出范围,这时我们就要借助一个公式:rear/front = (rear+1)%length(数组长度)。
步骤:
1.循环队列结构的创建:
int front(队头)
int rear(队尾)
int[ ] elem //保存整数的数组
1.2循环队列构造方法的创建:
创建一个容纳k+1个数量的数组elem();
具体代码如下:
class MyCircularQueue {
public int rear;
public int front;
public int[] elem;
public MyCircularQueue(int k) {
elem = new int[k+1];
}
2 入队方法(enQueue)的实现:
在元素入队(插入)之前,先判断队列是否已满(布尔方法 isFull(判断条件:rear的下一个元素是否为front)),如果已经满,返回false.
队列未满,进行插入:将值value插入rear位置,同时rear更新至下一个位置,更新完毕后返回true即可。
具体代码如下:
public boolean enQueue(int value) {
if(isFull()){
return false;
}else{
elem[rear] = value;
rear = (rear+1)%elem.length; //指向下一个节点
return true;
}
}
3.出队方法的实现:
进行出队操作之前,判断队列是否为空,若为空,返回false,
若不为空,通过front = (front+1)% elem.length 更新front位置指针,并返回true值
具体代码如下:
public boolean deQueue() {
if(isEmpty()){
return false;
}else{
front = (front+1)%elem.length; //更新front节点
return true;
}
}
4.Front方法的实现:(获取队头元素)
获取队头元素之前,判断队列是否为空,为空,返回-1(int 方法),
否则,返回位于front位置的元素。具体代码如下:
public int Front() {
//获取队头元素
if(isEmpty()){
return -1;
}else{
return elem[front];
}
}
5. Rear(获取队尾元素) 方法的实现:
先判断队列是否尾空,为空,返回false,
不为空的话,由于rear位置插入新值后都会往后再走一步,要获取队尾的元素,需要将创建一个整形index来接收 rear-1 ,再通过elem数组返回index位置的值。但这里有一个特殊情况:
当rear == 0 时,rear-1 = -1,此时实际的队尾位置在7位置处:
此时需总长度-1,得到的即为队尾位置 ,具体代码如下:
public int Rear() {
if(isEmpty()){
return -1;
}else{
int index = (rear == 0)? elem.length-1 : rear-1;
return elem[index];
}
}
最后,判断队列是否为空依据:rear 是否 == front
判断队列是否已满的依据:(rear+1)%elem.length 是否 == front
到这里,题目基本上已经完成。
喜欢的老贴们点个赞吧!