环形队列
队列基本介绍
- 队列是一个有序列表,可以用数组或是链表来实现。
- 遵循先入先出的原则。即:先存入队列的数据,要先取出。后存入的要后取出
示意图:

环形队列的两种代码实现
实现方式一(牺牲空间)
此方式通过front和rear来判断队列的空满状态,需要牺牲数组的最后一位
package queue;
import java.util.Scanner;
/**
* @author xq
* @create 2021-01-09-13:35
*/
public class CircleArrayQueueDemo {
public static void main(String[] args) {
//创建一个队列
CircleArrayQueue arrayQueue = new CircleArrayQueue(3);//设置3,实际队列长度为2
char key = ' ';//接受用户输入
Scanner sc = new Scanner(System.in);//接受输入
boolean loop = true;
//输出一个菜单
while (loop) {
System.out.println("s(show):显示队列");
System.out.println("e(exit):退出队列");
System.out.println("a(add):添加数据到队列");
System.out.println("g(get):从队列取出数据");
System.out.println("h(head):查看队列头的数据");
key = sc.next().charAt(0);//接受一个字符
switch (key) {
case 's':
arrayQueue.showQueue();
break;
case 'e':
loop = false;
break;
case 'a':
System.out.println("输出一个数");
int value = sc.nextInt();
arrayQueue.addQueue(value);
break;
case 'g'://取出数据
try {
System.out.println("取出的数据是" + arrayQueue.getQueue());
} catch (Exception e) {
System.out.println(e.getMessage());
}
break;
case 'h'://查看队列头的数据
try {
System.out.println("队列头的数据是" + arrayQueue.headQueue());
} catch (Exception e) {
System.out.println(e.getMessage());
}
break;
}
}
}
}
//使用数组模拟队列-编写一个ArrayQueue类
class CircleArrayQueue {
private int maxSize;//表示数组的最大容量
private int front;//队列头
private int rear;//队列尾
private int[] arr;//该数组用于存放数据,模拟队列
//创建队列的构造器
public CircleArrayQueue(int arrMaxSize) {
maxSize = arrMaxSize;
arr = new int[maxSize];
front = 0;//指向队列头部,分析出front是指向队列的第一个元素。
rear = 0;//指向队列尾,指向队列最后一个元素的后一个位置
}
//判断队列是否满
public boolean isFull() {
return (rear + 1) % maxSize == front;
}
//判断队列是否为空
public boolean isEmpty() {
return rear == front;
}
//添加数据到队列
public void addQueue(int n) {
//判断队列是否满
if (isFull()) {
System.out.println("队列满");
return;
} else {
arr[rear] = n;
rear = (rear + 1) % maxSize;//让rear后移,这里必须考虑取模
}
}
//获取队列的第一个数据,出队列
public int getQueue() {
//判断队列是否空
if (isEmpty()) {
//通过抛出异常处理
throw new RuntimeException("队列空,不能取数据");
}
//这里需要分析出front是指向队列的第一个元素
//1.先把front对应值保存到一个临时变量
int value = arr[front];
//2.将front后移,考虑取模
front = (front + 1) % maxSize;
//将临时保存的变量返回
return value;
}
//显示队列的所有数据
public void showQueue() {
//遍历
if (isEmpty()) {
System.out.println("队列空");
}
//思路:从front开始遍历,遍历多少个元素
for (int i = front; i < front + size(); i++) {
System.out.printf("arr[%d]=%d\n", i % maxSize, arr[i % maxSize]);
}
}
//求出当前队列有效数据的个数
public int size() {
return (rear + maxSize - front) % maxSize;
}
//显示队列的头数据是多少
public int headQueue() {
//判断
if (isEmpty()) {
throw new RuntimeException("队列为空");
}
return arr[front];
}
}
方式一 思考
- 循环队列为什么要空出一个元素?
因为需要区分队列空和队列满的状态,当头指针和尾指针相等时队列为空,当尾指针在头指针前一个位置时队列为满。尾指针所指向的位置必须空着,所以能用的元素个数为n-1。 - 队列实际长度的计算
(rear + maxSize - front) % maxSize
方式二(LeetCode622)
此方法多定义了一个Size用于判断队列的空满状态,无需牺牲空间
class MyCircularQueue {
private int front;
private int rear;
private int maxSize;
private int[] arr;
private int size = 0;
public MyCircularQueue(int maxSize) {
this.maxSize = maxSize;
arr = new int[maxSize];
front = 0;
rear = -1;
}
public boolean enQueue(int value) {
if(isFull()){
return false;
}
size++;
rear = (rear + 1) % maxSize;
arr[rear] = value;
return true;
}
public boolean deQueue() {
if(isEmpty()){
return false;
}
size--;
front = (front + 1) % maxSize;
return true;
}
public int Front() {
if(isEmpty()){
return -1;
}
return arr[front];
}
public int Rear() {
if(isEmpty()){
return -1;
}
return arr[rear];
}
public boolean isEmpty() {
if(size == 0){
return true;
}
return false;
}
public boolean isFull() {
if(size == maxSize){
return true;
}
return false;
}
}
方式二 思考
- 为什么将rear定义为-1?
将尾指针直接指向最后一位数,便于查看队列的最后一位。
本文介绍了环形队列,队列是有序列表,遵循先入先出原则。重点讲解了环形队列的两种代码实现:一是牺牲空间,通过front和rear判断空满,需牺牲数组最后一位;二是LeetCode622方式,多定义Size判断空满,无需牺牲空间,还对两种方式进行了思考分析。
2853

被折叠的 条评论
为什么被折叠?



