前言
學習Java阻塞隊列的時候,瞭解到了ConcurrentLinkedQueue隊列使用了堆結構,就整理一下堆結構的邏輯
原理
堆是一顆滿二叉樹(除了最後一層的節點可以不滿,其他層都必須是滿的),元素存儲在數組中,頭結點必定是最大或者最小值(大小頂堆)。
結構圖
入隊邏輯:保證小頂堆不變
出隊邏輯:
代碼模擬實現
public class BinaryHeap { /** * 默認數組長度 */ private static final int DEFAULT_CAPACITY = 100; /** * 數組長度 */ private int currentSize; // Number of elements in heap private Comparable[] array; // The heap array public BinaryHeap() { this(DEFAULT_CAPACITY); } public BinaryHeap(Comparable[] items) { currentSize = items.length; array = new Comparable[(currentSize + 2) * 11 / 10]; int i = 1; for (Comparable item : items) { array[i++] = item; } buildHeap(); } public BinaryHeap(int capacity) { currentSize = 0; array = new Comparable[capacity + 1]; } public void insert(Comparable x) { // Percolate up int hole = ++currentSize; for (; hole > 1 && x.compareTo(array[hole / 2]) < 0; hole /= 2) array[hole] = array[hole / 2]; array[hole] = x; } public Comparable findMin() { if (isEmpty()) return null; return array[1]; } public Comparable deleteMin() { if (isEmpty()) return null; Comparable minItem = findMin(); array[1] = array[currentSize--]; percolateDown(1); return minItem; } private void buildHeap() { for (int i = currentSize / 2; i > 0; i--) percolateDown(i); } public boolean isEmpty() { return currentSize == 0; } public boolean isFull() { return currentSize == array.length - 1; } public void makeEmpty() { currentSize = 0; } private void percolateDown(int hole) { int child; Comparable tmp = array[hole];//保存變量 for (; hole * 2 <= currentSize; hole = child) { child = hole * 2;//獲取左子樹結點 //如果左子樹結點不是堆的長度並且左子樹大於右子樹的值 if (child != currentSize && array[child + 1].compareTo(array[child]) < 0) child++;//child指向右子樹 if (array[child].compareTo(tmp) < 0)//如果孩子比tmp小 array[hole] = array[child];//交換值 else break; } array[hole] = tmp; } public static void main(String[] args) { int numItems = 10; BinaryHeap h = new BinaryHeap(numItems); int i = 37; try { for (i = 37; i != 0; i = (i + 37) % numItems){ h.insert(i); } System.out.println("插入數據之後展示====================="); for (int j=1;j<=h.currentSize;j++){ System.out.print(h.array[j]+" "); } System.out.println(); h.deleteMin(); System.out.println("刪除數據之後展示====================="); for (int j=1;j<=h.currentSize;j++){ System.out.print(h.array[j]+" "); } System.out.println(); } catch (Exception e) { System.out.println("Overflow (expected)! " + i); } } }
運行結果:
總結
堆是專門爲優先級排序準備的一種數據結構,最小/最大的值永遠在頂部,從底部獲取就可以保證優先級。