数据结构和算法02–队列
- 2021 年 4 月 13 日
- 笔记
队列:先进先出、用链表或数组实现。
一、一般的队列
1、思路:
模拟简单队列——队首走的位置不能再添加。
实现方式:两个指针,一个指向队首front、一个指向队尾rear。指向队首的负责取出数据,指向队尾的负责添加数据。
难点:在于添加和取出数据时,指针应先操作该位置数据然后再移动指针,不然指针就没了。
2、代码
代码实现思路:先创建数组队列–>添加判断为空、已满、放入数据、取出数据、遍历队列、查看头节点的方法–>main方法写测试代码。
//测试最基本的队列
public class BasicQueue01 {
//9、创建主方法用于测试
public static void main(String[] args) {
//创建一个队列
ArrayQueue arrQueue = new ArrayQueue(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':
arrQueue.showQueue();
break;
case 'a':
System.out.println("请输入一个数");
int value = scanner.nextInt();
arrQueue.addQueue(value);
break;
case 'g':
try {
int num = arrQueue.getQueue();
System.out.println(num);
}catch(RuntimeException e) {
System.out.println(e.getMessage());
}
break;
case 'h':
try {
int headQueue = arrQueue.headQueue();
System.out.println("第一个数据是" + headQueue);
}catch(RuntimeException e) {
System.out.println(e.getMessage());
}
break;
case 'e':
scanner.close();
loop = false;
default:
break;
}
}
System.out.println("程序退出啦");
}
}
class ArrayQueue{
//1、先给出队列的各种属性
private int maxSize;
private int front;
private int rear;
private int[] arr;
//2、给一个队列的构造方法
public ArrayQueue(int arrmaxSize) {
maxSize = arrmaxSize;
front = -1;
rear = -1;
arr = new int[maxSize];
}
//3、判断队列是否已满
public boolean isFull() {
return rear == maxSize - 1;
}
//4、判断队列是否为空
public boolean isEmpty() {
return rear == front;
}
//5、添加数据到队列
public void addQueue(int n) {
//(1)先判断队列是否已满
if(isFull()) {
System.out.println("队列已满,不能添加~~");
return;
}
//(2)如果不满的话,那就在后面加一格,然后加数据
rear++;
arr[rear] = n;
}
//6、获取队列的数据,出队列
public int getQueue() {
//(1)先判断队列是否为空
if(isEmpty()) {
throw new RuntimeException("队列为空,不能获取~~");
}
//(2)如果不为空的话,那就把指向第一个的前面这个指针,指向第一个,然后取出来,以此类推
front++;
return arr[front];
}
//7、查询队列
public void showQueue() {
if (isEmpty()) {
System.out.println("队列空的,没有数据~~");
return;
}
for(int i = 0;i < arr.length;i++) {
System.out.printf("arr[%d]=%d\n",i+1,arr[i]);
}
System.out.println();
}
//8、显示队列的头数据
public int headQueue() {
if(isEmpty()) {
throw new RuntimeException("队列为空,无法显示");
}
return arr[front+1];
}
}
二、循环队列
1、思路
解决普通队列不能不能在前面位置再添加的问题。
改成环形队列这样就可以反复添加了。
但是这里要注意到最大值后就返回到初始值了。
实现方式:front、rear指针,每添加一个rear指向当前位置后一个,浪费一个元素,指到最后一个元素为满。
难点:因为满了又跳到0,所以得注意front/rear + 1可能回到初始位置,并且得注意rear – front可能存在小减大的情况,所以判断有几个元素的时候不能直接用rear – front的方式。
2、代码
代码实现思路:先创建数组队列–>添加判断为空、已满、放入数据、取出数据、遍历队列、查看头节点的方法–>main方法写测试代码。
//测试环形队列
public class CircleArrayQueue01 {
public static void main(String[] args) {
System.out.println("测试数组模拟环形队列的案例~~~");
CircleQueue circleQueue = new CircleQueue(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':
circleQueue.showQueue();
break;
case 'a':
System.out.println("请输入一个数");
int num = scanner.nextInt();
circleQueue.addQueue(num);
break;
case 'g':
try {
int result = circleQueue.getQueue();
System.out.printf("查到的数据是%d\n",result);
}catch(RuntimeException e) {
System.out.println(e.getMessage());
}
break;
case 'h':
int result = circleQueue.headQueue();
System.out.printf("查到的数据是%d\n",result);
break;
case 'e':
scanner.close();
loop = false;
break;
default:
break;
}
}
System.out.println("退出程序~~");
}
}
class CircleQueue{
//属性
private int maxSize;
private int front;
private int rear;
private int[] arr;
//构造函数
public CircleQueue(int arrMaxSize) {
maxSize = arrMaxSize;
arr = new int[maxSize];
}
//判断是否为空
public boolean isEmpty() {
return rear == front;
}
//判断是否已满
public boolean isFull() {
return (rear + 1) % maxSize == front;
}
//添加数列到队列
public void addQueue(int num) {
if(isFull()) {
System.out.println("队列已满,无法加入");
return;
}
arr[rear] = num;
rear = (rear + 1) % maxSize;
}
//获取队列数据,出队列
public int getQueue() {
if(isEmpty()) {
throw new RuntimeException("队列为空,不能取数据");
}
int value = arr[front];
front = (front + 1)% maxSize;
return value;
}
//显示队列所有数据
public void showQueue() {
if(isEmpty()) {
System.out.println("队列为空,不能显示");
return;
}
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];
}
}