首先我要了解什么是循环队列,即我们开辟一段数组,用front和rear引用分别指向队头和队尾,
当我你要队头出数据后,front向后走到数组下标为1的位置,我们希望队头出数据的位置可以存放新的数据,此时我们要从数组下标为7的位置该如何回到数组 下标为0的位置呢?
这里我们提供了一个数组下标循环的小技巧:
下标最后再往后走1步: index = (index + 1) % array.length
此时让数组做到了循环,就可以形成下面这种样子
那么该如何区别数组是否存满了呢?
有三种方法:
- 通过添加 usedSize 属性记录 区别数组是否存满了
java
//循环队列1------》利用usedSize标记
class MyCircularQueue1 {
public int[] arr;
int usedSize = 0;//初始有效数据为0
public int front;
public int rear;
public MyCircularQueue1 (int k) {
//开辟存放k个数据的有效空间
int[] arr = new int[k];
}
//入队列
public boolean enQueue(int value) {
//1.如果队列满了,无法入队,返回false
if (isFull()) {
return false;
}
//2.队尾入数据
arr[rear] = value;
//指向队尾的指针往后走1步
rear = (rear + 1) % arr.length;
//数组中的有效数据+1
usedSize++;
return true;
}
//出队列
public boolean deQueue() {
//1.如果有效数据为0,表示队列为空,无法出队,返回false
if (usedSize == 0) {
return false;
}
//有效数据-1
usedSize--;
//队头往后走1步
front = (front + 1) % arr.length;
return true;
}
//取队头元素
public int Front() {
if (isEmpty()) {
return -1;
}
return arr[front];
}
//取队尾元素
public int Rear() {
if (isEmpty()) {
return -1;
}
//通过上面的if判断可知此时队中存在元素,
//1.rear的指向若为0下标,表示已经循环一次,若直接用0-1得到的是-1下标的数据,数组越界,所以使用arr.length - 1 ,得到下标为arr.length - 1的值
//2.若此时rear的指向不为0,则表示rear的范围在(0,k-1]范围内,直接rear-1即可
int index = (rear == 0) ? arr.length - 1 : rear - 1;
return arr[index];
}
//判断循环队列是否空了
public boolean isEmpty() {
//有效数据为0,表示队空
if (usedSize == 0) {
return true;
}
return false;
}
//判断循环队列是否满了
public boolean isFull() {
//有效数据==数组长度,队满
if (usedSize == arr.length) {
return true;
}
return false;
}
}
- 牺牲一个空间
java
class MyCircularQueue2 {
public int [] arr;
public int front=0;
public int rear=0;
public MyCircularQueue2 (int k) {
//由于要牺牲一个空间来判断是否为满,所以多申请一个空间
arr=new int[k+1];
}
public boolean enQueue(int value) {
if(isFull()){
return false;
}
arr[rear] = value;
rear = (rear+1)%arr.length;
return true;
}
public boolean deQueue() {
if(isEmpty()){
return false;
}
front = (front+1)%arr.length;
return true;
}
public int Front() {
if (isEmpty()){
return -1;
}
return arr[front];
}
public int Rear() {
if (isEmpty()){
return -1;
}
int index = (rear == 0) ? arr.length-1 : rear-1;
return arr[index];
}
public boolean isEmpty() {
//front和rear引用指向同一个位置表示,队为空
if(front==rear){
return true;
}
return false;
}
//判断循环队列是否满了
public boolean isFull() {
//若raer跳过牺牲的一个空间后,仍然等于front 表示队满
if((rear+1)%arr.length==front){
return true;
}
return false;
}
}
- 使用标记(flag)
java
class MyCircularQueue3 {
public int[] arr;
public int front;
public int rear;
boolean flag;//默认为false
public MyCircularQueue3(int k) {
arr = new int[k];
}
public boolean enQueue(int value) {
if(isFull()){
return false;
}
arr[rear]=value;
rear=(rear+1)% arr.length;
//入队后,将flag改为true,表示队中有数据了
flag=true;
return true;
}
public boolean deQueue() {
if(isEmpty()){
return false;
}
front=(front+1)% arr.length;
flag=false;
return true;
}
public int Front() {
if(isEmpty()){
return -1;
}
return arr[front];
}
public int Rear() {
if (isEmpty()) {
return -1;
}
int index = (rear == 0) ? arr.length - 1 : rear - 1;
return arr[index];
}
public boolean isEmpty() {
if(front == rear && !flag) {
return true;
}
return false;
}
public boolean isFull() {
if (rear==front&&flag) {
return true;
}
return false;
}
}