1.使用场景
银行排队的案例:
2.队列介绍
队列是一个有序列表,可以用数组或是链表来实现。
遵循先入先出的原则:
先存入队列的数据,要先取出。
后存入的要后取出
示意图:(使用数组模拟队列示意图)
3.实现方式1:数组模拟队列
思路分析
队列本身是有序列表,若使用数组的结构来存储队列的数据,则队列数组的声明如下图, 其中 maxSize 是该队列的最大容量。
front 是队列最前元素之前一个位置【不含最前】
rear 是队列最后元素 【含最后】
插入队列,判断是否已满,将尾指针往后移:rear++,然后插入arr[rear]
移出队列,判断是否为空,将前指针往后移:front++,然后移出arr[front]
队列为空判断条件:当front == rear 【空】
队列是否满判断条件:rear == maxSize - 1【队列满】
代码实现
//使用数组模拟队列-编写一个ArrayQueue类
classArrayQueue {private int maxSize; //表示数组的最大容量
private int front; //队列头
private int rear; //队列尾
private int[] arr; //该数据用于存放数据, 模拟队列//创建队列的构造器
public ArrayQueue(intarrMaxSize) {
maxSize=arrMaxSize;
arr= new int[maxSize];
front= -1; //指向队列头部,分析出front是指向队列头的前一个位置.
rear = -1; //指向队列尾,指向队列尾的数据(即就是队列最后一个数据)
}//判断队列是否满
public booleanisFull() {return rear == maxSize - 1;
}//判断队列是否为空
public booleanisEmpty() {return rear ==front;
}//添加数据到队列
public void addQueue(intn) {//判断队列是否满
if(isFull()) {
System.out.println("队列满,不能加入数据~");return;
}
rear++; //让rear 后移
arr[rear] =n;
}//获取队列的数据, 出队列
public intgetQueue() {//判断队列是否空
if(isEmpty()) {//通过抛出异常
throw new RuntimeException("队列空,不能取数据");
}
front++; //front后移
returnarr[front];
}//显示队列的所有数据
public voidshowQueue() {//遍历
if(isEmpty()) {
System.out.println("队列空的,没有数据~~");return;
}for (int i = 0; i < arr.length; i++) {
System.out.printf("arr[%d]=%d\n", i, arr[i]);
}
}//显示队列的头数据, 注意不是取出数据
public intheadQueue() {//判断
if(isEmpty()) {throw new RuntimeException("队列空的,没有数据~~");
}return arr[front + 1];
}
}
View Code
出现问题
目前数组不能复用,用一次就用不了了
优化方式:将数组模拟成环形队列
4. 数组模拟环形队列
思路:
1.front变量的含义做调整:front指向队列的第一个元素,即arr[front]就是队列的第一个元素
2.rear变量的含义做调整:rear指向队列的最后一个元素的后一个元素,因为希望空出一个空间作为约定(队列实际容量=maxSize-1,理解为防止指向超出数组范围的地方报错)。
3.当队列满时,条件是:(rear + 1) % maxSize == front [满]
4.当队列空时,条件是:rear == front [空]
5.队列中有效数据的个数:(rear + maxSize - front) % maxSize
6.插入队列时,判断队满,先插入队列arr[rear],然后rear++
7.移出队列时,判断队空,先移出队列arr[front],然后front++
代码实现
classCircleArray {private int maxSize; //表示数组的最大容量//front 变量的含义做一个调整: front 就指向队列的第一个元素, 也就是说 arr[front] 就是队列的第一个元素//front 的初始值 = 0
private intfront;//rear 变量的含义做一个调整:rear 指向队列的最后一个元素的后一个位置. 因为希望空出一个空间做为约定.//rear 的初始值 = 0
private int rear; //队列尾
private int[] arr; //该数据用于存放数据, 模拟队列
public CircleArray(intarrMaxSize) {
maxSize=arrMaxSize;
arr= new int[maxSize];
}//判断队列是否满
public booleanisFull() {return (rear + 1) % maxSize ==front;
}//判断队列是否为空
public booleanisEmpty() {return rear ==front;
}//添加数据到队列
public void addQueue(intn) {//判断队列是否满
if(isFull()) {
System.out.println("队列满,不能加入数据~");return;
}//直接将数据加入
arr[rear] =n;//将 rear 后移, 这里必须考虑取模
rear = (rear + 1) %maxSize;
}//获取队列的数据, 出队列
public intgetQueue() {//判断队列是否空
if(isEmpty()) {//通过抛出异常
throw new RuntimeException("队列空,不能取数据");
}//这里需要分析出 front是指向队列的第一个元素//1. 先把 front 对应的值保留到一个临时变量//2. 将 front 后移, 考虑取模//3. 将临时保存的变量返回
int value =arr[front];
front= (front + 1) %maxSize;returnvalue;
}//显示队列的所有数据
public voidshowQueue() {//遍历
if(isEmpty()) {
System.out.println("队列空的,没有数据~~");return;
}//思路:从front开始遍历,遍历多少个元素//动脑筋
for (int i = front; i < front + size() ; i++) {
System.out.printf("arr[%d]=%d\n", i % maxSize, arr[i %maxSize]);
}
}//求出当前队列有效数据的个数
public intsize() {//rear = 2//front = 1//maxSize = 3
return (rear + maxSize - front) %maxSize;
}//显示队列的头数据, 注意不是取出数据
public intheadQueue() {//判断
if(isEmpty()) {throw new RuntimeException("队列空的,没有数据~~");
}returnarr[front];
}
}
View Code