数据结构——Java实现环形队列
初学数据结构观看尚学堂的Java版数据结构笔记
*
1.思路
2.代码实现
package com.Structures.sparsearray.queue;
import java.util.Scanner;
public class CircleArrayQueueDemo {
public static void main(String[] args) {
//测试
System.out.println("测试数组模拟环形队列的案例~~");
//测试
//创建一个队列
CircleArray queue= new CircleArray(4);
char key=' ';//接受用户输入
Scanner scanner=new Scanner(System.in);
boolean loop=true;
//输出一个菜单
while(loop){
System.out.println("s(show):显示队列");
System.out.println("a(add):添加数据到队列");
System.out.println("g(get):从队列取出数据");
System.out.println("h(head):查看队列头的数据");
System.out.println("e(exit):退出程序");
key=scanner.next().charAt(0);
switch (key){
case 's'://显示数据
queue.showArr();
break;
case 'a'://添加数据
System.out.println("输入一个数:");
int value=scanner.nextInt();
queue.addQueue(value);
break;
case 'g'://取出数据
try {
int res= queue.getQueue();
System.out.printf("取出的数据是%d\n",res);
}catch (Exception e){
System.out.println(e.getMessage());
}
break;
case 'h'://查看队列头的数据
try {
int res= queue.headQueue();
System.out.printf("队列头的数据是%d\n",res);
}catch (Exception e){
System.out.println(e.getMessage());
}
break;
case 'e'://退出
scanner.close();
loop=false;
break;
default:
break;
}
}
}
}
class CircleArray{
private int maxSize;//表示数组的最大容量
//front 变量的含义做一个调整:front 就指向队列的第一个元素,就是说arr[front]
//front 的初始值=0
private int front=0;
//rear 变量的含义做一个调整:rear指向队列的最后一个元素的后一个位置,因为希望空出一个空间做约定。
//rear 的初始值=0
private int rear;
private int[] arr;//该数组用于存放数据,模拟队列
//创造构造器
public CircleArray(int arrMaxSize){
maxSize=arrMaxSize;
arr=new int[maxSize];
}
//判断队列是否满
public boolean isFull(){
return (rear+1)%maxSize==front;
}
//判断队列是否为空
public boolean isEmpty() {
return rear == front;
}
//添加数据到队列
public void addQueue(int n) {
//判断队列是否满
if (isFull()) {
System.out.println("队列满,不能加入数据~~");
return;
}
//直接将数据加入
arr[rear]=n;
//将rear后移,这里必须考虑取模
rear=(rear+1)%maxSize;
}
//获取数据到队列,出队列
public int getQueue() {
//判断队列是否为空
if (isEmpty()) {
//抛出异常
throw new RuntimeException("队列空,不能去数据");
//不需要return,throw直接结束
}
//这里需要知道front是指向队列的第一个元素
//1.先把front 对应的数值保存在一个临时变量里
//2.将front后,考虑取模
//3.将临时保存的变量返回
int value=arr[front];
front=(front+1)%maxSize;
return value;
}
//显示队列的所有数据
public void showArr() {
//判断队列是否为空
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 int size(){
return(rear+maxSize-front)%maxSize;
}
//显示队列的头数据,不是取出数据
public int headQueue(){
if (isEmpty()) {
throw new RuntimeException("队列为空,不能取数据~~");
}
return arr[front];
}
}
3.对代码里一些内容进行解释
rear=(rear+1)%maxSize和front=(front+1)%maxSize
分两种情况
1.当rear+1<maxSize;
取模的值直接是rear+1,此时上式为rear=rear+1。
2.当rear+1=maxSize;
取模得的值为0上式就为rear=0,此时rear重新进入环形队列的头部,不用担心数据重复因为前面必须要有一个方法来检查数据是否存满。
前提:!!!!rear是空的不储存数据
(rear+1)%maxSize==fornt//判断队列是否满
1.rear>front
(1) :未满时(rear+1)%maxSize的取值为rear+1怕判断为false
(2) :满时rear+1==maxSize则该式(rear+1)%maxSize=0于front相等怕判断为true
2.rear<front
(1):未满时有些复杂
举例:
在环型队列中maxSize=4,front=3,rear=1
带入式子(rear+1)%maxSize==fornt
(1+1)%4==3
得出不等于
(2):满时
举例:
在环型队列中maxSize=4,front=3,rear=2
带入式子(rear+1)%maxSize==fornt
(2+1)%4==3
得出true
(rear+maxSize-front)%maxSize计算有效个数
1.当rear>front时
该式就相当于rear-front
2.当rear<front时
有效数就是从front开始到rear-1的数,rear+maxSize是原本加已经进入下一循环的数,-front是将原本减少的减掉