引
本文主要介绍, 基于数组来实现循环队列的几种方式, 要使用数组来实现循环队列的关键点就在于, 如何解决数组越界的问题以及如何判断数组是满还是空
下面提供了三种解决方案:
- 使用 usedSize
- 使用 标志位
- 空出一个位置
下面就具体来介绍下这三种方法~
方式一
最简单的办法就是使用 usedSize 来记录当前数组中有几个有效元素即可
- usedSize == 0 是则表示当前数组为空
- usedSize == 数组的长度 则表示当前数组满了
图解
此时的 usedSize == 0 队列为空
入队操作
出队操作
下图的 usedSize == 4 说明队列已满
代码
/**
* @Author XUE_957
* @Date 2022/6/12 21:08
* @Version 2022.1.1
*/
public class MyCircularQueue1 {
private int[] queue;
// usedSize 表示有效元素个数
private int usedSize;
// 队列头
private int head;
// 队列尾
private int tail;
public MyCircularQueue1(int k) {
// 调用构造方法时初始化数组
this.queue = new int[k];
}
public boolean enQueue(int value) {
if (isFull()) {
// 这里不考虑扩容问题
return false;
}
// 这种写法会导致数组越界,所以需要取余数
//queue[tail++] = value;
queue[tail] = value;
tail = (tail + 1) % queue.length;
usedSize++;
return true;
}
public boolean deQueue() {
if (isEmpty()) {
return false;
}
head = (head + 1) % queue.length;
usedSize--;
return true;
}
public int Front() {
if (isEmpty()) {
return -1;
}
return queue[head];
}
public int Rear() {
if (isEmpty()) {
return -1;
}
if (tail == 0) {
// 因为每次入队操作, tail 都会加 1, 因此这里要获取队尾元素要减 1
// 而且这里要考虑数组越界的问题,这里只需针对 0 下标处理一下即可~
return queue[queue.length - 1];
}
return queue[tail - 1];
}
public boolean isEmpty() {
return usedSize == 0;
}
public boolean isFull() {
return usedSize == queue.length;
}
}
方式二
使用一个标记 flag 来判断当前队列是空还是满
- 如果 flag == false 则说明队列为空
- 如果 flag == true 则说明队列已满
- 每次的入队操作都将 flag 置为 true , 每次的出队操作都将 flag 置为 false
图解
空的情况:
满的情况:
代码
/**
* @Author XUE_957
* @Date 2022/6/12 22:01
* @Version 2022.1.1
*/
public class MyCircularQueue2 {
private int[] queue;
// 队列头
private int head;
// 队列尾
private int tail;
// 设立标记位,默认是 false
private boolean flag;
public MyCircularQueue2(int k) {
// 调用构造方法时初始化数组
this.queue = new int[k];
}
public boolean enQueue(int value) {
if (isFull()) {
// 这里不考虑扩容问题
return false;
}
flag = true;
// 这种写法会导致数组越界,所以需要取余数
//queue[tail++] = value;
queue[tail] = value;
tail = (tail + 1) % queue.length;
return true;
}
public boolean deQueue() {
if (isEmpty()) {
return false;
}
flag = false;
head = (head + 1) % queue.length;
return true;
}
public int Front() {
if (isEmpty()) {
return -1;
}
return queue[head];
}
public int Rear() {
if (isEmpty()) {
return -1;
}
if (tail == 0) {
// 因为每次入队操作, tail 都会加 1, 因此这里要获取队尾元素要减 1
// 而且这里要考虑数组越界的问题,这里只需针对 0 下标处理一下即可~
return queue[queue.length - 1];
}
return queue[tail - 1];
}
public boolean isEmpty() {
return head == tail && flag == false;
}
public boolean isFull() {
return head == tail && flag == true;
}
}
方式三
浪费一个格子, 用来判断队列是空还是满
- 如果 tail + 1 == head 则说明队列满了
- 如果 tail == head 则说明队列为空
题目链接: 设计一个循环队列
注意:
- 跑 oj 的时候, 在构造函数这里需要将 k 写成 k+1 因为浪费了一个格子~
图解
空的情况:
满的情况:
代码
/**
* @Author XUE_957
* @Date 2022/6/12 22:18
* @Version 2022.1.1
*/
public class MyCircularQueue3 {
private int[] queue;
// 队列头
private int head;
// 队列尾
private int tail;
public MyCircularQueue3(int k) {
// 调用构造方法时初始化数组
this.queue = new int[k];
}
public boolean enQueue(int value) {
if (isFull()) {
// 这里不考虑扩容问题
return false;
}
// 这种写法会导致数组越界,所以需要取余数
//queue[tail++] = value;
queue[tail] = value;
tail = (tail + 1) % queue.length;
return true;
}
public boolean deQueue() {
if (isEmpty()) {
return false;
}
head = (head + 1) % queue.length;
return true;
}
public int Front() {
if (isEmpty()) {
return -1;
}
return queue[head];
}
public int Rear() {
if (isEmpty()) {
return -1;
}
if (tail == 0) {
// 因为每次入队操作, tail 都会加 1, 因此这里要获取队尾元素要减 1
// 而且这里要考虑数组越界的问题,这里只需针对 0 下标处理一下即可~
return queue[queue.length - 1];
}
return queue[tail - 1];
}
public boolean isEmpty() {
return head == tail;
}
public boolean isFull() {
return (tail + 1) % queue.length == head;
}
}