数据结构与算法——单列队列
队列介绍
- 队列是一个有序列表,可以用数组或是链表来实现。
- 遵循先入先出的原则。即:先存入队列的数据,要先取出。后存入的要后取出
示意图:使用数组模拟队列示意图
数组模拟队列
- 队列本身是有序列表,若使用数组的结构来存储队列的数据,则队列数组的声明如下图, 其中 maxSize 是该队列的最大容量。
- 因为队列的输出、输入是分别从前后端来处理,因此需要两个变量 front及 rear分别记录队列前后端的下标,front 会随着数据输出而改变,而 rear则是随着数据输入而改变。
数组模拟队列的思路分析
根据图进行分析:
- 将尾指针往后移:rear+1 , 当front == rear,说明队列是空。
- 若尾指针 rear 小于队列的最大下标 maxSize-1,则将数据存入 rear所指的数组元素中,否则无法存入数据。 rear == maxSize - 1,此时说明队列满。
- 我们需要构造以下几个方法来满足队列的“增删查”的功能:
1 出队列操作getQueue
2 显示队列的情况showQueue
3 查看队列头元素headQueue
4 退出系统exit
代码分析
1.根据上述分析,我们在创建数组队列时候,需要的几个参数包括:maxSize指定数组的长度,front和rear来确定数据输入输出时指针指向的索引位置,以及创建一个数组来保存数据。
2.其中,因为初始化时候,动态数组(int型)数据都为0,此时需要把front和rear的指针索引都赋值为1,同时指定数组长度,这些都可以在结构体中初始化完成。
3.同时,需要我们根据自己的需要创建一些“增删改”的方法体。
class arrQueue {
private int maxSize;// 队列最大长度
private int front;// 头部指针,用来输出
private int rear;// 尾部指针,用来输入
private int[] arr;// int型数组
// 构造数组队列的结构体
public arrQueue(int maxValue) {
maxSize = maxValue;// 指定队列长度
arr = new int[maxSize];// 创建动态数组
front = -1;
rear = -1;
}
// 写方法体
// 1.判断队列是否满
public boolean isFull() {
return rear == maxSize - 1;
}
// 2.判断队列是否空
public boolean isEmpty() {
return front == rear;
}
// 3.添加数据到队列
public void addQueeu(int num) {
if (isFull()) {
System.out.println("队列已满,无法存入数据~~");
}
rear++;
arr[rear] = num;
}
// 4.从队列取出数据
public int getQueue() {
if (isEmpty()) {
System.out.println("队列里当前没有数据~~~");
}
front++;
return arr[front];
}
// 5.显示队列所有数据
public void show() {
if (isEmpty()) {
System.out.println("当前队列没有数据~~~");
}
for (int i = 0; i < maxSize; i++) {
System.out.println(arr[i]);
}
}
// 6.显示头部数据
public void showHead() {
if (isEmpty()) {
System.out.println("当前队列没有数据~~~");
}
System.out.println(arr[front + 1]);
}
4.在完成一系列的初始化和方法体的构造后,在主函数里调用。在这里,我是实现了一个类似于功能菜单的方式,可以多次重复增删查的功能,直到退出。这部分较为简单,涉及到的知识点主要是java基础中的分支结构和循环结构,以及scanner的调用和字符的charAt函数的使用。
import java.util.Scanner;
public class ArrayQueue {
public static void main(String[] args) {
arrQueue queue = new arrQueue(5);
char key = ' ';
Scanner sc = new Scanner(System.in);
boolean isFlag = true;
while (isFlag) {
System.out.println("s(show):显示队列");
System.out.println("a(add):添加数据");
System.out.println("g(get):取出数据");
System.out.println("h(head):查看队列头数据");
System.out.println("e(exit):退出队列");
System.out.println("请输入选择(s/a/g/h/c):");
key = sc.next().charAt(0);
switch (key) {
case 's':
queue.show();
break;
case 'a':
if (queue.isFull()) {
System.out.println("队列满了,请重新选择~~");
break;
}
System.out.println("请输入要添加的数字:");
int n = sc.nextInt();
queue.addQueeu(n);
break;
case 'g':
if (queue.isEmpty()) {
System.out.println("队列空了,请重新选择~~");
break;
}
queue.getQueue();
case 'h':
queue.showHead();
break;
case 'e':
sc.close();
isFlag = false;
break;
default:
break;
}
}
System.out.println("程序退出~~~");
}
}
5.缺陷:
浪费内存:当front指针后移之后,front指针前面的内存空间无法再进行使用,需要后续使用环形队列来做优化。