06-java實現佇列
阿新 • • 發佈:2020-08-14
06-java實現佇列
一丶佇列
- 佇列是特殊的線性結構,只能在頭尾兩端操作
- 隊尾入隊,隊頭出隊,
- FIFO
- 佇列可以用動態陣列和雙向連結串列實現
- 優先使用雙向連結串列,主要在頭尾進行操作
二丶佇列的介面設計(和之前的線性結構類似)
public class Queue<E> { // 使用雙向連結串列實現佇列 private List<E> list = new LinkedList<>(); // 元素的數量 public int size(); // 是否為空 public boolean isEmpty(); // 入隊 public void enQueue(E element); // 出隊 public E deQueue(); // 獲取佇列的頭元素 public E front(); }
三丶佇列的實現
public class Queue<E> { private List<E> list = new LinkedList<>(); public int size() { return list.size(); } public boolean isEmpty() { return list.isEmpty(); } public void enQueue(E element) { list.add(element); } public E deQueue() { return list.remove(0); } public E front() { return list.get(0); } }
四丶雙端佇列
- 雙端佇列,頭可以入隊出隊,尾可以入隊出隊
五、雙端佇列的介面設計&實現
public class Deque<E> { private List<E> list = new LinkedList<>(); // 元素的數量 public int size() { return list.size(); } // 是否為空 public boolean isEmpty() { return list.isEmpty(); } // 從隊頭出隊 public E deQueueFront() { return list.remove(0); } // 從隊頭入隊 public void enQueueFront(E element) { list.add(0, element); } // 從隊尾入隊 public void enQueueRear(E element) { list.add(element); } // 從隊尾出隊 public E deQueueRear() { return list.remove(list.size() - 1); } // 獲取佇列的頭元素 public E front() { return list.get(0); } // 獲取佇列的尾元素 public E rear() { return list.get(list.size() - 1); } }
六丶迴圈佇列
- 佇列內部實現也可以用動態陣列實現,並且將各項介面優化到O(1)的時間複雜度, 這個用陣列實現並優化之後的佇列就叫做: 迴圈佇列。
七、迴圈佇列的介面設計
public class CircleQueue<E> {
// 記錄第0個元素的索引
private int front;
// 當前佇列儲存的元素個數
private int size;
// 用來儲存元素的陣列
private E[] elements;
// 當前佇列儲存的元素數量
public int size();
// 當前佇列是否為空
public boolean isEmpty();
// 入隊
public void enQueue(E element);
// 出隊
public E deQueue();
// 檢視索引為0的元素
public E front();
}
八丶迴圈佇列的實現
3.1 構造方法
public class ArrayList<E> {
private E[] elements;
// 設定elements陣列預設的初始化空間
private static final int DEFAULT_CAPACITY = 10;
public CircleQueue() {
elements = (E[]) new Object[DEFAULT_CAPACITY];
}
}
3.2 入隊
- 入隊前需要考慮兩個問題:佇列是否需要擴容和計算入隊實際索引。
3.2.1 動態擴容
動態陣列的擴容方法拿來直接用即可
private void ensureCapacity(int capacity) {
int oldCapacity = elements.length;
if (oldCapacity >= capacity) return;
// 新容量為舊容量的1.5倍
int newCapacity = oldCapacity + (oldCapacity >> 1); //位運算
E[] newElements = (E[]) new Object[newCapacity];
for (int i = 0; i < size; i++) {
newElements[i] = elements[index(i)];
}
elements = newElements;
// 重置front
front = 0;
}
3.2.2 索引計算
- 獲取實際索引公式 (front+index)%elements.length;
private int index(int index) {
return (front +index)%elements.length;
}
入隊程式碼
public void enQueue(E element) {
// 陣列擴容判斷
ensureCapacity(size + 1);
// 索引計算,並賦值
elements[index(size)] = element;
// size加一
size++;
}
3.3 出隊
- 一定要更新front指標,一定不要忘
public E deQueue() {
// 獲取出隊元素
E frontElement = elements[front];
// 將索引位置致空
elements[front] = null;
// 更新font
front = index(1);
// size減一
size--;
// 返回出隊元素
return frontElement;
}