数组模拟实现队列(Java语言描述)

队列的实例:电影院购票、排队打饭、去麦当劳买吃的,银行排队叫号等等这些场合都需要排队,生活中的各种排队现象就展示了队列的实例

队列的介绍:队列是个有序列表

队列的实现方式:

  1. 数组
  2. 链表

注意:若使用数组来模拟实现队列,就是顺序存储,若使用链表来实现队列,就是链式存储。

队列的重要原则(或者叫做特点):先入先出(FIFO) ,也就是说谁先进入到队列谁就会先被调出去。即:先存入队列的数据要先取出,反之,后存入队列的数据要后取出

使用数组来模拟实现队列

画图分析:
数组模拟实现队列(Java语言描述)_第1张图片

rear : 表示队尾,就是队列的尾部

front:表示对首,就是队列的头部

当把数据添加到队列中时,front的值和位置不会产生变化,而rear队尾的位置和值会随着数据的增加变化而变化。由此说明,往队列中添加数据是从队列尾部rear加,变化的是rear,而不是front

当把数据从队列中取出时,rear的值和位置不会产生变化,而front队首的位置和值会随着数据的减少变化而变化。由此说明:往队列中取出数据是从队列头部front取出的,变化的是front,而不是rear


若使用数组的结构来存储队列的数据,则数组队列的声明如下图所示:
数组模拟实现队列(Java语言描述)_第2张图片

设计队列时,首先定义个ArrayQureue类,类中有4个属性(也叫做成员变量)分别是数组queueArr[]maxsizefrontrear

maxsize:代表队列的最大容量,就是该队列数组最大能存储多少个数据

rear:用来记录队列的队尾

front:用来记录队列的队首

queueArr[]:数组模拟实现队列,队列存的数据就是存放在数组中的。

队列的常用操作:(重要

  1. 创建队列
  2. 把数据添加到队列中(入队列)
  3. 把数据从队列从取出来(出队列)

入队列思路分析:

将入队列这个功能写成一个对应的成员方法addQueue(int n)

实现入队列需要两个步骤:

  1. 首先必须判断队列是否已满rear == maxsize - 1,当队尾rear = maxsize - 1时,则说明队列已经满了,就不能实现入队列了,反之,当队尾rear != maxsize - 1 || real < maxsize - 1时,则说明队列未满,就可实现入队列操作

    注意:判断队列是否满,取决于maxsizerear之间的关系

    画图分析:
    数组模拟实现队列(Java语言描述)_第3张图片
    数组模拟实现队列(Java语言描述)_第4张图片

  2. 将队尾rear ++,rear的位置往后移动以下,数据从队尾加入。

数组模拟实现队列(Java语言描述)_第5张图片

出队列思路分析:

将出队列这个功能写成一个对应的成员方法getQueue(int num)

实现出队列需要两个步骤:

  1. 首先判断队列是否为空rear == front,若队首和队尾相等了rear = front,则证明队列是空的,就不能实现出队列的操作,若强制实现出队列,会抛出数组下标越界异常,反之,则证明队列不为空,则可实现出队列的操作。

    注意:判断队列是否满,取决于frontrear之间的关系

    画图分析:

    数组模拟实现队列(Java语言描述)_第6张图片

  2. 将队首front ++,front的位置往后移动以下,数据从队首取出。

    画图分析:
    数组模拟实现队列(Java语言描述)_第7张图片

    front = - 1时, 队列中的第一个数据是queueArr[0],front指向的是队列头的前一个位置,front不包含这个queueArr[0]数据,当front ++ ;这时front = 0,然后实现return queueArr[front];出队列操作,则证明queueArr[0]出队列了,同理,队列中不再包含queueArr[0]这个数据,那么队列中的第一个数据所在的位置由原来的queueArr[0]变为了现在的queueArr[1]。画图分析:
    数组模拟实现队列(Java语言描述)_第8张图片

代码实现:

import java.util.Scanner;
public class ArrayDemoTest{
	public static void main(String[] agrs){
		// 实例化 ArrayQueue对象
		ArrayQueue arrayQueue = new ArrayQueue(3);
		char c = ' ';
		Scanner input = new Scanner(System.in);
		boolean flag = true;
		while(flag){
			System.out.println("s (showQueue()) : 显示队列中的所有数据");
			System.out.println("a(addQueue()):  实现入队列操作,把数据添加到队列中");
			System.out.println("g(getQueue()):  实现出队列操作,把数据从队列中取出来");
			System.out.println("h (headQueue()) : 查看队列中的第一个数据");
			System.out.println("e (exit) : 退出程序");
			System.out.println("请选择(s、a、g、h、e):");
			c = input.next().charAt(0);	
			switch(c) {
				case 'e':
					input.close(); 
					flag = false;
					break;
				case 's':
					arrayQueue.showQueue();
					break;
				case 'a':
					System.out.println("请输入一个数:");
					int num = input.nextInt();
					arrayQueue.addQueue(num);
					break;
				case 'g':
					try{
						System.out.println("取出的数据是" + arrayQueue.getQueue());
					}catch(Exception e){
						System.out.println(e.getMessage());
					}
					break;
				case 'h':
					try{
						System.out.println("队列的第一个数据是" + arrayQueue.headQueue());
					}catch(Exception e){
						System.out.println(e.getMessage());
					}
					break;
				default:
					System.out.println("您输入的信息错误");
					break;
			}
		}
		System.out.println("程序正常退出");
	}
}
// 定义个ArrayQureue类
class ArrayQueue{
    // 编写属性(共4个)
    // maxsize : 表示队列的最大容量
    private int maxsize;
    // rear : 表示队列的尾部,即:队尾
    private int rear;
    // front :表示 队列的头部 即:队首
    private int front;
    // queueArr[] : 数组模拟实现队列,队列存的数据就是存放在数组中的
    private int queueArr[];
    
    // 编写队列的构造方法,实现将局部变量maxsize的值赋值给成员变量maxsize并对rear、front和queueArr[] 进行初始化
    // 带参构造
    public ArrayQueue(int maxsize){
        // 将局部变量maxsize的值赋值给成员变量maxsize
        this.maxsize = maxsize;
        // 对rear、front和queueArr[] 进行初始化
        rear = -1;
        front = -1;
        queueArr = new int[maxsize];
    }
    // 无参构造
    public ArrayQueue(){
        
    }
    // 编写成员方法isFull(),用来判断队列是否满
    public boolean isFull(){
        // true : 满  false : 未满
        return rear == maxsize - 1; 
    }
    // 编写成员方法isEmpty(),用来判断队列是否为空
    public boolean isEmpty(){
        // true : 空 false : 不为空
        return rear == front;
    }
    // 编写无返回值带参的成员方法,实现入队列addQueue(int num),类似于setXxx(形参列表)方法
    public void addQueue(int num){
      	if(isFull()){
            // 抛异常做处理,给提示文字
            System.out.println("队列已满,不能实现入队列操作");
            return;
        }
        queueArr[++rear] = num;
    }
    // 编写有返回值无参的成员方法,实现出队列getQueue(),类似于getXxx()方法
    public int getQueue(){
        if(isEmpty()){
            throw new RuntimeException("空队列,不能实现出队列操作");
        }
        return queueArr[++front];
    }
    // 编写成员方法,使用增强for循环 | 普通for循环遍历队列中的所有数据.
  	public void showQueue(){
        if(isEmpty()){
            System.out.println("空队列,没有数据可以遍历");
            return;
        }
        /*for(int temp : queueArr){
            System.out.print(temp + " ");
        }*/
        for(int i = 0;i < queueArr.length ; i++){
            System.out.println("queueArr[" + i + "] = " + queueArr[i]);
        }
        
    }
    // 编写成员方法,显示队列的第一个数据,注意:不是出队列
    public int headQueue(){
        if(isEmpty()){
         	throw new RuntimeException("空队列,队列中没有数据");   
        }
        return queueArr[front + 1];
    }
}

问题及优化:

  1. 目前数组使用一次就不能使用了,没有达到复用的效果
  2. 将这个数组使用算法改进成环形队列的数组,核心是采用取模% 来实现的

总结:

  1. front 始终指向的是队列头的前一个位置,不是直接指向队列中的第一个数据,始终不包含队列中的第一个数据,front所指向的存储空间中始终没有数据。当rear 和front相等 时,front不包含队列中的任何数据,因为队列是空的,也无法实现出队列操作。

数组模拟实现队列(Java语言描述)_第9张图片

数组模拟实现队列(Java语言描述)_第10张图片

  1. rear指向队列的尾部的具体的数据,包含队列的最后一个数据。当rear 和front相等 时,rear不包含队列中的任何数据,因为队列是空的。

    画图分析:
    数组模拟实现队列(Java语言描述)_第11张图片

数组模拟实现队列(Java语言描述)_第12张图片

  1. 判断队列是否满 ,取决于rearmaxsize的关系rear == maxsize - 1
  2. 判断队列是否为空 ,取决于rearfront的关系 rear == front

你可能感兴趣的:(数据结构和算法)