1. 程式人生 > >堆排序分析實現

堆排序分析實現

演算法思想

若升序,建大堆,每次選擇堆頂元素即最大的數,和最後一位交換,再縮小堆的範圍(避免剛排好的最後一個位置被調回去),對剩下的進行向下調整(此時只有根節點不對,左右子樹都滿足大堆)。反覆進行直到堆的範圍為0.則資料就有序了。

程式碼實現思路

堆排序的實現首先是需要將陣列調整為一個大堆或者小堆,然後就是迴圈交換和調整堆的過程。因為在建堆和調整堆過程都用到了將陣列的某一部分調整為一個堆,所以抽出為一個adjustArray(int[] nums, int start, int end)函式。

時間複雜度

O(nlogn)。
建堆的時間複雜度近似為O(n*log n),每次選一個數後進行調整的複雜度也近似為O(n*log n),時間複雜度忽略係數,結果就近似為O(n*log n)。

空間複雜度

O(1)

穩定性

不穩定。
堆的調整時可能會打亂穩定性。

程式碼實現

package sort;

/**
 * @作者:dhc
 * @建立時間:8:28 2018/8/15
 * @排序方法:堆排序
 * @時間複雜度:O(nlogn)。建堆的時間複雜度近似為O(n*log n),每次選一個數後進行調整的複雜度也近似為O(n*log n),時間複雜度忽略係數,結果就近似為O(n*log n).
 * @空間複雜度:O(1)
 * @穩定性:不穩定
 */
public class HeapSort {
    //堆排序
    public static void heapSort
(int[] nums){ heapArray(nums); int tem; for(int i = nums.length - 1;i > 0;i--){ tem = nums[0]; nums[0] = nums[i]; nums[i] = tem; adjustArray(nums,0,i-1); } } //堆化陣列 public static void heapArray(int[] nums){ for
(int i = nums.length / 2; i >= 0; i--) { adjustArray(nums,i,nums.length); } } //對某個節點進行一次從上到下的調整(建小堆的調整) public static void adjustArray1(int[] nums, int start, int end){ int min; int k; for (int i = start; i < end;) { if(2*i+2<=end){ //這裡是和左右子節點比較並的較小者交換,後面得到的是小堆,如果要大堆,則需要和比較後的較大者交換 min = nums[2*i+1] > nums[2*i+2] ? nums[2*i+2] : nums[2*i+1]; k = nums[2*i+1] > nums[2*i+2] ? 2*i+2 : 2*i+1; if(nums[i] > min){ nums[k] = nums[i]; nums[i] = min; i = k; }else{ break; } }else{ break; } } } //建大堆的調整 public static void adjustArray(int[] nums, int start, int end){ int max; int k; for (int i = start; i < end;) { if(2*i+2<=end){ max = nums[2*i+1] < nums[2*i+2] ? nums[2*i+2] : nums[2*i+1]; k = nums[2*i+1] < nums[2*i+2] ? 2*i+2 : 2*i+1; if(nums[i] < max){ nums[k] = nums[i]; nums[i] = max; i = k; }else{ break; } }else{ break; } } } public static void main(String[] args) { int[] nums = new int[]{1,0,5,3,7,9,2,4,5}; heapSort(nums); for (int i = 0; i < nums.length; i++) { System.out.print(nums[i]+" "); } } }

參考連結