首先我们先来了解一下队列是什么?
队列:数据先入先出,后进后出(与栈刚好相反),主要通过数组实现。需要通过两个指针来创建对应的队列;一个指针为前缀pre,一个指针为后缀rear。pre指针指向先进来的数的前面,rear指针指向数组的加入数,即有数据的末尾,以此来判断加入的数组是否已满。(我们这个pre指针指向的是首个数据的前面(要保证先进先出,就得要有个指针指向数据的第一个),而rear指向的是数据中的最后一个数据)
这是我对于队列的总结,但这只是普通队列,该种方式实现的队列只能使用一次(大家有兴趣可以去实现一下这个普通队列);如果要做到循环使用,那我们就要实现环形队列
环形队列:通过取模的方法实现环形队列,需要空出一个空间容量作为约定,此时pre指向的是先进来的数,rear为最后一个元素的后一个位置。此时(rear+1)% maxSize==front(满),rear==front(空)。下图是尚硅谷韩顺平老师对于环形队列的分析,我觉得很形象,图中的MaxSize-1为预留出的空间,我们需要一个预留的空间以达到循环的目的,即我们对于这个空间不操作,用于循环递换。
图中的得到有效数据的个数的公式,为什么加maxSize韩老师没有具体讲,我总结为+maxSize的原因是怕rear-front出现负数,此时无法取模,故加maxSize。
如果对于上图还不是很明白的,我附上代码实现,大家应该就懂了,如果还有不理解的,可以在评论区留言,我会及时回复解答的。
package com.liu.Array;/*** @author lwx* @create 2021-09-06 21:17*/
public class CircleQueue {private int pre;//指向先进来的数private int rear;//指向数据末尾的下一位private int[] queue;//队列private int maxSize;//队列的长度public static void main(String[] args) {CircleQueue circleQueue = new CircleQueue(10);circleQueue.addQueue(2);circleQueue.addQueue(4);circleQueue.addQueue(5);circleQueue.addQueue(8);circleQueue.addQueue(10);circleQueue.addQueue(10);circleQueue.addQueue(10);circleQueue.addQueue(10);circleQueue.addQueue(10);circleQueue.addQueue(10);circleQueue.addQueue(11);circleQueue.addQueue(12);System.out.println("加入数据后队列为:");circleQueue.show();circleQueue.deleteQueue();circleQueue.addQueue(0);System.out.println("删除数据后队列为: ");circleQueue.show();}public CircleQueue(int maxSize) {this.maxSize = maxSize;queue = new int[this.maxSize];pre = 0;rear = 0;}/*** 判断该队列是否已满** @return*/public boolean isFull() {return (rear + 1) % maxSize == pre;}/*** 判断该队列是否空** @return*/public boolean isEmpty() {return rear == pre;}/*** 加入数据到队列中** @param num 要传入的数据*/public void addQueue(int num) {if (isFull()) {System.out.println("该队列已满,无法添加");return;}queue[rear] = num;//加入完数据后rear指针要向后移动,借助取模以达到循环rear = (rear + 1) % maxSize;}/*** 删除队列中的数据* 遵循先进先出原则*/public int deleteQueue() {if (isEmpty()) {throw new RuntimeException("该队列为空,无法取出数据");}int result = queue[pre];//弹出数据后pre指针要向后移动,借助取模以达到循环pre = (pre + 1) % maxSize;return result;}/*** 获取头数据** @return*/public int getHead() {return queue[pre + 1];}/*** 获取有效数据的个数** @return*/public int size() {return (rear - pre + maxSize) % maxSize;}/*** 显示队列的所有数据*/public void show() {if (isEmpty()) {System.out.println("队列中没有数据");return;}for (int i = pre; i < pre + size(); i++) {i = i % maxSize;//为了防止i的数值大于数组的长度System.out.print(queue[i] + " ");}System.out.println();}
}