用数组实现自动扩容的无界队列

用数组实现自动扩容的无界队列


  1/**
  2 * 使用数组实现无界顺序队列(自动扩容)
  3 *
  4 * @author wangy
  5 * @version 1.0
  6 * @date 2021/6/28 / 17:02
  7 */
  8public class ArrayQueueUnbounded {
  9    private int[] data;
 10
 11    // size of data array
 12    private int cap;
 13    // index of head element
 14    private int head;
 15    /*
 16       关于tail指针,一般是将tail指向最新的可以插入元素的index,
 17       即tail是一个空槽(slot):
 18       ===================================================
 19        data[0]                                   data[7]
 20        |    |    |  5  |  6  |  9  |  16  |      |     |
 21                   head                      tail
 22       ===================================================
 23        初始化时,head = tail = 0,此后每插入一个元素,tail后移一位。
 24
 25        当head = tail时,认为队列已空,因为tail是一个空槽:
 26        ===================================================
 27        data[0]                                   data[7]
 28        |    |    |     |     |     |     |      |     |
 29                                            tail
 30                                            head
 31        ===================================================
 32
 33        当tail = cap时,即认为队列"已满":
 34        ========================================================
 35        data[0]                                   data[7]
 36        |    |    |  5  |  6  |  9  |  16  |  87  |  56  |
 37                   head                                    tail
 38        ========================================================
 39
 40        有一个特殊的情况,即 head = tail = cap-1 时,此时队列是空的,也是满的,
 41        不过其不影响队列后续的入队:
 42        ===================================================
 43        data[0]                                   data[7]
 44        |    |    |     |     |     |     |      |     |
 45                                                   tail
 46                                                   head
 47        ===================================================
 48     */
 49    // index of tail element + 1
 50    private int tail;
 51
 52    public ArrayQueueUnbounded() {
 53        // initialization capacity: 4
 54        this.data = new int[4];
 55        this.cap = 4;
 56        this.head = this.tail = 0;
 57    }
 58
 59    boolean isFull() {
 60        // 当tail指向最后一个空槽时,即认为队列已满
 61        return tail == cap ;
 62    }
 63
 64    boolean isEmpty() {
 65        // 无论指针在何处,只要2个指针"相遇",即认为队列为空
 66        return head == tail;
 67    }
 68
 69    // 入队 平均时间复杂度O(1)
 70    int enQueue(int e) {
 71        // 若队列满了,那么增加容量,并且将队列中的元素进行重排
 72        // |x|x|1|2| => |1|2|-|-|-|-|
 73        if (isFull()) {
 74            cap += cap >> 1;
 75            int[] newData = new int[cap];
 76            for (int i = head; i < tail; i++) {
 77                newData[i - head] = data[i];
 78            }
 79            data = newData;
 80            tail -= head;
 81            head = 0;
 82        }
 83        data[tail++] = e;
 84        return e;
 85    }
 86
 87    // 出队
 88    int deQueue() {
 89        if (isEmpty()) throw new RuntimeException("队列为空!");
 90        return data[head++];
 91    }
 92
 93    // 打印数组/队列
 94    void printAll() {
 95        System.out.println("数组:" + Arrays.toString(data));
 96        System.out.print("队列:[");
 97        if (!isEmpty()) {
 98            for (int i = head; i < tail; i++) {
 99                if (i == tail - 1)
100                    System.out.print(data[i]);
101                else
102                    System.out.print(data[i] + ", ");
103            }
104        }
105        System.out.println("]");
106    }
107
108    public static void main(String[] args) {
109        ArrayQueueUnbounded aqu = new ArrayQueueUnbounded();
110        aqu.enQueue(1);
111        aqu.deQueue();
112        aqu.enQueue(2);
113        aqu.enQueue(3);
114        aqu.enQueue(4);
115        aqu.deQueue();
116        aqu.deQueue();
117        aqu.deQueue();
118//        aqu.deQueue();
119        aqu.enQueue(5);
120        aqu.printAll();
121    }
122}