【資料結構與演算法】最小堆 minheap
阿新 • • 發佈:2018-12-31
最小堆與最大堆實現思路一樣,只不過順序不同,這裡只記錄最小堆。
最小堆的定義是,一棵完全二叉樹,每一個節點都大於等於其父節點。完全二叉樹是葉子都在最後一層,且儘量靠左。
實現方面可以使用連結串列或者陣列,這裡使用陣列。
如果使用陣列,那麼下標從0開始,父節點是i,則左子樹是2*i+1,右子樹是2*i+2。如果子節點是i,則父節點是(i-1)/2。
minheap的操作主要有兩個,一個是add,思路是,新建一個節點在最後,然後不斷地和父節點比較,如果小於父節點,就交換,直到大於等於或者root。
第二個操作是輸出root,那麼需要把最後一個節點移至root位置,然後重新梳理minheap,因為此時可能不再shiminheap了,梳理過程用函式minheapify實現。該函式的實現思路是傳入一個i引數,表明以i為根的子樹需要梳理,然後讓i和比i小的子節點中的較小值交換,再遞迴地梳理被交換的節點。
下面是程式碼,這裡沒有考慮一些邊界,比如陣列的大小,或者輸出空的heap的情況。
public class MinHeap { private int size = 0; private int[] heap = new int[100]; public void add(int data){ heap[size++] = data; int i = size - 1; while(i > 0 && heap[i] < heap[(i - 1) / 2]){ swap(i, (i - 1) / 2); i = (i - 1) / 2; } } public int top(){ size --; int r = heap[0]; swap(size, 0); minheapify(0); return r; } public void minheapify(int i){ int l = 2 * i + 1; int r = 2 * i + 2; int small = i; if(l < size && heap[i] > heap[l]){ small = l; } if(r < size && heap[r] < heap[small]){ small = r; } if(i != small){ swap(i, small); minheapify(small); } } private void swap(int i, int j){ int temp = heap[i]; heap[i] = heap[j]; heap[j]= temp; } public int size(){ return size; } }