堆是一种数据结构,是具有特定条件(任何节点大于等于子节点的值(左右子节点大小没有定义))的顺序存储(树从树根开始 从上到下从左到右依次存储到数组里)的完全二叉树。
思想:
1.将待排序序列构建成大小顶堆(大顶堆升序 反之降序)
从最后一个非终端节点(n/2 n是数据总数 得到结果向下取整 获得最后一个非终端节点的下标)层进行调整,然后在一层层往上(从下往上),一直到根
2.此时最大(小)的值位于根节点
3.将其和末尾元素进行交换 此时末尾元素就是最大(小)元素
4.将n-1个元素重新构造堆,反复进行 2 3
堆排序是不稳定的,时间复杂度为nlogn
大顶堆和小顶堆
来个图
代码实现:
package heapSort;
import java.util.Arrays;
public class HeapSort {
public static void main(String[] args) {
int[] arr = {4, 6, 8, 5, 9, -1, 90, 89, 56, -999};
isHeapSort(arr);
System.out.println(Arrays.toString(arr));
}
//堆排序方法
public static void isHeapSort(int[] arr) {
int temp = 0;
//i是顺序存储的最后树根的下标 从右至左 从下至上 i>=0 0是数的树根
for (int i = arr.length / 2 - 1; i >= 0; i--) adjustHeap(arr, i, arr.length);
//调整完了 只是一颗局部树,但是树根和末尾元素没有交换
//交换 i是数组长度 每交换一次 长度-1
for (int i = arr.length - 1; i > 0; i--) {
temp = arr[i];
arr[i] = arr[0];
arr[0] = temp;
//调整一次交换一次 之后继续调用
adjustHeap(arr, 0, i);
}
}
//最后的树根索引 从下至上调整
//将数组调整成大顶堆
//arr 待调整的数组
//i 表示要调整的节点(有子节点)索引
//len 表示对多少个元素进行调整,len是在主逐渐减少
public static void adjustHeap(int[] arr, int i, int len) {
//把要调整的局部树根的值保存下来
int temp = arr[i];
//j=左子节点 循环一次后 左子节点的左子节点 类似递归
for (int j = i * 2 + 1; j < len; j = j * 2 + 1) {
//左<右 并且k+1不能大于总长度
if (j + 1 < len && arr[j] < arr[j + 1]) {
//指向右子节点 j是索引 j++的索引比j大1,因为是顺序存储二叉树 if执行完毕 左右孩子最大节点出现
j++;
}
//左右节点中大的值和当前的树根(父节点)比较
//大于树根
if (arr[j] > temp) {
arr[i] = arr[j];
i = j;
} else {
//小于树根
break;
}
}
//for 循环结束 当前i为树根的树调整完毕
//把temp放到调整后的位置
arr[i] = temp;
}
}