/**
* Copyright (C), 2018-2019, LMaWC
* FileName: application
* Author: neo
* Date: 2019/5/6 10:29
* Description:
* History:
* <author> <time> <version> <desc>
* 作者姓名 修改时间 版本号 描述
*/
package com.threadTest;
/**
* 〈一句话功能简述〉<br>
* 〈堆排序实现:使用递归,易于理解〉
*
* @author neo
* @create 2019/5/6
* @since 1.0.0
*/
public class application {
public static void main(String[] args) {
int[] nums = {4, 1, 3, 2, 16, 9, 10, 14, 8, 7};
// 构建堆
heapBuild(nums);
// 堆排序
heapSort(nums);
for (int i = 0; i < nums.length; i++) {
System.out.println(nums[i]);
}
}
// 堆排序
// 思想:把最大值放到nums end 处,然后维护1--end-1 的堆
public static void heapSort(int[] nums) {
int numsLen = nums.length;
for (int i = nums.length - 1; i >=0; i--) {
// 把最大值放在末尾
swap(nums, 0, i);
numsLen--;
// 维护堆(0,i-1)的堆
heapJustify(nums, 0, numsLen); // 这里idx 可以为0 是因为根节点的两个子树都是最大堆
}
}
// 维护堆(递归实现)
// idx为父节点
// 思想:三个元素可以构成一个完整的最大堆,将三个最大值放到根节点,然后分别以左右子节点为根节点,维护堆,直至数组的end
public static void heapJustify(int[] nums, int idx, int numsLen) {
// 子节点为
int left_idx = 2 * idx + 1;
int right_idx = 2 * idx + 2;
// 进行比较,找到最大值
if (right_idx < numsLen) { // 先保证不能越界
// 先左右子节点判断(这样可以减少交换次数)
if (nums[left_idx] > nums[right_idx] && nums[idx] < nums[left_idx]) {
// 交换位置
swap(nums, idx, left_idx);
// 以该节点为根节点继续递归
heapJustify(nums, left_idx, numsLen);
} else if (nums[left_idx] <= nums[right_idx] && nums[idx] < nums[right_idx]) {
// 交换位置
swap(nums, idx, right_idx);
//以该节点为根节点继续递归
heapJustify(nums, right_idx, numsLen);
}
}
// 当只有左子节点时
else if (left_idx < numsLen) {
if (nums[idx] < nums[left_idx]) {
swap(nums, idx, left_idx);
}
}
}
// 构建堆(调用维护堆)
// 思想:获取距离根节点最远的父节点(nums.length/2-1),逐渐向根节点遍历至根节点
public static void heapBuild(int[] nums) {
// 数组从0开始,就不要-1
for (int i = nums.length / 2 - 1; i >= 0; i--) {
heapJustify(nums, i, nums.length);
}
}
public static void swap(int[] nums, int a, int b) {
int temp = nums[a];
nums[a] = nums[b];
nums[b] = temp;
}
}