个人简介
😎大家好,我是辉code⬅️⬅️往期文章可以查看我的主页进行观看哦
👊因为坚持才有幸运的机会!!
❤️点赞随意,关注随缘,你的支持是我坚持的动力!
👊此文章的专栏 数据结构
前言
跟着B站尚硅谷老韩的数据结构进行学习,所做的笔记。若是对你有用,点赞,关注支持一下!!我会持续更新。👊👊本文讲的是队列的介绍与代码实现等等,队列是遵循先进先出,相信读完这篇文章,对队列会有初步的概念。
队列
1.队列的一个使用场景
银行排队的案例:
2.队列介绍
● 队列是一个有序列表,可以用数组或是链表来实现。遵循先入先出的原则。
● 即:先存入队列的数据,要先取出。后存入的要后取出
3.使用数组模拟队列
队列本身是有序列表,若使用数组的结构来存储队列的数据,则队列数组的声明如下图, 其中 maxSize 是该队列的最大容量。
因为队列的输出、输入是分别从前后端来处理,因此需要两个变量 front及 rear分别记录队列前后端的下标,front 会随着数据输出而改变(如图front++),而 rear则是随着数据输入而改变(如图rear++),如图所示:
初始化时:rear = front =-1
4.数组模拟队列思路
当我们将数据存入队列时称为”addQueue”,addQueue 的处理需要有两个步骤:
思路分析
- 判断 rear == maxSize - 1[队列满] 若成立无法存入数据。
- 当front == rear 【空】或尾指针 rear 小于队列的最大下标 maxSize-1,则将数据存入 rear所指的数组元素中将尾指针往后移:rear++ ,Queue[rear]=value
注意: - rear 是队列最后元素的位置
- front 是队列最前元素的前一个位置
5.代码实现
package day2;
import java.util.Scanner;
/**
* 作者:灰爪哇
* 时间:2022-12-29
*/
public class ArrayQueue {
//初始化队列
private int maxSize;
private int front;
private int rear;
private int[] arr;
//构造器
public ArrayQueue(int maxSize) {
this.maxSize = maxSize;//初始化
this.front = -1;//头指针,指向队头元素的前一个位置
this.rear = -1;//尾指针,指向队尾的最后一个元素
arr = new int[maxSize]; //初始化模拟队列数组
}
//是否为空
public boolean isEmpty() {
return this.rear == this.front;
}
//是否为满
public boolean isFull() {
return this.rear == maxSize - 1;
}
//加队列
public void addQueue(int value) {
if (isFull()) {
System.out.println("队列已满,不可加入数据");
return;
}
rear++;
arr[rear] = value;
System.out.println("添加成功");
}
//出队列
public int getQueue() {
if (isEmpty()) {
throw new RuntimeException("队列为空,不能取数据");
}
front++;
return arr[front];
}
//队列头
public int headQueue() {
if (isEmpty()) {
throw new RuntimeException("队列为空,不能取数据");
}
return arr[front + 1];
}
//展示数据
public void showQueue() {
if (isEmpty()) {
System.out.println("队列为空,不能展示数据");
return;
}
for (int i = front + 1; i < rear + 1; i++) {
System.out.println("第" + i + "个元素的值为" + arr[i]);
}
}
//测试队列方法
public static void main(String[] args) {
//初始化对象
ArrayQueue queue = new ArrayQueue(3);
//定义菜单进行测试
boolean flag = true;
Scanner scanner = new Scanner(System.in);
char key;//用于接受用户输入
while (flag) {
System.out.println("s(show):展示数据");
System.out.println("a(add):添加数据");
System.out.println("e(exit):退出程序");
System.out.println("h(head):展示头数据");
System.out.println("g(get):取出数据");
key = scanner.next().charAt(0);
switch (key) {
case 's':
queue.showQueue();
break;
case 'a':
System.out.println("请输入要添加的数据");
int value = scanner.nextInt();
queue.addQueue(value);
break;
case 'h':
try {
int res = queue.headQueue();
System.out.println(res);
} catch (Exception e) {
System.out.println(e.getMessage());
}
break;
case 'g':
try {
int res = queue.getQueue();
System.out.println(res);
} catch (Exception e) {
System.out.println(e.getMessage());
}
break;
case 'e':
scanner.close();
flag = false;
break;
default:
break;
}
}
}
}
6.问题分析并优化
1)目前数组使用一次就不能用,没有达到复用的效果
2)将这个数组使用算法,改进成一个环形的队列取模:%
7.数组模拟环形队列
对前面的数组模拟队列的优化,充分利用数组。
因此将数组看做是一个环形的。(通过取模的方式来实现即可)分析说明:
尾索引的下一个为头索引时表示队列满,即将队列容量空出一个作为约定,这个在做判断队列满的时候需要注意 (rear + 1) % maxSize == front 满]
rear == front [空]
测试示意图:
思路如下:
1.front变量的含义做一个调整:front就指向队列的第一个元素也就是说arr[front]就是队列的第一个元素front的初始值=0
2.rear变量的含义做一个调整: rear指向队列的最后一个元素的后一个位置因为希望空出一个空间做为约定rear 的初始值=0
3.当队列满时,条件是**(rear +1) %maxSize=front [满]**
4.对队列为空的条件,rear== front空
5.当我们这样分析,队列中有效的数据的个数 (rear+maxSize-front)%maxSize //例如rear=1 front=0
6.我们就可以在原来的队列上修改得到,一个环形队列
8.环形队列代码实现
package day2;
import java.util.Scanner;
/**
* 作者:灰爪哇
* 时间:2022-12-29
*/
public class CricleArrayQueue {
//测试队列方法
public static void main(String[] args) {
//初始化对象
CricleQueue queue = new CricleQueue(4);
//定义菜单进行测试
boolean flag = true;
Scanner scanner = new Scanner(System.in);
char key;//用于接受用户输入
while (true) {
System.out.println("s(show):展示数据");
System.out.println("a(add):添加数据");
System.out.println("e(exit):退出程序");
System.out.println("h(head):展示头数据");
System.out.println("g(get):取出数据");
key = scanner.next().charAt(0);
switch (key) {
case 's':
queue.showQueue();
break;
case 'a':
System.out.println("请输入要添加的数据");
int value = scanner.nextInt();
queue.addQueue(value);
break;
case 'h':
try {
int res = queue.headQueue();
System.out.println(res);
} catch (Exception e) {
System.out.println(e.getMessage());
}
break;
case 'g':
try {
int res = queue.getQueue();
System.out.println(res);
} catch (Exception e) {
System.out.println(e.getMessage());
}
break;
case 'e':
scanner.close();
flag = false;
break;
default:
break;
}
}
}
}
class CricleQueue{
//初始化队列
private int maxSize;
private int front;
private int rear;
private int[] arr;
//构造器
public CricleQueue(int maxSize) {
this.maxSize = maxSize;//初始化
arr = new int[maxSize]; //初始化模拟队列数组
}
//是否为空
public boolean isEmpty() {
return rear == front;
}
//是否为满
public boolean isFull() {
return (rear + 1) % maxSize == front;
}
//加队列
public void addQueue(int value) {
if (isFull()) {
System.out.println("队列已满,不可加入数据");
return;
}
arr[rear]=value;
rear = (rear +1) % maxSize;
}
//出队列
public int getQueue() {
if (isEmpty()) {
throw new RuntimeException("队列为空,不能取数据");
}
int value =arr[front];
front = (front +1)%maxSize;
return value;
}
//队列头
public int headQueue() {
if (isEmpty()) {
throw new RuntimeException("队列为空,不能取数据");
}
return arr[front];
}
//展示数据
public void showQueue() {
if (isEmpty()) {
System.out.println("队列为空,不能展示数据");
return;
}
for (int i = front ; i < front+size(); i++) {
System.out.println("第" + (i%maxSize) + "个元素的值为" + arr[i%maxSize]);
}
}
//有效数
public int size(){
int value = (rear + maxSize -front)%maxSize;
return value;
}
}
总结
若是有所收获,点赞,关注支持一下!!谢谢!!❤️❤️❤️❤️❤️