package org.example._02环形队列;
import java.util.Scanner;
public class CircleQueueDemo {
public static void main(String[] args) {
System.out.println("-----------------队列测试------------------");
CircleQueue queue = new CircleQueue(4);
char key = ' ';
Scanner scanner = new Scanner(System.in);
boolean loop = true;
while (loop) {
System.out.println("-----------------");
System.out.println("输入s显示队列");
System.out.println("输入e退出程序");
System.out.println("输入a添加元素");
System.out.println("输入g取出头元素");
System.out.println("输入h显示头元素");
System.out.println("-----------------");
//charAt(index)是一个字符串的方法,它用于获取指定索引位置的字符。
// 索引从 0 开始计数。在这里,charAt(0)就是获取这个字符串的第一个字符,也就是 “H”
key = scanner.next().charAt(0);
switch (key) {
case 's':
queue.showQueue();
break;
case 'e':
scanner.close();
loop = false;
System.exit(0);
break;
case 'a':
System.out.println("输入一个数");
int val = scanner.nextInt();
queue.addQueue(val);
break;
case 'h':
try {
System.out.println("头元素是:" + queue.getHeadEle());
} catch (Exception e) {
System.out.println(e.getMessage());
}
break;
case 'g':
try {
int res = queue.getQueue();
System.out.printf("取出的数据是%d\n", res);
} catch (Exception e) {
System.out.println(e.getMessage());
}
break;
}
}
System.out.println("退出程序。");
}
}
// 队列通常使用环形队列,因为普通队列只能使用一次,没卵用,另外队列是用数组完成的
// 知识点1:取模,若长度为3,则4,5,6 对应的位置就是 1,2,3,实现了位置循环使用
// 知识点2:两个指针的新位置由公式 (x + 1) % maxSize 确定
// 知识点3:有效元素个数由公式 (rear + maxSize - front) % maxSize 得到
// 相当于得到rear比front多跑一圈后比front多出来的身位,对队列长度取模,得到的就是实际长度
// 知识点4:涉及到取值的都判空+抛异常提示,涉及到显示元素的要判空+打印提示
class CircleQueue {
// 基础要素
int maxSize; //队列存储空间
int front; //头指针
int rear; //尾指针
int[] arrQueue; //队列的本体--数组
//构造函数
public CircleQueue(int size) {
maxSize = size;
arrQueue = new int[size];
rear = 0;
front = 0; //环形队列约定预留一个空间放尾指针,且头尾初始值都是0
}
//判满
public boolean isFull() {
//如果rear后移后会碰到front,则满
return (rear + 1) % maxSize == front;
}
//判空
public boolean isEmpty() {
//rear不后移就碰到front,则空
return rear == front;
}
//添加
public void addQueue(int val) {
//添加先判满
if (isFull()) {
System.out.println("队列已满~");
return;
}
//未满,则尾指针处先放值,然后尾指针在环形队列中后移
arrQueue[rear] = val;
rear = (rear + 1) % maxSize;
}
//取值
public int getQueue() {
//取值先判空,然后抛异常
if (isEmpty()) {
throw new RuntimeException("队列为空,无值可取~");
}
//不空,则头指针处先取值,然后头指针在环形队列中后移
//但是头指针的值不能直接return掉,因为return完就没机会移动头指针了,所以要先存起来
int val = arrQueue[front];
front = (front + 1) % maxSize;
return val;
}
//显示队列中所有元素
public void showQueue() {
//显示值先判空,但不用异常
if (isEmpty()) {
System.out.println("队列为空,无值可显~");
return;
}
//不空,则从front开始打印元素
for (int i = front; i < front + queueValidSize(); i++) {
// 易错点 这里是 i % maxSize,因为front+size可能会很大导致i后面越界
System.out.printf("arr[%d] = %d\n", i % maxSize, arrQueue[i % maxSize]);
}
}
public int queueValidSize() {
return (rear + maxSize - front) % maxSize;
}
public int getHeadEle() {
//取值先判空,然后抛异常
if (isEmpty()) {
throw new RuntimeException("队列为空,木有数据~");
}
return arrQueue[front];
}
}
韩顺平循环队列实现
最新推荐文章于 2025-05-15 20:49:36 发布