堆排序分析實現

算法思想

若升序,建大堆,每次選擇堆頂元素即最大的數,和最後一位交換,再縮小堆的範圍(避免剛排好的最後一個位置被調回去),對剩下的進行向下調整(此時只有根節點不對,左右子樹都滿足大堆)。反覆進行直到堆的範圍爲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]+" ");
        }
    }
}

參考鏈接

白話經典算法系列之七 堆與堆排序
【數據結構】幾種常見的排序算法
穩定排序和不穩定排序

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章