堆排序是利用堆这种数据结构而设计的一种排序算法,堆排序是一种选择排序,它的最坏,最好,平均时间复杂度均为O(nlogn),它也是不稳定排序。
堆是具有以下性质的完全二叉树:每个结点的值都大于或等于其左右孩子结点的值,称为大顶堆;或者每个结点的值都小于或等于其左右孩子结点的值。
堆排序的基本思路:
a.将无需序列构建成一个堆,根据升序降序需求选择大顶堆或小顶堆;
b.将堆顶元素与末尾元素交换,将最大元素"沉"到数组末端;
c.重新调整结构,使其满足堆定义,然后继续交换堆顶元素与当前末尾元素,反复执行调整+交换步骤,直到整个序列有序。
升序排序,则构建大顶堆。
package nuc.edu.lisheng;
import java.util.Arrays;
public class HeapSort {
public static void main(String[] args) {
int[] a = { 58, 4, 5, 9, 36, 27, 1, 3, 58 };
HeapSortFianl(a);
System.out.println(Arrays.toString(a));
}
//是否排序完成
public static boolean ifend(int[] a) {
// true代表还要继续,即没有排序好
boolean ifend = true;
A: for (int index = a.length - 1; index > 0; index--) {
if (a[index] < a[index - 1]) {
ifend = false;
break A;
}
}
return ifend;
}
//判断a是否为奇数。(从0开始)完全二叉树中奇数索引在左,偶数索引在右。左右对应的交换操作斌不相同
public static boolean odd(int a) {
if (a % 2 == 0) {
return false;
} else {
return true;
}
}
//左右节点与父节点比较大小,交换
public static void sortHeap(int[] a, int i, int changeIndex) {
//如果是偶数
if (!odd(i)) {
int left = i - 1;
int father = (i - 1) / 2;
if (a[i] > a[father]) {
int num = a[i];
a[i] = a[father];
a[father] = num;
}
if (a[left] > a[father]) {
int num = a[left];
a[left] = a[father];
a[father] = num;
}
} else {
//如果是奇数,且在可操作的最后一位,那么没有右节点,直接比较左节点即可
if (i == changeIndex) {
int father = i / 2;
if (a[i] > a[father]) {
int num = a[i];
a[i] = a[father];
a[father] = num;
}
} else {
//左右都有,都比较
int right = i + 1;
int father = i / 2;
if (a[i] > a[father]) {
int num = a[i];
a[i] = a[father];
a[father] = num;
}
if (a[right] > a[father]) {
int num = a[right];
a[right] = a[father];
a[father] = num;
}
}
}
}
public static void getMaxHeap(int[] a, int changeIndex) {
//从可操作的最后一位往后比较,直到1为止。
for (int i = changeIndex; i > 0; i--) {
sortHeap(a, i, changeIndex);
}
}
//可操作的最后一位与守卫交换
public static void changeFirstAndEnd(int[] a, int changeIndex) {
int num = a[changeIndex];
a[changeIndex] = a[0];
a[0] = num;
}
public static void HeapSortFianl(int[] a) {
int changeIndex = a.length - 1;
A: while (true) {
getMaxHeap(a, changeIndex);
changeFirstAndEnd(a, changeIndex);
changeIndex--;
if (ifend(a)) {
break A;
}
}
}
}
结果: