数据结构与算法之环形队列(以int数组为例,不包含扩容)

废话补不多说了, 环形队列最难理解的部分就是取模部分, 可以先看一下这个链接的大佬的讲解:
https://juejin.im/post/5c95d2515188252dab3ebfc5
如果上面这个链接的内容看懂了, 那本章的内容就不用看了, 就只当我做一个学习记录就好了:

// 代码部分
import java.util.Arrays;

public class CircleArrayQueue2 {
    private int front;
    private int tail;
    private final int capacity;
    private final int[] queue;

    public CircleArrayQueue2(int capacity) {
        this.capacity = capacity;
        queue = new int[capacity];
    }

    // 判断环形队列是否为空
    public boolean isEmpty() {
        return front == tail;
    }

    // 判断环形队列是否已满
    public boolean isFull() {
        return (tail + 1) % capacity == front;
    }

    // 存
    public void put(int n) {
        if (isFull()) {
            throw new IllegalArgumentException("queue is full !");
        }
        queue[tail] = n;
        tail = (tail + 1) % capacity;
    }

    // 取
    public int get() {
        if (isEmpty()) {
            throw new IllegalArgumentException("queue is empty !");
        }
        int n = queue[front];
        queue[front] = 0;// 此处的目的是模仿讲引用置为null的操作
        front = (front + 1) % capacity;
        return n;
    }

    // 队首
    public int catHead() {
        if (isEmpty()) {
            throw new IllegalArgumentException("queue is empty !");
        }
        return queue[front];
    }

    @Override
    public String toString() {
        return "CircleArrayQueue2{" +
                "front=" + front +
                ", tail=" + tail +
                ", capacity=" + capacity +
                ", queue=[队首]" + Arrays.toString(queue) +
                "[队尾], 队首元素: " + catHead() + "}";
    }
}

// 测试类
public class CircleArrayQueueTest2 {
    public static void main(String[] args) {
        CircleArrayQueue2 circleArrayQueue2 = new CircleArrayQueue2(8);
        for (int i = 1; i < 8; i++) {
            circleArrayQueue2.put(i);
        }
        System.out.println(circleArrayQueue2);
        circleArrayQueue2.get();
        System.out.println(circleArrayQueue2);
        circleArrayQueue2.get();
        System.out.println(circleArrayQueue2);
        circleArrayQueue2.put(8);
        System.out.println(circleArrayQueue2);
        circleArrayQueue2.put(9);
        System.out.println(circleArrayQueue2);
        circleArrayQueue2.put(10);
        System.out.println(circleArrayQueue2);
    }
}
// 测试结果
CircleArrayQueue2{front=0, tail=7, capacity=8, queue=[队首][1, 2, 3, 4, 5, 6, 7, 0][队尾], 队首元素: 1}
CircleArrayQueue2{front=1, tail=7, capacity=8, queue=[队首][0, 2, 3, 4, 5, 6, 7, 0][队尾], 队首元素: 2}
CircleArrayQueue2{front=2, tail=7, capacity=8, queue=[队首][0, 0, 3, 4, 5, 6, 7, 0][队尾], 队首元素: 3}
CircleArrayQueue2{front=2, tail=0, capacity=8, queue=[队首][0, 0, 3, 4, 5, 6, 7, 8][队尾], 队首元素: 3}
CircleArrayQueue2{front=2, tail=1, capacity=8, queue=[队首][9, 0, 3, 4, 5, 6, 7, 8][队尾], 队首元素: 3}
Exception in thread "main" java.lang.IllegalArgumentException: queue is full !
at com.sgu.data.structure.date_5_23.array.arrayqueue2.CircleArrayQueue2.put(CircleArrayQueue2.java:29)
at com.sgu.data.structure.date_5_23.array.arrayqueue2.CircleArrayQueueTest2.main(CircleArrayQueueTest2.java:18)

Process finished with exit code 1

// 分析

(tail + 1)% capacity :

我上面举的例子当中,测试结果第四个可以看到 tail 指向索引7(也就是最后一个元素)的位置,此时如果我再加一个元素tail应该指向0(环形队列嘛,索引7的下一个元素索引就是0),正好模运算就可以实现 (7 + 1)% 8 = 0,front 加 1之后和capacity取模是一个道理

capacity总是空出一个元素来判断队列是否已满:

仍然看我上面举的例子:当我添加完元素9以后,可以看到队列中索引为1的位置是空着的,当我再向队列中添加元素10时就开始报queue is full的错误了。原因是,如果加完元素10以后,tail的指针位置正好和front的指针位置重合(都在索引值为2的位置),我们说过了当front == tail时判断的是队列为空,所以为了和队列为空的条件区分开,就空出一个元素位置来作为队列已满的判断条件 

 

------------------------------------------------------------------------------------------------------------------------------------------------------------------------

7月6号,复习:

1. 队列特点:先进先出

1)怎样体现的先进先出的特点:front 和 rear 这两个指针,put值时rear加1,get值时front加1

2. 环形队列

1)front 和 rear 的初始值都为0,表示队列为空

2)front == (rear + 1) % QueueSize 表示队列已满

3)环形队列中有效元素的个数:

1> 当 rear 大于 front 时,有效元素个数 = rear - front

2> 当 rear 小于 front 时,有效元素个数 = ( rear + QueueSize ) - front

总结:( rear + QueueSize - front ) % QueueSize    ---> 前面这两个选项可以明白,但是后面这个推理不太明白,不知道怎么得出来的

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值