Java 数据结构与算法 环形队列

最近由于忙其他事情,有一段时间没有接触一些基础的数据结构了,前两天遇到一个手写环形队列的题,都搞忘了,再次特地写一篇博客,记录一下,加深印象。

环形队列主要是有几个公式容易忘记,其实理解了也很简单。

几个必要的变量说明

int[] arr:存储队列的数组,也可以用链表做,这里不多赘述

int maxSize:数组的长度,也是队列的最大长度,通常是初始化队列时传入

int front:队头指针,记录数组中队列的队头下标

int size:当前的队列的长度

注:以前学习数据结构时,一般老师或者教材在实现队列都是用的front和rear双指针来表示队头队尾,但其实一个环形队列,我们只需要一个头指针即可。

下面的poll、peek这些命名我是参考的Java中Queue队列操作

公式1:offer入队操作,向队尾添加元素时,需要计算出队列长度,将新的元素添加到队尾

             index = (front + size) % maxSize;

公式2:poll出队操作,取出队头元素时,front需要向数组后面移动一位

             front = (front + 1) % maxSize;

公式3:getLast获取队尾元素操作,该操作一般队列不提供,但这里顺便提一下

             last = (front + size - 1) % maxSize;

其实公式1看懂了,公式3很容易理解,就是在队尾的后一个元素插入元素嘛

下面直接上代码

/**
 * 数组实现环形队列
 */
public class LoopArrayQueue {
    private int[] arr; // 该数据用于存放数据, 模拟队列    
    private int maxSize; // 表示数组的最大容量    
    private int front; // 队列头,指向队列的第一个元素
    private int size;//记录当前数组中队列的长度

    // 创建队列的构造器
    public LoopArrayQueue(int arrMaxSize) {
        maxSize = arrMaxSize;
        arr = new int[maxSize];
        front = 0;
        size = 0;
    }

    // 判断队列是否满
    public boolean isFull() {
        return size == maxSize;//数组长度和队列长度相同说明队列已满
    }

    // 判断队列是否为空
    public boolean isEmpty() {
        return size == 0;
    }

    // 添加数据到队列,入队列
    public void offer(int n) {
        // 判断队列是否满
        if (isFull()) throw new RuntimeException("队列满,不能加入数据~");
        int index = (front + size) % maxSize;//计算出要存放的位置,相当于rear
        arr[index] = n;
        size++;//队列长度+1
    }

    // 获取队列的头数据,同时删除数据
    public int poll() {
        if (isEmpty()) throw new RuntimeException("队列空,不能取数据");
        int res = arr[front];
        front = (front + 1) % maxSize; //队头的位置向后移动
        size--;//队列长度-1
        return res;
    }

    // 读取队列的头数据, 不删除数据
    public int peek() {
        if (isEmpty()) throw new RuntimeException("队列空的,没有数据~~");
        return arr[front];//front起始就指向数组开始
    }

    /**
     * 读取队尾元素 - 一般队列不提供这个个操作
     * 只要知道队头位置、数组长度、队列个数就可以用下面的公式求出队尾位置
     *  tailIndex = (headIndex + count −1) % capacity
     *  得到队尾位置后,即可对整个环形队列进行操作。
     */
    public int getLast(){
        if(isEmpty()) throw new RuntimeException("队列空的,没有数据~~");
        int tail = (front + size - 1) % maxSize;
        return arr[tail];
    }

    // 显示队列的所有数据
    public void display() {
        if (isEmpty())
            throw new RuntimeException("队列空的,没有数据~~");
        //遍历应该从front开始遍历,遍历次数为队列有效个数
        System.out.print("当前队伍:");
        for (int i = front; i < front+size; i++) {
            System.out.print(arr[i]+"\t");
        }
        System.out.println("");
    }


}

 下面进行测试一下:

public static void main(String[] args) {
    LoopArrayQueue queue = new LoopArrayQueue(3);//传入队列的长度,这里长度是传入的数值-1
    queue.offer(11);
    queue.offer(22);
    queue.offer(33);
    System.out.println("显示队头:"+queue.peek());
    System.out.println("显示队尾:"+queue.getLast());
    System.out.println("队头出队:"+queue.poll());
    System.out.println("队头出队:"+queue.poll());
    queue.display();
    System.out.println("显示队头:"+queue.peek());
}

运行结果如下图

猜你喜欢

转载自blog.csdn.net/c_o_d_e_/article/details/111969496