Java数组实现循环队列

简介: Java数组实现循环队列

Java数组实现循环队列

上一节(Java实现队列——顺序队列、链式队列)我们使用数组实现了顺序队列,但是在tail == n时会有数据搬移操作,这样入队操作性能就会受到影响。这里我们使用循环队列的解决思路。

循环队列

顾名思义,首尾相连就形成了循环队列,如下图所示:

实现循环队列最关键的部分是确定队列何时为空何时满。在用数组实现的非循环队列中,队满的判断条件是tail == n,队空的判断条件是head == tail。在循环队列中,队列为空的判断条件仍然是head == tail,但队列满的判断条件有所更改,是( tail + 1 ) % capacity == head
另外一点需要注意的是,当队列满时,tail指针指向的位置实际上是没有存储数据的,所以会浪费一个数组的存储空间。

代码实现如下:

public class CircularQueue implements QueueInterface {
    private String[] values;// 容器
    private int capacity = 0;// 容量
    // head 表示队头下标,tail表示对尾下标
    private int head = 0;
    private int tail = 0;

    public CircularQueue(int capacity) {
        values = new String[capacity];
        this.capacity = capacity;
    }

    @Override
    public Boolean enqueue(String value) {
        // 队列满了
        if ((tail + 1) % capacity == head) {
            return false;
        }
        values[tail] = value;
        tail = (tail + 1) % capacity;
        return true;
    }

    @Override
    public String dequeue() {
        // 如果head == tail 表示队列为空
        if (head == tail) {
            return null;
        }
        String ret = values[head];
        head = (head + 1) % capacity;
        return ret;
    }

    @Override
    public String toString() {
        return "CircularQueue{" +
                "values=" + Arrays.toString(values) +
                ", capacity=" + capacity +
                ", head=" + head +
                ", tail=" + tail +
                '}';
    }
}

测试代码:

    CircularQueue cq = new CircularQueue(10);
    System.out.println(cq);
    System.out.println();

    //正常添加的数据
    System.out.println("正常添加的数据:");
    for (int i = 0; i < 9; i++) {
        System.out.println("cq.enqueue():" + cq.enqueue("" + i + i + i));
        System.out.println(cq);
    }
    System.out.println();

    // 队列满了以后添加数据
    System.out.println("队列满了以后添加数据:");
    System.out.println("cq.enqueue():" + cq.enqueue("aaa"));
    System.out.println(cq);
    System.out.println();

    // 清空队列
    System.out.println("清空队列:");
    for (int i = 0; i < 9; i++) {
        System.out.println("cq.dequeue():" + cq.dequeue());
        System.out.println(cq);
    }
    System.out.println();

    // 队列清空以后,继续清空
    System.out.println("队列清空以后,继续清空:");
    System.out.println("cq.dequeue():" + cq.dequeue());
    System.out.println(cq);

输出结果:符合期望

CircularQueue{values=[null, null, null, null, null, null, null, null, null, null], capacity=10, head=0, tail=0}

正常添加的数据:
cq.enqueue():true
CircularQueue{values=[000, null, null, null, null, null, null, null, null, null], capacity=10, head=0, tail=1}
cq.enqueue():true
CircularQueue{values=[000, 111, null, null, null, null, null, null, null, null], capacity=10, head=0, tail=2}
cq.enqueue():true
CircularQueue{values=[000, 111, 222, null, null, null, null, null, null, null], capacity=10, head=0, tail=3}
cq.enqueue():true
CircularQueue{values=[000, 111, 222, 333, null, null, null, null, null, null], capacity=10, head=0, tail=4}
cq.enqueue():true
CircularQueue{values=[000, 111, 222, 333, 444, null, null, null, null, null], capacity=10, head=0, tail=5}
cq.enqueue():true
CircularQueue{values=[000, 111, 222, 333, 444, 555, null, null, null, null], capacity=10, head=0, tail=6}
cq.enqueue():true
CircularQueue{values=[000, 111, 222, 333, 444, 555, 666, null, null, null], capacity=10, head=0, tail=7}
cq.enqueue():true
CircularQueue{values=[000, 111, 222, 333, 444, 555, 666, 777, null, null], capacity=10, head=0, tail=8}
cq.enqueue():true
CircularQueue{values=[000, 111, 222, 333, 444, 555, 666, 777, 888, null], capacity=10, head=0, tail=9}

队列满了以后添加数据:
cq.enqueue():false
CircularQueue{values=[000, 111, 222, 333, 444, 555, 666, 777, 888, null], capacity=10, head=0, tail=9}

清空队列:
cq.dequeue():000
CircularQueue{values=[000, 111, 222, 333, 444, 555, 666, 777, 888, null], capacity=10, head=1, tail=9}
cq.dequeue():111
CircularQueue{values=[000, 111, 222, 333, 444, 555, 666, 777, 888, null], capacity=10, head=2, tail=9}
cq.dequeue():222
CircularQueue{values=[000, 111, 222, 333, 444, 555, 666, 777, 888, null], capacity=10, head=3, tail=9}
cq.dequeue():333
CircularQueue{values=[000, 111, 222, 333, 444, 555, 666, 777, 888, null], capacity=10, head=4, tail=9}
cq.dequeue():444
CircularQueue{values=[000, 111, 222, 333, 444, 555, 666, 777, 888, null], capacity=10, head=5, tail=9}
cq.dequeue():555
CircularQueue{values=[000, 111, 222, 333, 444, 555, 666, 777, 888, null], capacity=10, head=6, tail=9}
cq.dequeue():666
CircularQueue{values=[000, 111, 222, 333, 444, 555, 666, 777, 888, null], capacity=10, head=7, tail=9}
cq.dequeue():777
CircularQueue{values=[000, 111, 222, 333, 444, 555, 666, 777, 888, null], capacity=10, head=8, tail=9}
cq.dequeue():888
CircularQueue{values=[000, 111, 222, 333, 444, 555, 666, 777, 888, null], capacity=10, head=9, tail=9}

队列清空以后,继续清空:
cq.dequeue():null
CircularQueue{values=[000, 111, 222, 333, 444, 555, 666, 777, 888, null], capacity=10, head=9, tail=9}

完整代码请查看

项目中搜索SingleLinkedList即可。

github传送门 https://github.com/tinyvampirepudge/DataStructureDemo

gitee传送门 https://gitee.com/tinytongtong/DataStructureDemo

参考:
队列:队列在线程池等有限资源池中的应用

相关文章
|
5天前
|
存储 Java 程序员
Java 数组
4月更文挑战第16天
|
27天前
|
Java
java 8 数组转字符串并以逗号分隔
java 8 数组转字符串并以逗号分隔
11 0
|
1月前
|
Java
【Java】数组中的拷贝方法与初步理解深浅拷贝
【Java】数组中的拷贝方法与初步理解深浅拷贝
13 0
|
1月前
|
存储 Java C语言
【Java】以数组为例简单理解引用类型变量
【Java】以数组为例简单理解引用类型变量
15 1
|
1月前
|
存储 Java 索引
Java数组
Java数组
7 0
|
1月前
|
Java
java中判断数组中元素出现的次数
java中判断数组中元素出现的次数
10 0
|
1月前
|
Java
java向数组中插入元素
java向数组中插入元素
9 0
|
1月前
|
存储 Java 索引
JAVA一维数组
JAVA一维数组
19 3
|
1月前
|
Java 索引
JAVA数组的常用方法
JAVA数组的常用方法
17 1
|
1月前
|
Java C语言
Java中的数组,你知道多少细节?
Java中的数组,你知道多少细节?
26 1