简单队列的实现原理

一.队列的定义和特性

  • 什么是队列?
    队列是一种特殊的线性表,遵循先入的先出,后进入的后出来的这个简单的规则。它只允许在线性表的前端进行删除工作,在表的后端进行添加操作,比如我们的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()函数作用就是将指定的数字插入队列当中

三.队列实现的基本分析

java队列机制的作用_System

//简单队列的实现方式
//首先知道队列当中的必备的参数:队列长度,队列的前端,队列的尾部,以及实现队列所需要的数组
//相关知识 从键盘输入输出的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];
	}
}

五.代码实现效果展示

java队列机制的作用_开发语言_02


java队列机制的作用_System_03


java队列机制的作用_数据_04

六:反思总结

1.异常处理机制还不够了解和深入
2.输入输出的用法不熟练,scanner类的运用
3.需要在学习异常处理机制相关知识和基础的I/O操作的相关知识