優先隊列是一種用來維護一組元素構成的結合S的數據結構,其中每一個元素都有一個關鍵字key,元素之間的比較都是經過key來比較的。優先隊列包括最大優先隊列和最小優先隊列,優先隊列的應用比較普遍,好比做業系統中的調度程序,當一個做業完成後,須要在全部等待調度的做業中選擇一個優先級最高的做業來執行,而且也能夠添加一個新的做業到做業的優先隊列中。Java中,PriorityQueue的底層數據結構就是堆(默認是小堆),關於Java的PriorityQueue更多知識請點擊:深刻理解Java PriorityQueue。html
優先隊列的實現中,咱們能夠選擇堆數據結構,最大優先隊列能夠選用大堆,最小優先隊列能夠選用小堆來實現。下面以最大優先隊列來說解其原理。最大優先隊列通常包括將一個元素插入到集合S中、返回集合S中具備最大key的元素、返回並刪除集合S中具備最大key的元素等。java
插入操做是將一個元素插入到集合S中,首先把該元素放入全部元素的下一位置,而後執行「上浮」操做,以下圖示例(注意,下圖示例是小堆,不過原理是同樣的,圖片來自深刻理解Java PriorityQueue)數組
)數據結構
優先隊列中,在隊列非空狀況下移除集合中第一個元素,也就是下標爲0的元素,而後將集合中最後一個元素移到下標爲0位置,在將下標爲0的新元素執行「下沉」操做。以下圖示例(注意,下圖示例是小堆,不過原理是同樣的,圖片來自深刻理解Java PriorityQueue)this
package priorityheap; import java.util.Arrays; /** * 優先隊列類(最大優先隊列) */ public class PriorityHeap { // ------------------------------ Instance Variables private int[] arr; private int size; // ------------------------------ Constructors /** * 優先隊列數組默認大小爲64 */ public PriorityHeap() { this(64); } public PriorityHeap(int initSize) { if (initSize <= 0) { initSize = 64; } this.arr = new int[initSize]; this.size = 0; } // ------------------------------ Public methods public int max() { return this.arr[0]; } public int maxAndRemove() { int t = max(); this.arr[0] = this.arr[--size]; sink(0, this.arr[0]); return t; } public void add(int data) { resize(1); this.arr[size++] = data; pop(size - 1, data); } // ------------------------------ Private methods /** * key下沉方法 */ private void sink(int i, int key) { while (2 * i <= this.size - 1) { int child = 2 * i; if (child < this.size - 1 && this.arr[child] < this.arr[child + 1]) { child++; } if (this.arr[i] >= this.arr[child]) { break; } swap(i, child); i = child; } } /** * key上浮方法 */ private void pop(int i, int key) { while (i > 0) { int parent = i / 2; if (this.arr[i] <= this.arr[parent]) { break; } swap(i, parent); i = parent; } } /** * 從新調整數組大小 */ private void resize(int increaseSize) { if ((this.size + increaseSize) > this.arr.length) { int newSize = (this.size + increaseSize) > 2 * this.arr.length ? (this.size + increaseSize) : 2 * this.arr.length; int[] t = this.arr; this.arr = Arrays.copyOf(t, newSize); } } /** * Swaps arr[a] with arr[b]. */ private void swap(int a, int b) { int t = this.arr[a]; this.arr[a] = this.arr[b]; this.arr[b] = t; } }