排序算法-堆排序
复杂度
时间复杂度(平均) | 时间复杂度(最好) | 时间复杂度(最坏) | 空间复杂度 | 稳定性 | 复杂性 |
---|---|---|---|---|---|
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] -
步骤:
- 建堆(若期望得到升序数组,则应构建大顶堆,反之构建小顶堆)
- 调整,对每次建堆后的数组,将根节点元素与堆末元素swap
(此时相当于已经固定了堆末元素为最大元素) - 每次对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;
}