队列
*银行排队,业务处理(使用环境)
*有序列表,可以用数组或链表实现
*遵循先入先出原则,先存入队列的数据要先输出,后存入的后输出
*添加数据在末尾,取出数据在开头
使用数组模拟队列
*一个常量,两个变量:maxSize(队列最大容量),front(队列前端的位置),rear(队列后端的位置)
*基本操作
*存入数据add
1.先判断是否队列为空(front == rear),不为空时添加时rear+1
2.先判断是否队列已满(rear == maxSize-1),否则无法存入
代码实现:
package 队列的运用;
import java.util.Scanner;
public class ArrayQueueDemo{
public static void main(String[] args){
ArrayQueue queue = new ArrayQueue(); //创建新对象
queue.ArrayQueue(4);
char key = ' '; //创建接收输入
Scanner in = 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 = in.next().charAt(0);
switch(key){
case's':
queue.showQueue();
break;
case'e':
in.close();
loop = false;
break;
case'a':
System.out.println("请输入一个数");
int num = in.nextInt();
queue.addQueue(num);
break;
case'g':
try{
int num2 = queue.getQueue();
System.out.printf("取出的数据是:%d\n",num2);
}
catch(Exception e){
//TODO: handle exception
System.out.println(e.getMessage());
}
break;
case'h':
try{
int num2 = queue.getQueue();
System.out.printf("取出的头数据是:%d\n",num2);
}
catch(Exception e){
//TODO: handle exception
System.out.println(e.getMessage());
}
break;
default:
break;
}
}
System.out.println("thank you for your use!");
}
}
//创建一个ArrayQueue的类
class ArrayQueue{
//定义一个常量两个变量
private int maxSize; //队列最大容量
private int front; //指向队列前端的指针
private int rear; //指向队列后端的指针
private int arrQueue[]; //该数组用于存放数据.模拟队列
//创建队列的构造器,初始化各个变量
public void ArrayQueue(int arrMaxSize){
maxSize = arrMaxSize;
arrQueue = new int[maxSize];
front = -1;
rear = -1;
}
//判断队列是否满
public boolean IsFull(){
return rear == maxSize - 1;
}
//判断队列是否为空
public boolean IsEmpty(){
return rear == front;
}
//添加数据到队列
public void addQueue(int num){
//判断队列是否已满
if(IsFull()){
System.out.println("队列已满,无法添加");
return;
}
rear++; //将rear后移,添加数据
arrQueue[rear] = num;
}
//读取数据出队列
public int getQueue(){
//判断队列是否为空
if(IsEmpty()){
//通过抛出异常来处理
throw new RuntimeException("队列为空,无法读取");
}
front++; //将front后移
return arrQueue[front];
}
//显示队列的所有数据,以供检查结果
public void showQueue(){
//遍历并输出数组arrQueue
if(IsEmpty()){
System.out.println("队列为空,没有数据");
return;
}
for(int i = 0; i < arrQueue.length; i++){
System.out.printf("arrQueue[%d] = %d\n",i,arrQueue[i]);
}
}
//显示队列的头数据
public int showFront(){
//判断是否为空
if(IsEmpty()){
throw new RuntimeException("队列为空,无法读取");
}
return arrQueue[front + 1];
}
}
存在的问题
*只能使用一次,没有充分利用数组
*将原数组通过算法改进为环形队列,取模
解决:
分析
使用数组模拟环形队列的思路
1.将front变量做一个调整,使其指向队列第一个元素,front的初始值变为0
2.将rear变量做一个调整,使其指向队列的最后一个元素的后一个位置
空出一个空间作为约定,初始值也变为0
3.当队列满时条件改变——>(rear + 1) % maxSize = front
4.当队列空时条件改变——>rear = front
5.转换后,队列的有效数据个数方程为——>(rear + maxSize - front) % maxSize
[因为是环形队列,所以rear可能在front前方,因此取模]
代码实现(修改后)
package 队列的运用;
import java.util.Scanner;
public class CircleArrayQueueDemo {
public static void main(String[] args) {
// TODO Auto-generated method stub
CircleArrayQueue queue = new CircleArrayQueue(); //创建新对象
queue.ArrayQueue(4);
char key = ' '; //创建接收输入
Scanner in = 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 = in.next().charAt(0);
switch(key){
case's':
queue.showQueue();
break;
case'e':
in.close();
loop = false;
break;
case'a':
System.out.println("请输入一个数");
int num = in.nextInt();
queue.addQueue(num);
break;
case'g':
try{
int num2 = queue.getQueue();
System.out.printf("取出的数据是:%d\n",num2);
}
catch(Exception e){
//TODO: handle exception
System.out.println(e.getMessage());
}
break;
case'h':
try{
int num2 = queue.getQueue();
System.out.printf("取出的头数据是:%d\n",num2);
}
catch(Exception e){
//TODO: handle exception
System.out.println(e.getMessage());
}
break;
default:
break;
}
}
System.out.println("thank you for your use!");
}
}
class CircleArrayQueue{
//定义一个常量两个变量
private int maxSize; //队列最大容量
private int front; //指向队列前端的指针
private int rear; //指向队列后端的指针
private int arrQueue[]; //该数组用于存放数据.模拟队列
//创建队列的构造器,初始化各个变量
public void ArrayQueue(int arrMaxSize){
maxSize = arrMaxSize;
arrQueue = new int[maxSize];
front = 0;
rear = 0;
}
//判断队列是否满
public boolean IsFull(){
return (rear + 1) % maxSize == front;
}
//判断队列是否为空
public boolean IsEmpty(){
return rear == front;
}
//添加数据到队列
public void addQueue(int num){
//判断队列是否已满
if(IsFull()){
System.out.println("队列已满,无法添加");
return;
}
//先添加再后移
arrQueue[rear] = num;
rear = (rear + 1) % maxSize;
}
//读取数据出队列
public int getQueue(){
//判断队列是否为空
if(IsEmpty()){
//通过抛出异常来处理
throw new RuntimeException("队列为空,无法读取");
}
//先保存front所指向的值保存后front后移
int value = arrQueue[front];
front = (front + 1) % maxSize;
return value;
}
//显示队列的所有数据,以供检查结果
public void showQueue(){
//遍历并输出数组arrQueue
if(IsEmpty()){
System.out.println("队列为空,没有数据");
return;
}
//从front开始遍历,循环至rear
for(int i = front; i < front + (rear + maxSize - front) % maxSize; i++){
System.out.printf("arrQueue[%d] = %d\n",i % maxSize,arrQueue[i % maxSize]);
}
}
//显示队列的头数据
public int showFront(){
//判断是否为空
if(IsEmpty()){
throw new RuntimeException("队列为空,无法读取");
}
return arrQueue[front];
}
}