優先隊列原理與實現
阿新 • • 發佈:2018-04-19
() 通過 size 大堆 默認 深入理解 -s 示例 完整
轉自:https://www.cnblogs.com/luoxn28/p/5616101.html
優先隊列是一種用來維護一組元素構成的結合S的數據結構,其中每個元素都有一個關鍵字key,元素之間的比較都是通過key來比較的。優先隊列包括最大優先隊列和最小優先隊列,優先隊列的應用比較廣泛,比如作業系統中的調度程序,當一個作業完成後,需要在所有等待調度的作業中選擇一個優先級最高的作業來執行,並且也可以添加一個新的作業到作業的優先隊列中。Java中,PriorityQueue的底層數據結構就是堆(默認是小堆),關於Java的PriorityQueue更多知識請點擊:深入理解Java PriorityQueue。
優先隊列的實現中,我們可以選擇堆數據結構,最大優先隊列可以選用大堆,最小優先隊列可以選用小堆來實現。下面以最大優先隊列來講解其原理。最大優先隊列一般包括將一個元素插入到集合S中、返回集合S中具有最大key的元素、返回並刪除集合S中具有最大key的元素等。
插入操作
插入操作是將一個元素插入到集合S中,首先把該元素放入所有元素的下一位置,然後執行“上浮”操作,如下圖示例(註意,下圖示例是小堆,不過原理是一樣的,圖片來自深入理解Java PriorityQueue)
移除操作
優先隊列中,在隊列非空情況下移除集合中第一個元素,也就是下標為0的元素,然後將集合中最後一個元素移到下標為0位置,在將下標為0的新元素執行“下沈”操作。如下圖示例(註意,下圖示例是小堆,不過原理是一樣的,圖片來自深入理解Java PriorityQueue)
完整代碼實現
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; } }
優先隊列原理與實現