定义:队列是一种特殊的线性表,特殊之处在于它只允许在表的前端(front)进行删除操作,而在表的后端(rear)进行插入操作,和栈一样,队列是一种操作受限制的线性表。进行插入操作的端称为队尾,进行删除操作的端称为队头。
即遵循先进先出的原则
那么队列怎么样才能够循环利用呢?这时候就引出了循环队列的概念,但是在实现循环队列之前,先讲一讲普通的由数组实现的队列。
队列之普通数组实现篇

设置一个队列,用数组实现,front表示队列的前端,rear表示数组的后端,他们的初始值都为-1;当向队列中加入数据data时,rear++,arr[rear]=data,假设当加入的data=10,此时arr[0]=10,rear指向0处。当rear指向6时,即rear=maxSize-1时,此时队列就满了。当向数组中取值时,front++,return arr[front],front向上移动。
下面使用代码实现:
class ArrayQueue{
private int maxSize;//数组长度,即队列长度
private int front;//队列头
private int rear;//队列尾
private int[] arr;//数组
public ArrayQueue(int maxSize){
this.maxSize=maxSize;
front=-1;
rear=-1;
arr=new int[maxSize];
}
//判断是否为空
public boolean isEmpty(){
return front==rear;
}
//判断是否满了
public boolean isFull(){
return rear==maxSize-1;
}
//向队列中加入数据
public void add(int data){
if(isFull()){
System.out.println("队列已满");
return;
}
rear++;
arr[rear]=data;
}
//像队列中取出数据
public int get(){
if(isEmpty()){
throw new RuntimeException("队列是空的");
}
front++;
return arr[front];
}
//显示队列中的所有数据
public void show(){
if(isEmpty()){
System.out.println("队列是空的");
return;
}
for (int i=front+1;i<rear+1;i++){
System.out.println("arr["+i+"]"+arr[i]);
}
}
//显示队列的头元素
public void headQueue(){
if(isEmpty()){
throw new RuntimeException("队列是空的");
}
System.out.println("arr["+(front+1)+"]"+arr[front+1]);
}
然后创建一个程序运行一下这个普通的数组队列吧!
public static void main(String[] args) {
Scanner sc=new Scanner(System.in);
ArrayQueue arrayQueue=new ArrayQueue(3);
char c=' ';
boolean flag=true;
while (flag){
System.out.println("a(add)");
System.out.println("g(get)");
System.out.println("s(show)");
System.out.println("h(head)");
System.out.println("e(exit)");
c = sc.next().charAt(0);
switch (c){
case 'a':
System.out.println("请输入一个数");
int num = sc.nextInt();
arrayQueue.add(num);
break;
case 'g':
try {
arrayQueue.get();
}catch (Exception e){
System.out.println(e.getMessage());
}
break;
case 's':
arrayQueue.show();
break;
case 'h':
try {
arrayQueue.headQueue();
}catch (Exception e){
System.out.println(e.getMessage());
}
break;
case 'e':
flag=false;
break;
}
}
}
这里测试的时候为了简单,将队列的size设置为3.

队列之循环队列实现篇
先看一张图

class CircleArrayQueue{
private int front;
private int rear;
private int maxSize;
private int []arr;
public CircleArrayQueue(int maxSize){
this.maxSize=maxSize;
arr=new int[maxSize];
}
public boolean isEmpty(){
return front==rear;
}
public boolean isFull(){
return (rear+1)%maxSize==front;
}
public void add(int data){
if(isFull()){
System.out.println("队列已满");
return;
}
arr[rear]=data;
rear= (rear+1)%maxSize;
}
public int get(){
if(isEmpty()){
throw new RuntimeException("队列是空的");
}
int data=arr[front];
front=(front+1)%maxSize;
return data;
}
//需要计算出队列中的个数
public void show(){
if (isEmpty()){
System.out.println("队列是空的");
return;
}
for (int i=front;i<front+getNum();i++){
System.out.println("arr["+(i%maxSize)+"]"+arr[i%maxSize]);
}
}
/*当队列不是循环数组的时候,个数为rear-front
* 但是当为循环数组时,rear-front的值可能为负数
* 所以此时应该加上maxSize,
* 但同时如果rear-front的值为正数的时候,加上maxSIze的值超出了数组的范围
* 所以此时需要与maxSize取余*/
public int getNum(){
return (rear-front+maxSize)%maxSize;
}
public void headQueue(){
if(isEmpty()){
throw new RuntimeException("队列是空的");
}
System.out.println("队列的头元素为"+arr[front]);
}
}
可以将循环数组队列的代码与普通数组队列的代码相互比较,可以 看出:
1.判断是否为空的方法是相同的;
2.判断是否为满的代码有了区别,因为普通数组队列是一次性的,当rear到达了maxSize-1时便队列为满,而循坏数组的队列需要判断rear下一个地址的值是否为空,如果为空,则数组没有满。并且要考虑到rear下一个地址是否超过了队列的范围,如果超过就会指到0地址处,即(rear+1)%maxSize是否等于maxSize;
3.add方法和show方法有一点区别,最初让front和rear都指向0,当rear和front都为maxSize-1时,继续增加让它们指向队列的0地址处。
4.headQueue方法无区别
创建程序的代码和前面的相同。 下面为程序运行的截图
public class CircleArrayQueueDemo {
public static void main(String[] args) {
Scanner sc=new Scanner(System.in);
CircleArrayQueue arrayQueue=new CircleArrayQueue(4);
char c=' ';
boolean flag=true;
System.out.println("a(add)");
System.out.println("g(get)");
System.out.println("s(show)");
System.out.println("h(head)");
System.out.println("e(exit)");
while (flag){
c = sc.next().charAt(0);
switch (c){
case 'a':
System.out.println("请输入一个数");
int num = sc.nextInt();
arrayQueue.add(num);
break;
case 'g':
try {
arrayQueue.get();
}catch (Exception e){
System.out.println(e.getMessage());
}
break;
case 's':
arrayQueue.show();
break;
case 'h':
try {
arrayQueue.headQueue();
}catch (Exception e){
System.out.println(e.getMessage());
}
break;
case 'e':
flag=false;
break;
}
}
}
}
class CircleArrayQueue{
private int front;
private int rear;
private int maxSize;
private int []arr;
public CircleArrayQueue(int maxSize){
this.maxSize=maxSize;
arr=new int[maxSize];
}
public boolean isEmpty(){
return front==rear;
}
public boolean isFull(){
return (rear+1)%maxSize==front;
}
public void add(int data){
if(isFull()){
System.out.println("队列已满");
return;
}
arr[rear]=data;
rear= (rear+1)%maxSize;
}
public int get(){
if(isEmpty()){
throw new RuntimeException("队列是空的");
}
int data=arr[front];
front=(front+1)%maxSize;
return data;
}
//需要计算出队列中的个数
public void show(){
if (isEmpty()){
System.out.println("队列是空的");
return;
}
for (int i=front;i<front+getNum();i++){
System.out.println("arr["+(i%maxSize)+"]"+arr[i%maxSize]);
}
}
/*当队列不是循环数组的时候,个数为rear-front
* 但是当为循环数组时,rear-front的值可能为负数
* 所以此时应该加上maxSize,
* 但同时如果rear-front的值为正数的时候,加上maxSIze的值超出了数组的范围
* 所以此时需要与maxSize取余*/
public int getNum(){
return (rear-front+maxSize)%maxSize;
}
public void headQueue(){
if(isEmpty()){
throw new RuntimeException("队列是空的");
}
System.out.println("队列的头元素为"+arr[front]);
}
}