利用数组实现简单的循环队列

本文介绍了如何在不扩容数组的情况下使用循环队列插入新元素,并确定队尾位置。通过利用已出队元素的空间,使得队列循环使用数组空间。文章详细展示了入队、出队操作的代码实现,并通过一个例子验证了循环队列的功能。优化后的代码利用取模运算,简化了逻辑。

原理:在数组不做扩容的前提下,如何让新元素入队并确定新的队尾位置呢? 我们可以利用已出队元素留下的空间,让队尾指针重新指回数组的首 位。这样一来,整个队列的元素就“循环”起来了。在物理存储上,队尾的位 置也可以在队头之前。当再有元素入队时,将其放入数组的首位,队尾 指针继续后移即可。

在这里插入图片描述
一直到(队尾下标+1)%数组长度 = 队头下标 时,代表此队列真的已 经满了。需要注意的是,队尾指针指向的位置永远空出1位,所以队列最大容量比数组长度小1。这就是所谓的循环队列。
在这里插入图片描述

public class CirculeQueue {

    /**
     * 队头
     */
    public int front;
    /**
     * 队尾
     */
    private int rear;
    /**
     * 用数组实现
     */
    private int[] array;

    public CirculeQueue(int size) throws Exception {
        if(size<2){
            throw new Exception("队列长度必须大于1");
        }
        array = new int[size];
    }

    /**
     * 入队
     * @param node
     */
    private void enQueue(int node) throws Exception {
        if((rear+1)%array.length==front){
            throw new Exception("队列已满,请移除元素后再放置新元素");
        }

//        // 第一版写法start
//        // 如果放置的第一个元素,队头和队尾此时都为0
//        if(front==0&&rear==0){
//            array[0]=node;
//            rear++;
//            return;
//        }
//        // 判断当前队尾是否是数组最后一个位置
//        // 如果是则将当前元素放置在队尾,同时新的队尾指向数组第一个元素,即下标0
//        if(rear==array.length-1){
//            array[array.length-1]=node;
//            rear = 0;
//        }else{
//            array[rear]=node;
//            rear++;
//        }
//        // 第一版写法end


        // 第二版优化写法
        array[rear]=node;
        // 利用取模运算,一行代码搞定
        rear =(rear+1)%array.length;
    }

    /**
     * 出队
     */
    private int outQueue() throws Exception {
        if(rear == front){
            throw new Exception(" 队列已空!");
        }
        // 每次从队头取出一个元素,同时将该位置的元素置为0
        final int head = array[front];

//        // 第一版写法start
//        array[front]=0;
//        // 如果此时队头已经是数组的最后一位,则重置为0
//        if(front==array.length-1){
//            front=0;
//        }else{
//            // 如果不是,则队头下标后移一位
//            front++;
//        }
//        // 第一版写法end

        // 第二版优化写法
        front =(front+1)%array.length;
        return head;
    }

    /**
     * 打印队列全部元素
     */
    private void output(){
        for(int i=front; i!=rear; i=(i+1)%array.length){
            System.out.println(array[i]);
        }

    }

    /**
     * 利用main方法进行验证
     * @param args
     * @throws Exception
     */
    public static void main(String[] args) throws Exception {
        CirculeQueue myQueue = new CirculeQueue(6);
        myQueue.enQueue(3);
        myQueue.enQueue(5);
        myQueue.enQueue(6);
        myQueue.enQueue(8);
        myQueue.enQueue(1);
        myQueue.output();
        myQueue.outQueue();
        myQueue.outQueue();
        myQueue.outQueue();
        myQueue.enQueue(2);
        myQueue.enQueue(4);
        myQueue.enQueue(9);
        myQueue.output();
    }

}

总结:取模运算的巧妙运用,让我们的代码更加简单易懂!

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值