本文旨在加深学习印象并留记录以供日后查看。学习视频为韩顺平图解Java数据结构和算法,以下内容来自于视频内容与自我总结。如有错误请您指正。
队列
队列分析
- 队列是一个有序列表,可以用数组或是链表来实现。
- 遵循先入先出的原则。即:先存入队列的数据,要先取出。后存入的要后取出
示意图:(使用数组模拟队列示意图)
- 因为队列的输出、输入是分别从前后端来处理,因此需要两个变量 front及 rear分别记录队列前后端的下标,front 会随着数据输出而改变,而 rear则是随着数据输入而改变
- 因为队列的输出、输入是分别从前后端来处理,因此需要两个变量 front及 rear分别记录队列前后端的下标,front 会随着数据输出而改变,而 rear则是随着数据输入而改变
- 当我们将数据存入队列时称为”addQueue”,addQueue 的处理需要有两个步骤
(1)将尾指针往后移:rear+1 , 当front == rear 表示队列为空
(2)若尾指针 rear 小于队列的最大下标 maxSize-1,则将数据存入 rear所指的数组元素中,否则无法存入数据。 rear == maxSize - 1则队列已满
代码实现
package com.hyf.queue;
public class ArrayQueueDemo {
public static void main(String[] args) {
//测试
//创建队列
ArrayQueue queue = new ArrayQueue(3);
queue.addQueue(1);
queue.addQueue(2);
queue.addQueue(3);
queue.addQueue(4);
queue.showQueue();
System.out.println();
System.out.println("------------");
System.out.println(queue.getQueue());
System.out.println(queue.getQueue());
System.out.println(queue.getQueue());
System.out.println(queue.getQueue());
System.out.println("------------");
queue.showQueue();
}
}
//使用数组模拟队列
class ArrayQueue {
private int maxSize; // 数组队列的最大长度/容量
private int front; // 队列头位置
private int rear; // 队列尾位置
private int[] arr; // 存放队列数据
public ArrayQueue(int maxSize) {
this.maxSize = maxSize;
this.arr = new int[this.maxSize];
this.front = -1;
this.rear = -1;
}
//判断队列是否已满
public boolean isFull() {
// if (this.rear >= this.maxSize-1){
// return true;
// }
// return false;
return this.rear == this.maxSize-1;
}
//判断队列是否为空
public boolean isEmpty() {
return this.front == this.rear;
}
//添加数据到队列中,入队列
public void addQueue(int a) {
if (isFull()){
System.out.println("队列已满");
return;
}
this.rear++;
this.arr[this.rear] = a;
}
//获取数据,出队列
public int getQueue(){
if (isEmpty()){
throw new RuntimeException("队列为空,无数据");
}
this.front++;
return this.arr[this.front];
}
//显示队列所有数据
public void showQueue(){
if (isEmpty()){
System.out.println("队列为空,无数据");
return;
}
for (int i = 0; i < this.arr.length; i++) {
System.out.printf("%d\t", this.arr[i]);
}
}
}
问题
目前的数组只能使用一次,不能复用。
环形队列
为了充分利用数组,可以考虑将数组改造为一个环形的
思路分析
- 将front 变量的含义做一个调整: front 指向队列的第一个元素,也就是说 arr[front] 就是队列的第一个元素 。front 的初始值 = 0
- 将rear 变量的含义做一个调整:rear 指向队列的最后一个元素的后一个位置, 因为希望空出一个空间做为约定。rear 的初始值 = 0
- 当队列满时,条件是 (rear + 1) % maxSize == front
- 当队列空时,条件是 rear == front
- 队列中有效的数据的个数为 (rear + maxSize - front) % maxSize // rear = 1 front = 0
代码实现
将之间的代码做一些修改
package com.hyf.queue;
public class CircleArrayQueueDemo {
public static void main(String[] args) {
//测试
//创建环形队列
//设置长度4, 其队列的有效数据最大是3
CircleArrayQueue queue = new CircleArrayQueue(4);
queue.addQueue(11);
queue.addQueue(22);
queue.addQueue(33);
queue.addQueue(44);
//显示队列所有数据
queue.showQueue();
System.out.println();
System.out.println("------------");
//取一个,再加一个55
System.out.println(queue.getQueue());
queue.addQueue(55);
queue.showQueue();
System.out.println();
System.out.println("-----------");
System.out.println(queue.getQueue());
System.out.println(queue.getQueue());
queue.addQueue(66);
queue.showQueue();
System.out.println();
System.out.println("------------");
System.out.println(queue.getQueue());
System.out.println(queue.getQueue());
System.out.println(queue.getQueue());
System.out.println(queue.getQueue());
}
}
class CircleArrayQueue {
private int maxSize; // 数组队列的最大长度/容量
//front 指向队列的第一个元素, 也就是说 arr[front] 就是队列的第一个元素
//初始值 = 0
private int front; // 队列头位置
//rear 指向队列的最后一个元素的后一个位置
//初始值 = 0
private int rear; // 队列尾位置
private int[] arr; // 存放队列数据
public CircleArrayQueue(int maxSize) {
this.maxSize = maxSize;
this.arr = new int[this.maxSize];
}
//判断队列是否已满
public boolean isFull() {
return (this.rear + 1) % this.maxSize == this.front;
}
//判断队列是否为空
public boolean isEmpty() {
return this.front == this.rear;
}
//添加数据到队列中,入队列
public void addQueue(int a) {
if (isFull()){
System.out.println("队列已满");
return;
}
//先加入
this.arr[this.rear] = a;
//再后移,注意环形要取模,不然会导致数组越界
this.rear = (this.rear + 1) % this.maxSize;
}
//获取数据,出队列
public int getQueue(){
if (isEmpty()){
throw new RuntimeException("队列为空,无数据");
}
//先取值
int res = this.arr[this.front];
//再后移,注意取模,不然会导致数组越界
this.front = (this.front + 1) % this.maxSize;
return res;
}
//显示队列所有数据
public void showQueue(){
if (isEmpty()){
System.out.println("队列为空,无数据");
return;
}
//此时的i不是数组下标,会造成数组越界,所以要进行取模才能作为下标取值
for (int i = this.front; i < this.front + size(); i++) {
System.out.printf("%d\t", this.arr[i % this.maxSize]);
}
}
//获取arr中的有效元素个数
public int size(){
return (this.rear + this.maxSize - this.front) % this.maxSize;
}
}
测试结果