一.基礎准備
這個算法研究了兩天,整整兩天啊,中間水了一道線段樹,好在皇天不負有心人,嘿嘿。
1991年計算機先驅獎獲得者、斯坦福大學計算機科學系教授羅伯特·弗洛伊德(Robert W.Floyd)和威廉姆斯(J.Williams)在1964年共同發明了著名的堆排序算法(Heap Sort )。堆排序是高效的排序方法。沒有最壞情況(即與平均情況一樣),空間占用又小,綜合效率比快速排序還好。
數據結構中的堆和操作系統中的堆、堆棧(棧)是沒有關系的,不要有誤解。
說道堆排序就不得不先說堆,樹中任一非葉結點的關鍵字均不大於(或不小於)其左右孩子(若存在)結點的關鍵字,分別對應大頂堆和小頂堆。堆排序利用了大根堆(或小根堆)堆頂記錄的關鍵字最大(或最小)這一特征,使得在當前無序區中選取最大(或最小)關鍵字的記錄變得簡單。
堆排序(HeapSort)是一樹形選擇排序。堆排序的特點是:在排序過程中,將R[l..n]看成是一棵完全二叉樹的順序存儲結構,利用完全二叉樹中雙親結點和孩子結點之間的內在關系(參見二叉樹的順序存儲結構),在當前無序區中選擇關鍵字最大(或最小)的記錄。堆排序的最壞時間復雜度為O(nlogn)。堆序的平均性能較接近於最壞性能。由於建初始堆所需的比較次數較多,所以堆排序不適宜於記錄數較少的文件。堆排序是就地排序,輔助空間為O(1),它是不穩定的排序方法。
注意:①堆中任一子樹亦是堆。②以上討論的堆實際上是二叉堆(Binary
Heap),類似地可定義k叉堆。
題外話:滿二叉樹肯定是完全二叉樹,完全二叉樹不一定是滿二叉樹;在C和匯編里,位移運算比乘除要快得多。位移運算比加減更快,可能只占一個CPU時鍾,乘除要占20多個以上,差了一個數量級。效率而言,那是差不起的。
二.算法理解
三.算法實現
1: //小頂堆2: public class W {3:4: public static void main(String[] args) {5: //第一個元素不用6: int a[] = {65535,49, 38, 65, 97, 76, 13, 27, 49};7: System.out.print("排序前序列為:");8: for(int i:a) {9: System.out.print(i+" ");10: }11: System.out.println();12: mySort(a,a.length-1);13: System.out.print("排序后序列為:");14: for(int i:a) {15: System.out.print(i+" ");16: }17: System.out.println();18: }19:20: private static void mySort(int[] a,int len) {21: //構建小頂堆成功22: for(int i=len/2; i>=1; i--) {23: adjust(a,i,len);24: // System.out.print(a[i]+" "+i+":");25: // for(int j:a) {26: // System.out.print(j+" ");27: // }28: // System.out.println();29: }30: //注意共len-1次循環31: for(int i=1; i<len; i++) {32: /*33: * 注意下邊這兩句第二個參數都是134: * 這個for循環里只需要調整一個節點就是根節點,而adjust初初始設計為35: * 從最后開始,不過此時也行了,因為adjust雖然是從最后開始不過36: * 還需要擴展到根節點,很巧妙37: */38: mySwap(a, 1, len-i+1);39: adjust(a, 1,len-i);40: }41: }42:43: public static void adjust(int[] a, int i, int len) {44: /*45: * 原來犯了一個錯誤,更新上一個節點時沒有更新子節點即沒有采用循環結構46: */47: int temp = a[i];48: int j = i<<1;49: /*50: * 為什么是循環?51: * 因為從最后一個非葉子節點開始的,上面的節點更新后可能使下方52: * 已經調整過的節點不再滿足堆的性質,需要繼續調整53: */54: while (j<=len) {55: if (j<len && a[j]>a[j+1]) {56: j++;57: }58: if (temp<=a[j]) {59: break;60: }61: a[j>>1] = a[j];62: //往下擴展子節點63: j <<= 1;64: }65: a[j>>1] = temp;66: }67:68: private static void mySwap(int[] a, int i, int j) {69: int temp = a[i];70: a[i] = a[j];71: a[j] = temp;72: }73: }74:




