队列的简单介绍:
*队列是一个有序列表,可以使用数组或者链表来实现
*队列遵循先入先出的原则。先存入队列的数据要先取出,后存入的后取出
使用数组来模拟队列
- 说明
- 实现思路
- 示意图
- 代码
1.说明
*队列本身是有序列表,若使用数组的结构来存储队列的数据,则队列数组的声明入下图所示,其中maxSize是队列的最大容量
*由于队列的输入输出分别从前后端来处理,所以需要两个变量front和rear分别记录队列的前后端的下标,front随着数据输出而改变(向上移动),rear随着数据的输入而改变(向上移动)
2.实现思路
将数据存储队列时,将尾指针向后移动,rear+1,将数据输出的时候,front+1进行数据输出,当front==rear(队列空)。
若尾指针rear小于队列的最大下标maxSize-1,则将队列存入rear所指的数组元素中,否则无法存入数据,rear==maxSize-1(队列满)。
3.示意图
4.代码:
1.建立类和构造器
class ArrayQueue {
private int maxSize;//数组的最大容量
private int front; //指向队列头指针
private int rear; //指向队列尾指针
private int[] arr; //该数组用于存放数据
//创建队列的构造器
public ArrayQueue(int arrMaxSize) {
maxSize = arrMaxSize;
arr = new int[maxSize];
front = -1;//指向队列头部,此时指向队列头的前一个位置
rear = -1;//指向队列的尾部,此时指向队列的最后一个位置
}
2.判断队列是否为空或者为满
//判断队列是否满
public boolean isFull() {
return rear == maxSize - 1;
}
//判断队列是否为空
public boolean isEmpty() {
return rear == front;
}
3.入队列
//添加数据
public void addQueue(int n) {
//判断队列是否满
if (isFull()) {
System.out.println("队列已满,不能加入数据");
return;
}
rear++;//加入数据 尾指针后移
arr[rear] = n;
}
4.出队列
//出队列(获取队列数据)
public int getQueue() {
if (isEmpty()) {
throw new RuntimeException("队列已空,不能取出数据");
}
front++;
return arr[front];
}
5.显示队列以及队列的头数据
扫描二维码关注公众号,回复:
9322989 查看本文章
//显示队列
public void showQueue() {
if (isEmpty()) {
System.out.println("队列为空,没有数据");
return;
}
//printf用来进行输入各种占位符
for(int i=0;i<arr.length;i++){
System.out.printf("arr[%d]=%d\n",i,arr[i]);
}
}
//显示队列的头数据
public int headQueue() {
if (isEmpty()) {
throw new RuntimeException("队列为空");
}
return arr[front + 1];
}
6.主函数测试
public static void main(String[] args) {
//创建一个队列
ArrayQueue arrayQueue = new ArrayQueue(3);
char key = ' ';//接收用户输入
Scanner scanner = 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 = scanner.next().charAt(0);//接收一个字符
switch (key) {
case 's':
arrayQueue.showQueue();
break;
case 'a':
System.out.println("请输入一个数据:");
int value=scanner.nextInt();
arrayQueue.addQueue(value);
break;
case 'g':
try {
int res=arrayQueue.getQueue();
System.out.printf("取出的数据是%d\n",res);
}catch (Exception e){
System.out.println(e.getMessage());
}
break;
case 'h':
try {
int res=arrayQueue.headQueue();
System.out.printf("队列头的数据是%d\n",res);
}catch (Exception e){
System.out.println(e.getMessage());
}
break;
case 'e':
scanner.close();
loop=false;
break;
}
}
System.out.println("程序退出");
}
注意:由于使用数组去模拟普通队列,只能使用一次,所以需要将普通队列改进为环形队列
数组模拟环形队列
思路如下:
1.front变量的含义做一个调整:front就指向数组队列的第一个元素(原先指向第一个元素的前一个位置),也就是说arr[front]是队列的第一个元素
2.rear指向队列的最后一个元素的后一个位置(原先指向最后一个元素),因为希望空出一个空间做一个约定
3.当队列满时,条件时(rear+1)%maxSize=front【首尾是否重合】
4.队列为空时,rear==front
5.front的初始值为0.rear的初始值为0
6.队列中有效的个数 (rear+maxSize-front)%maxSize
测试一下:
因此可以修改上述代码如下:
package com.lz.arrayqueue;
import java.util.Scanner;
/***
* 环形数组实现队列的多次使用
*/
public class CircleArrayQueue {
//测试函数
public static void main(String[] args) {
//创建一个队列
System.out.println("测试数组模拟环形队列的案例~");
//最大有效数据为3(0--2)
CircleArray arrayQueue = new CircleArray(4);
char key = ' ';//接收用户输入
Scanner scanner = 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 = scanner.next().charAt(0);//接收一个字符
switch (key) {
case 's':
arrayQueue.showQueue();
break;
case 'a':
System.out.println("请输入一个数据:");
int value = scanner.nextInt();
arrayQueue.addQueue(value);
break;
case 'g':
try {
int res = arrayQueue.getQueue();
System.out.printf("取出的数据是%d\n", res);
} catch (Exception e) {
System.out.println(e.getMessage());
}
break;
case 'h':
try {
int res = arrayQueue.headQueue();
System.out.printf("队列头的数据是%d\n", res);
} catch (Exception e) {
System.out.println(e.getMessage());
}
break;
case 'e':
scanner.close();
loop = false;
break;
}
}
System.out.println("程序退出");
}
}
//编写一个CircleArray的类
class CircleArray {
private int maxSize;//数组的最大容量
private int front; //指向队列头指针 指向首部 初始值为0
private int rear; //指向队列尾指针 指向尾部后一个位置 初始值为0
private int[] arr; //该数组用于存放数据
//创建队列的构造器
public CircleArray(int arrMaxSize) {
maxSize = arrMaxSize;
arr = new int[maxSize];
front = 0;
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;
}
arr[rear] = n;//因为rear已经指向了后一个位置
rear = (rear + 1) % maxSize;//为了考虑前面的位置【循环使用】
}
//出队列(获取队列数据)
public int getQueue() {
if (isEmpty()) {
throw new RuntimeException("队列已空,不能取出数据");
}
//front是指向队列的第一个元素
//1.先把front对应的值保存到一个临时变量 然后将front后移
int value = arr[front];
front = (front + 1) % maxSize;
return value;
}
//显示队列
public void showQueue() {
if (isEmpty()) {
System.out.println("队列为空,没有数据");
return;
}
//printf用来进行输入各种占位符
//从front开始遍历 遍历多少个元素 当前有效元素:(rear+maxSize-front)%maxSize
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];
}
}