链式队列
由链表实现的队列;
顺序队列
由数组实现的队列;
数组实现可变长度的队列
思路:
- 使用System.arraycopy()进行扩容、进行数据迁移
- 记录数组有效长度、不需要记录数组的总容量
package com.hshuo; /** * 数组实现可变长度的队列 * @author SHshuo * @data 2022/2/26--11:39 */ public class arrayToVolatileQueue { private int front; private int rear; private int length; private int[] arr; public arrayToVolatileQueue(int capicity){ length = 0; front = 0; rear = 0; arr = new int[capicity]; } private void resize(int capicity){ int[] res = new int[capicity]; // 数据迁移时间复杂度为O(n)通过均摊,整体的add、get的时间复杂度仍为O(1) System.arraycopy(arr, front, res, 0, rear - front + 1); // 重置 rear -= front; front = 0; arr = res; } public void add(int value){ arr[rear++] = value; length++; // 超过数组长度的一半进行扩容 if(length > 0 && length > arr.length / 2){ resize(arr.length * 2); } } public int remove(){ if(length == 0){ throw new RuntimeException("队列空了,不能再拿了"); } int ans = arr[front++]; length--; if(length > 0 && length < arr.length / 4){ resize(arr.length / 2); } return ans; } public void allData(){ if(length == 0){ throw new RuntimeException("队列空了"); } for(int i = front; i < rear; i++){ System.out.println("i: " + i + "arr: " + arr[i]); } } public static void main(String[] args) { arrayToVolatileQueue queue = new arrayToVolatileQueue(6); queue.add(1); queue.add(2); queue.add(3); queue.remove(); queue.add(4); queue.allData(); queue.add(5); queue.add(6); queue.add(6); queue.add(6); } }
循环队列
数组实现容量固定的队列、可以重复利用数组
思路:
- 数组要预留一处空间,如果容量是capicity则实际空间是capicity - 1;
- 队列已满条件:(rear + 1)% capicity == front;
- 队列已空条件:front == rear;
- 指针增加:front = (front + 1)% capicity 或者 rear= (rear+ 1)% capicity ;
- 数组的有效长度:(capicity + rear - front)% capicity;
- 数组的下标:i % capicity;
package com.hshuo; /** * 数组转化为固定大小的队列、重复利用数组空间,每次都要取模 * 数组要预留一处空间,如果容量是capicity则实际空间是capicity - 1 * @author SHshuo * @data 2022/2/26--9:50 */ public class arrayToQueue { // 数组 private int[] arr; private int front; private int rear; private int capicity; // 初始化队列 public arrayToQueue(int capicity){ this.capicity = capicity; front= 0; rear = 0; arr = new int[capicity]; } // 对列已满的条件 private boolean isFull(){ return (rear + 1) % capicity == front; } // 队列已空的条件 private boolean isEmpty(){ return rear == front; } public void add(int value){ if(isFull()){ throw new RuntimeException("队列满了,不能再加了"); } arr[rear] = value; // rear++需要取模 rear = (rear + 1) % capicity; } public int remove(){ if(isEmpty()){ throw new RuntimeException("队列空了,不能再拿了"); } int ans = arr[front]; System.out.println("移除的元素是:" + ans); // front++需要取模 front = (front + 1) % capicity; return ans; } // 有效长度 public int size(){ if(isEmpty()){ return 0; } return (capicity + rear - front) % capicity; } // 返回所有数据 public void allData(){ if(isEmpty()){ throw new RuntimeException("队列空了"); } for(int i = front; i < front + size(); i++){ System.out.println("i: " + i % capicity + "arr: " + arr[i % capicity]); } } public static void main(String[] args) { arrayToQueue queue = new arrayToQueue(6); queue.add(1); queue.add(2); queue.add(3); queue.add(4); queue.add(5); queue.remove(); queue.add(6); queue.allData(); } }
阻塞对列
例如:ArrayBlockingQueue的源码
初始化
public ArrayBlockingQueue(int capacity, boolean fair) { if (capacity <= 0) throw new IllegalArgumentException(); this.items = new Object[capacity]; lock = new ReentrantLock(fair); notEmpty = lock.newCondition(); notFull = lock.newCondition(); }
(使用ReetrantLock 和 contional实现)
public void put(E e) throws InterruptedException { checkNotNull(e); final ReentrantLock lock = this.lock; lock.lockInterruptibly(); try { while (count == items.length) notFull.await(); enqueue(e); } finally { lock.unlock(); } }
public E take() throws InterruptedException { final ReentrantLock lock = this.lock; lock.lockInterruptibly(); try { while (count == 0) notEmpty.await(); return dequeue(); } finally { lock.unlock(); } }