环形队列的实现

首先我们先来了解一下队列是什么?

队列:数据先入先出,后进后出(与栈刚好相反),主要通过数组实现。需要通过两个指针来创建对应的队列;一个指针为前缀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();
    }
}

  • 2
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值