八大排序算法之一——堆排序
Java代码
import java.util.Scanner;
/**
* 堆排序:
* 一开始需自底向上堆化,后面每次与顶上元素交换之后,只需要自顶向下堆化即可。
*
* @author 14715
*
* 从大到小排序
*/
public class HeapSort {
public static void heapSort(int[] arr) {
int n = arr.length;
// 从最后一个父节点开始遍历
for (int parent = n / 2; parent >=1; parent--) {
// 传入父节点和需要调整的节点总个数(也就是让程序每次都把该父节点的所有子孙节点都遍历完)
// 传入n,是为了防止遍历孩子节点的时候超出范围
heapAdjust(arr, parent, n);
}
// 开始真正的排序,即将每次排好的堆的根节点跟后面的元素进行交换(除了已经排好序的位置)
for (int i = n; i > 1; i--) {
swap(arr, 0, i - 1);
// 继续调整堆
heapAdjust(arr, 1, i - 1);
}
}
/**
* 交换两个数的值
* @param arr
* @param a
* @param b
*/
public static void swap(int[] arr, int a, int b) {
int temp = arr[a];
arr[a] = arr[b];
arr[b] = temp;
}
/**
* 堆调整
* @param arr
* @param parentPos 父节点位置
* @param needN 需要调整的节点总个数
*/
public static void heapAdjust(int[] arr, int parentPos, int needN) {
// 将当前的父节点的值先用临时变量保存起来
int temp = arr[parentPos - 1];
// 判断该父节点下的所有左孩子
for (int i = parentPos * 2; i <= needN; i*=2) {
// 直接判断是否有右孩子,因为如果是父节点的话,就必定有一个左孩子
if (i + 1 <= needN && arr[i] < arr[i - 1]) {
i++;
}
// 孩子节点跟父节点比较
if (arr[i - 1] >= temp) {
break;
}
// 程序运行到这,表明孩子节点中一定有一个孩子是比父节点的值小的(不过不是的是左还是右)
arr[parentPos - 1] = arr[i - 1];
// 将较小的孩子作为父节点
parentPos = i;
}
// 将一开始的父节点放到应该放的地方
arr[parentPos - 1] = temp;
}
public static void main(String[] args) {
Scanner input = new Scanner(System.in);
int n = input.nextInt();
int[] arr = new int[n];
for (int i = 0; i < n; i++) {
arr[i] = input.nextInt();
}
heapSort(arr);
for (int i = 0; i < arr.length; i++) {
System.out.print(arr[i] + "\t");
}
}
}