java實現堆排序
阿新 • • 發佈:2019-01-09
最近開始學習排序的相關知識,計劃以後每天都要整理一個排序的演算法。
其中最需要注意的就是:
根據根結點i(i為陣列中的下標)來計算其左右孩子的座標時,left = i * 2 + 1, right = i * 2 + 2, 因為根節點是從陣列0位置開始的。
import java.util.Arrays; /** * 堆排序的介紹: * 堆排序對於記錄數較少的檔案並不提倡,但對n較大的檔案還是很有效的。 * 其最壞情況下的時間複雜度為:O(nlogn), 在最好情況下,時間複雜度為:O(1). * 堆排序是不穩定的排序。 * * * *堆排序的具體過程: * 1 、首先從第一個非葉子節點開始,比較當前節點和其孩子節點,將最大的元素放在當前節點,交換當前節點和最大節點元素。 * 2 、將當前元素前面所有的元素都進行1的過程,這樣就生成了最大堆 * 3 、將堆頂元素和最後一個元素交換,列表長度減1。由此無序區減1,有序區加1 * 4 、剩餘元素重新調整建堆 * 5 、 繼續3和4,直到所有元素都完成排序 * * **/ public class HeapSort{ public static void heapSort(int[] num){ if(num == null) return; int len = num.length; buildHeap(num, len); /**每次將堆頂元素放到陣列最後的位置*/ while(len > 1){ swap(num, len - 1, 0); len --; adjustHeap(num, len, 0); } } /**將一個無序的陣列構建成一個大頂堆*/ private static void buildHeap(int[] num, int len) { /**begin為最後一個根節點在陣列中的下標*/ int begin = len / 2 -1; /**依次遍歷每一個根節點,通過調整,使每一個根節點都比它的孩子結點大*/ for(int i = begin; i >= 0; i--){ adjustHeap(num, len, i); } } /**調整根節點和孩子結點的位置,使其滿足大頂堆*/ private static void adjustHeap(int[] num, int len, int i) { /**獲取下標為i的根節點的左孩子和右孩子在陣列中的下標*/ int leftChild = i * 2 + 1; int rightChild = i * 2 + 2; /**將本次調整的最大值下標暫時記為i*/ int max = i; while(leftChild < len || rightChild < len){ /**如果num[max]的左孩子num[leftChild]比max大,將leftChild暫存在max中*/ if(leftChild < len && num[max] < num[leftChild]){ max = leftChild; } /**如果num[max]的右孩子num[rightChild]比max大,將rightChild暫存在max中*/ if(rightChild < len && num[max] < num[rightChild]){ max = rightChild; } /**如果在前面的運算中,發生過賦值*/ if(i != max){ swap(num, max, i); i = max; leftChild = i * 2 + 1; rightChild = i * 2 + 2; }else{ break; } }//while(leftChild < len || rightChild < len) }//private static void adjustHeap() /**將陣列中num[x]和num[y]位置交換*/ private static void swap(int[] num, int x, int y) { num[x] = num[x] ^ num[y]; num[y] = num[x] ^ num[y]; num[x] = num[x] ^ num[y]; } public static void main(String[] args) { int[] num = {0, 9, 7, 0, 0, 6, -40, 200}; HeapSort.heapSort(num); System.out.println(Arrays.toString(num)); } }