本文根據《大話數據結構》一書,實現了Java版的堆排序。html
更多:數據結構與算法合集java
堆排序種的堆指的是數據結構中的堆,而不是內存模型中的堆。算法
堆:能夠當作一棵徹底二叉樹,每一個結點的值都大於等於(小於等於)其左右孩子結點的值,稱爲大頂堆(小頂堆)。數據結構
大頂堆(左)與小頂堆(右)ide
堆排序的基本思想:將帶排序的序列構形成大頂堆,最大值爲根結點。將根結點與最後一個元素交換,對除最大值外的剩下n-1個元素從新構形成大頂堆,能夠得到次大的元素。反覆執行,就能夠獲得一個有序序列了。函數
構造大頂堆的方法:post
1.首先複習徹底二叉樹的性質,層序遍歷,當第一個元素索引從0開始時,索引爲i的左孩子的索引是 (2*i+1),右孩子的索引是 (2*i+2)。測試
2.設計一個函數heapAdjust(),對於一個序列(除了第一個根結點外,其他結點均知足最大堆的定義),經過這個函數能夠將序列調整爲正確的大頂堆。url
3.正式構造:將帶排序的序列當作一棵徹底二叉樹的層序遍歷,咱們從下往上,從右往左,依次將每一個非葉子結點看成根結點,使用heapAdjust()調整成大頂堆。spa
具體細節的實現參閱代碼,比較清楚,再也不贅述。
(含測試代碼)
/** * * @Description 堆排序 * * @author yongh * */ public class HeapSort { public void heapSort(int[] arr) { if(arr==null || arr.length<=0) return; int len=arr.length; for(int i=len/2-1;i>=0;i--) { //從最後一個父結點開始構建最大堆 heapAdjust(arr,i,len-1); } for(int i=len-1;i>=0;i--) { int temp=arr[0]; arr[0]=arr[i]; arr[i]=temp; heapAdjust(arr, 0, i-1); } } /* * 功能:調整堆爲最大堆 * [i……j]中,除了i以外,部分子樹都知足最大堆定義 */ private void heapAdjust(int[] arr, int start, int end) { int temp=arr[start]; int child=2*start+1; while(child<=end) { if(child+1<=end && arr[child+1]>arr[child]) //記得child+1<=end的判斷 child++; //較大的孩子 if(arr[child]<=temp) break; arr[start]=arr[child]; start=child; child=child*2+1; } arr[start]=temp; } // =========測試代碼======= public void test1() { int[] a = null; heapSort(a); System.out.println(Arrays.toString(a)); } public void test2() { int[] a = {}; heapSort(a); System.out.println(Arrays.toString(a)); } public void test3() { int[] a = { 1 }; heapSort(a); System.out.println(Arrays.toString(a)); } public void test4() { int[] a = { 3, 3, 3, 3, 3 }; heapSort(a); System.out.println(Arrays.toString(a)); } public void test5() { int[] a = { -3, 6, 3, 1, 3, 7, 5, 6, 2 }; heapSort(a); System.out.println(Arrays.toString(a)); } public static void main(String[] args) { HeapSort demo = new HeapSort(); demo.test1(); demo.test2(); demo.test3(); demo.test4(); demo.test5(); } }
null [] [1] [3, 3, 3, 3, 3] [-3, 1, 2, 3, 3, 5, 6, 6, 7]
構建堆的時間複雜度爲O(n);每次調整堆的時間爲O(logn),共要調整n-1次,因此重建堆的時間複雜度爲O(nlogn)。
所以整體來講,堆排序的複雜度爲O(nlogn)。不過因爲記錄的比較和交換是跳躍式進行的,所以堆排序是不穩定的排序方法。
更多:數據結構與算法合集