大根堆化:从非叶子节点开始从右到左从下到上下沉。因为每个节点的子节点都是大根堆化的,所以最终单个节点下沉后的树也必然是大根堆,故先保证子树是大根堆
//学习堆排序:
//首先大根堆化,然后遍历替换头部和末尾元素,此时末位确定
public int[] sortArray(int[] nums) {
heapify(nums);
for (int i = nums.length - 1; i >= 0; i--) {
swap(nums, 0, i);
//不要涉及已经排序的位置
swiftDown(0, nums, i);
}
return nums;
}
public void heapify(int[] nums){
//每个非叶子节点开始下沉,因为叶子节点不需要下沉
for (int i = (nums.length / 2 - 1); i>=0; i--) {
swiftDown(i, nums, nums.length);
}
}
public void swiftDown(int pos, int[] nums, int length){
//如果不符合大根堆,就继续下沉
while ((pos * 2 + 1) <= length - 1){
int left = pos * 2 + 1;
int right = left + 1;
int tmp;
if (right <= length - 1 && nums[right] > nums[left]){
tmp = right;
}else{
tmp = left;
}
if (nums[tmp] > nums[pos]){
swap(nums, tmp, pos);
pos = tmp;
}else {
return;
}
}
}
public void swap(int[] nums, int i ,int j){
int tmp = nums[i];
nums[i] = nums[j];
nums[j] = tmp;
}