复杂度

时间复杂度(平均) 时间复杂度(最好) 时间复杂度(最坏) 空间复杂度 稳定性 复杂性
O(nlog2n) O(nlog2n) O(nlog2n) O(1) 不稳定 较复杂

思路

  • 堆:
    堆是具有以下性质的完全二叉树
    大顶堆:每个结点的值都大于或等于其左右孩子结点的值.
    nums[i] >= nums[2i+1] && nums[i] >= nums[2i+2]
    小顶堆:每个结点的值都小于或等于其左右孩子结点的值.
    nums[i] <= nums[2i+1] && nums[i] <= nums[2i+2]

  • 步骤:

  1. 建堆(若期望得到升序数组,则应构建大顶堆,反之构建小顶堆)
  2. 调整,对每次建堆后的数组,将根节点元素与堆末元素swap
    (此时相当于已经固定了堆末元素为最大元素)
  3. 每次对2后的堆重新调整,固定当前最大元素,直至元素全部固定

代码

public void heapSort(int[] nums){
    //初始构建大顶堆(只需遍历非叶子节点即可)
    for(int i = nums.length / 2 - 1; i >= 0; i--){
        adjust(nums, i, nums.length);
    }

    //对每次构建的大顶堆进行swap固定当前最大元素
    for(int i = nums.length - 1; i > 0; i--){
        swap(nums, 0, i);
        adjust(nums, 0, i);
    }

}

//调整顶堆,将较小元素压下去,较大元素冒上来
private void adjust(int[] nums, int i, int r){
    for(int k = i * 2 + 1; k < r; k = k * 2 + 1){
        if(k + 1 < r && nums[k + 1] > nums[k]) k++;
        if(nums[i] < nums[k]){
            swap(nums, i, k);
            i = k;
        }else break;
    }
}

private void swap(int[] nums, int i, int j){
    int temp = nums[i];
    nums[i] = nums[j];
    nums[j] = temp;
}