数据结构与算法--数组模拟循环队列(Circular Queue)

此文章仅作为自己学习过程中的记录和总结,同时会有意地去用英文来做笔记,一些术语的英译不太准确,内容如有错漏也请多指教,谢谢!


一、概述

-循环队列的基本组成结构为:

  • (int) maxSIze:队列的最大容量。
  • (int) front:指向队列头的“指针”。(实际上存储的是指向队列第一个元素下标
  • (int) rear:指向队列尾的“指针”。(实际上存储的是队列最后一个元素的下一个位置的下标
  • (E[ ]) queueArr:模拟队列的数组。(E的类型取决于实际情况)

数据结构与算法--数组模拟循环队列(Circular Queue)_第1张图片
-相较于普通队列的区别:

  1. 队列容量:模拟普通队列的数组每个元素都被利用起来;而模拟循环队列的数组的实际有效元素个数为(maxSize - 1),有一个位置被用来对队列空/满做判断。
  2. front和rear的含义: 循环队列中,front存储的是队列第一个元素的下标,rear存储的是队列最后一个元素的下一位置的下标;而普通队列中,front存储的是队列第一个元素的下一位置的下标,rear存储的是队列最后一个元素的下标。
  3. front和rear的默认值: 循环队列中,front和rear默认值为0;而普通队列中,front和rear的默认值为-1。

(关于普通队列,具体可见:数据结构与算法–数组模拟队列(Queue))

(关于C语言描述的普通队列和循环队列,具体可见:队列的定义、顺序、循环、链队列及其部分操作具体实现(C语言描述))

数据结构与算法--数组模拟循环队列(Circular Queue)_第2张图片
-内容

  • 构造方法创建数组循环队列。
  • isEmpty(), isFull()【判断队列是否为空/满】
  • getSIze()【获取队列当前有效元素个数】
  • addQueue()【向队列中添加元素】
  • getQueue()【获取队列头元素并将front向后移一个,实现“假出队列”的效果】
  • peekQueue()【获取队列头元素但不影响front的值】
  • showQueue()【展示队列所有元素】

-特别说明:

  • 判断循环队列是否为空的条件:rear == front
  • 判断循环队列是否为满的条件:(rear + 1) % maxSize == front
  • 循环队列当前有效元素个数:(rear + maxSize - front) % maxSize【可看作对rear-front取绝对值】

二、代码实现

  • Attributes and constructor
/*
 CircularArrayQueue

 Zzay

 2021/01/17
 */
package com.zzay.queue;

/**
 * DIFFERENCE:
 * (1) Capacity:【容量】
 * The capacity of a circular array queue is actually "maxSize - 1",
 * because it need to spare a space for the judgements of "isFull()" and "isEmpty()".
 * (若不留一个空位,则无论是满还是空,都是"front == rear")
 * 
 * (2) Default value of "front" and "rear":【front和rear的默认值】
 * Front: Default value is now 0 in place of -1 as before.
 * Rear: Default value is now 0 in place of -1 as before.
 * 
 * (3) The meaning of "front" and "rear":【front和rear的含义】
 * Front: Points to the first element of the queue, instead of the previous place of the first element.
 * Rear: Points to the next place of the last element, instead of the last element.
 *
 * @author Zzay
 * @version 2021/01/17
 */
public class CircularArrayQueue {

    // The maximum capacity of the array.
    private int maxSize;

    // The indicator of the first element of the queue.
    // The "front" indicator points right to the first element, different from the linear queue.
    // Default value is 0.
    private int front;

    // The indicator of the rear element of the queue.
    // The "rear" indicator points to the next place of the last element, different from the linear queue.
    // Default value is 0.
    private int rear;

    // The array that modifies a queue.
    private int[] queueArr;

    /**
     * Receive a capacity and instantiate a queue array with the max size of the same value.
     * Also, do initializations.
     *
     * @param capacity The expected max size of the queue array
     */
    public CircularArrayQueue(int capacity) {
        if (capacity <= 0) {
            System.out.println("Invalid capacity, enter again...");
            return;
        }
        maxSize = capacity;
        queueArr = new int[maxSize];
    }
}
  • Methods
    /**
     * Judge whether the queue is empty or not.
     *
     * @return True if the queue is empty; false if the queue is not empty
     */
    public boolean isEmpty() {
        return rear == front;
    }

    /**
     * Judge whether the queue is full or not.
     * Plus 1 because we need to spare a space for the judgment,
     * or we are not able to judge whether it's full or not (Draw a graph to see),
     * because no matter full or empty, there's always "front==rear".
     *
     * @return True if the queue is full; false if the queue is not full
     */
    public boolean isFull() {
        return (rear + 1) % maxSize == front;
    }

    /**
     * Get the current size of the queue.
     *
     * @return The current size of the queue
     */
    public int getSize() {
        return (rear + maxSize - front) % maxSize;
    }

    /**
     * Add an element into the queue if it's not full.
     */
    public void addQueue(int data) {
        //Judge if the queue is full or not.
        if (isFull()) {
            throw new RuntimeException("The queue is full, cannot add element into it...");
        }
        queueArr[rear] = data;
        rear = (rear + 1) % maxSize;
    }

    /**
     * Get the first element from the queue if it's not empty.
     *
     * @return The first element in the queue
     */
    public int getQueue() {
        //Judge if the queue is empty or not.
        if (isEmpty()) {
            throw new RuntimeException("The queue is empty, cannot get element from it...");
        }
        int first = queueArr[front];
        front = (front + 1) % maxSize;
        return first;
    }

    /**
     * Get the data of the first element in the queue, without affecting its existence.
     */
    public int peekQueue() {
        if (isEmpty()) {
            throw new RuntimeException("The queue is empty, cannot peek the first element...");
        }
        return queueArr[front];
    }

    /**
     * Display the data in the queue.
     */
    public void showQueue() {
        if (isEmpty()) {
            System.out.println("The queue is empty...");
            return;
        }
        for (int i = front; i < front + getSize(); i++) {
            System.out.printf("array[%d]: %d\n", i % maxSize, queueArr[i % maxSize]);
        }
        System.out.println();
    }
  • Test
/*
 CircularArrayQueueTest

 Zzay

 2021/01/17
 */
package com.zzay.queue;


import java.util.Scanner;

/**
 * @author Zzay
 * @version 2021/01/17
 */
public class CircularArrayQueueTest {

    public static void main(String[] args) {
        char key = ' ';
        boolean loop = true;
        Scanner scanner = new Scanner(System.in);
        CircularArrayQueue circularArrayQueue = new CircularArrayQueue(4);

        while (loop) {
            System.out.println("s(show): show queue");
            System.out.println("a(add): add element");
            System.out.println("g(get): get first element");
            System.out.println("p(peek): peek first element");
            System.out.println("e(exit): exit the program");
            key = scanner.next().charAt(0);
            switch (key) {
                case 's':
                    circularArrayQueue.showQueue();
                    break;
                case 'a':
                    try {
                        System.out.println("Please enter the element you'd like to add:");
                        circularArrayQueue.addQueue(scanner.nextInt());
                    } catch (RuntimeException e) {
                        System.out.println(e.getMessage());
                    }
                    break;
                case 'g':
                    try {
                        System.out.println("The element is: " + circularArrayQueue.getQueue());
                        System.out.println();
                    } catch (RuntimeException e) {
                        System.out.println(e.getMessage());
                    }
                    break;
                case 'p':
                    try {
                        System.out.println("The first element is: " + circularArrayQueue.peekQueue());
                        System.out.println();
                    } catch (RuntimeException e) {
                        System.out.println(e.getMessage());
                    }
                    break;
                case 'e':
                    loop = false;
                    break;
                default:
                    break;
            }
        }
        System.out.println("Thanks for your using!");
    }
}

你可能感兴趣的:(java,数据结构与算法,数据结构,算法,队列,java)