简单队列的实现原理
一.队列的定义和特性
- 什么是队列?
队列是一种特殊的线性表,遵循先入的先出,后进入的后出来的这个简单的规则。它只允许在线性表的前端进行删除工作,在表的后端进行添加操作,比如我们的LinkedList集合,它是实现了Queue接口,我们可以理解LinkedList就是一个队列 - JAVA队列的特性
阻塞于非阻塞性:阻塞性于非阻塞性:入列的时候如果队列当中数据是满的,那么会进行等待(阻塞),当队列当中有元素出列,元素数量未超过总的数量的时候,就会解除阻塞状态;进而继续进行入列操作。同理当取出数据的时候,如果队列是空的,那样同样会进行等待(阻塞),当队列当中添加数据,有数据的时候,就会解除阻塞状态可以继续取出数据。反之不管出列入列都不会进行阻塞,入列的时候队列满出列的时候队列是空的都会抛出异常,这就是非阻塞队列。
有界和无界性:有长度限制就是有界队列,没有长度的限制就是无界队列
二.JAVA队列中的常用方法
- 获取头元素的方法
1.poll()获取并且移除队列的头元素,如果队列是空,则返回null
2.remove()获取并且移除队列的头元素,如果队列是空,则抛出NoSuchException的相关异常 - 获取头元素但是不移除的相关方法
1.peek()获取队列的头,但是不移除队列的头,队列为空,返回null
2.element()获取但不移除队列的头元素,如果队列是空,则抛出NoSuchException的相关异常 - 添加元素的方法
1.offer()将指定的元素插入队列,插入成功返回true,插入失败返回false,在有限制的队列当中,offer()函数明显比add函数更加好用
2.add()函数作用就是将指定的数字插入队列当中
三.队列实现的基本分析
//简单队列的实现方式
//首先知道队列当中的必备的参数:队列长度,队列的前端,队列的尾部,以及实现队列所需要的数组
//相关知识 从键盘输入输出的Scanner类,异常处理机制的RuntimeException和写了RuntimeException就要写相关的try
//语句来接收异常 并且打出e.getMessage得到处理异常的时候会输出怎样的语句
/*
- 1.首先需要一个构造函数;构造函数初始化队列个数,并且front,rear初始值设置为-1(理解front和此时rear此时的含义)
- 2.需要两个布尔函数 判断队列是否是空或者是满 队列空条件 front==rear;队列满的条件 max-=rear;
- 3.添加函数,判断是否为满,满的话抛出异常,不满的话,rear加一然后将数据添加到队列当中
- 4.取出函数,判断队列是否是空,空的话抛出异常,然后front数据加1移动一位,输出数组【front】
- 5.显示队列数据函数
- 6.显示队列头部数据的函数:记住front始终是队列头部前一个位置的序号
- */
四.列代码实现
package com.lk.ArrayQueue0428;
import java.util.Scanner;
//简单队列的实现方式
//首先知道队列当中的必备的参数:队列长度,队列的前端,队列的尾部,以及实现队列所需要的数组
//相关知识 从键盘输入输出的Scanner类,异常处理机制的RuntimeException和写了RuntimeException就要写相关的try
//语句来接收异常 并且打出e.getMessage得到处理异常的时候会输出怎样的语句
/*
* 1.首先需要一个构造函数;构造函数初始化队列个数,并且front,rear初始值设置为-1(理解front和此时rear此时的含义)
* 2.需要两个布尔函数 判断队列是否是空或者是满 队列空条件 front==rear;队列满的条件 max-=rear;
* 3.添加函数,判断是否为满,满的话抛出异常,不满的话,rear加一然后将数据添加到队列当中
* 4.取出函数,判断队列是否是空,空的话抛出异常,然后front数据加1移动一位,输出数组【front】
* 5.显示队列数据函数
* 6.显示队列头部数据的函数:记住front始终是队列头部前一个位置的序号
* */
public class ArrayQueue1 {
private int max;//最大的队列的容积
private int front;
private int rear;
private int [] arrQueue;
public static void main(String[] args) {
ArrayQueue1 aq=new ArrayQueue1(3);
char key =' ';
Scanner scan =new Scanner(System.in);
boolean loop=true;
while(loop)
{
System.out.println("S(show)取出数据以后队列的数据");
System.out.println("s(show)展示全部队列数据");
System.out.println("e(exit)退出程序");
System.out.println("g(get)得到队列数据");
System.out.println("a(add)向队列添加数据");
System.out.println("h(head)查看队列头部数据");
//获取输入的第一个字符
key=scan.next().charAt(0);
switch (key) {
case 'S':
aq.showQueue2();
break;
//如果没有break的话,那样的话执行完相关函数以后,自动结束循环
case 's':
aq.showQueue();
break;
case 'a':
//获取输入的第一个整数值
try {
System.out.println("请输入一个数字,添加到队列当中");
int value =scan.nextInt();
aq.addQueue(value);
} catch (Exception e) {
// TODO: handle exception
System.out.println(e.getMessage());
}
break;
case 'g':
//一旦相关的函数当中抛出了异常,想要在程序当中观察到这样异常的时候,输出一段话,并且程序不会结束
//那样的话就要写一个try这样的函数体来接收这些异常
try {
int res;
res=aq.getQueue();
System.out.printf("输出的数字是%d\n",res);
} catch (Exception e) {
// TODO: handle exception
System.out.println(e.getMessage());
}
break;
case 'h':
try {
int res=aq.headQueue();
System.out.printf("头部的数据是%d\n",res);
} catch (Exception e) {
// TODO: handle exception
System.out.println(e.getMessage());
}
break;
case 'e':
//首先关闭输入输出的通道,其次退出循环即可退出队列
scan.close();
loop=false;
break;
default:
break;
}
}
System.out.println("程序退出");
}
public ArrayQueue1(int maxNumber)
{
this.max=maxNumber;
this.front=-1;
this.rear=-1;
this.arrQueue=new int [maxNumber];
}
//需要一个函数判断队列当中是否是空
public boolean isEmpty()
{
return front==rear;
}
//需要一个函数判断队列当中是否是满
public boolean isFull()
{
return rear==(max-1);
}
//添加
public void addQueue(int n)
{
if(isFull())
{
//当队列满的时候,抛出runtimeException当中的字符串话语
throw new RuntimeException("队列已经满了,不能在添加数据");
}
rear++;
arrQueue[rear]=n;
}
//首先判断队列是不是空的
public int getQueue()
{
if(isEmpty())
{
System.out.println("队列空的,没有数据~~~");
//return -1 ;
throw new RuntimeException("队列空,不能取数据");
}
front++;//front指向队列前一个的位置
return arrQueue[front];
}
//显示队列的所有的数据
//注意这个输出的数据是初始化时候队列的数据,当取出数据的时候队列的数据已经更新了
public void showQueue()
{
if(isEmpty())
{
System.out.println("队列空的,没有数据~~~");
return ;
}
for(int i=0;i<arrQueue.length;i++)
{
System.out.printf("arr[%d]=%d\n",i,arrQueue[i]);
}
}
public void showQueue2()
{
if(isEmpty())
{
System.out.println("队列空的,没有数据~~~");
return ;
}
for(int i=1;i+front<=rear;i++)
{
System.out.printf("arr[%d]=%d\n",i-1,arrQueue[i+front]);
}
return ;
}
//因为之前取走了代表0号位置上面的值其实就已经不在了的,那么此时front+1才代表现在的头号元素的位置
public int headQueue()
{
if(isEmpty())
{
throw new RuntimeException("队列空的,没有数据");
}
return arrQueue[front+1];
}
}
五.代码实现效果展示
六:反思总结
1.异常处理机制还不够了解和深入
2.输入输出的用法不熟练,scanner类的运用
3.需要在学习异常处理机制相关知识和基础的I/O操作的相关知识