思路说明
堆排序其实是选择排序的一种,构建大顶堆后,将选择元素放在堆顶再放在数组末尾
堆排序基于顺序化二叉树进行调整
大顶堆:
非叶子节点都比其子节点要大
小顶堆:
非叶子节点都比其子节点要小
当前节点为i ,左子节点:2i+1,右子节点:2i+2。
将树从上自下,从左至右,标记下标,第一个非叶子节点下标为length/2-1;
图解思路
局部构建
整体构建(== 注意这的指向6的指针,下一步是指向8去判断调整为大顶堆,这样才能满足,从上至下,从左至右调整为大顶堆的过程==)
选择插入
代码从局部到整体
注意:每次构建大顶堆是局部构建的,并不是一部构建出的
1.局部构建方法
public static void bigtop(int[]arr,int i,int length) {
//该方法是对于局部而言的
int temp=arr[i];//先保存,再插入防止覆盖
for (int k = 2*i+1; k <length; k=2*k+1) {//注意这里的长度为局部长度不是整个数组的长度
//往下找,直到没有节点
if (arr[k]<arr[k+1]&&k+1<length) {//左节点小于右节点,用右节点比较
k++;
}
if (temp<arr[k]) {//当前节点小于子节点,交换
arr[i]=arr[k];
i=k;//将当前节点指向下一层,继续循环比较
}else {
break;//当前节点的子节点都比当前节点小
}
}
arr[i]=temp;
}
- 通过每次局部构建达到整体构建的方法
for (int i =arr.length/2-1; i >=0; i--) {
//性质,第一个非叶子节点下标为 arr.length/2-1,横向记录下标为例子
//从第一个非叶子节点从下至上(i--),从左至右排序
bigtop(arr, i, arr.length);
}//第一次排成大顶堆
System.out.println(Arrays.toString(arr));
3.堆排序实现
package competion2020;
import java.util.Arrays;
public class 堆排序 {
public static void main(String[] args) {
// TODO 自动生成的方法存根
int arr[]= {4,6,8,5,9};
//待排序序列构造成一个大顶堆
heapSort(arr);
for (int i = 0; i < arr.length; i++) {
System.out.print(arr[i]);
}
}
public static void heapSort(int[] arr) {
for (int i =arr.length/2-1; i >=0; i--) {
//性质,第一个非叶子节点下标为 arr.length/2-1,横向记录下标为例子
//从第一个非叶子节点从下至上(i--),从左至右排序
bigtop(arr, i, arr.length);
}//第一次排成大顶堆
System.out.println(Arrays.toString(arr));
int temp;
//将堆顶元素与末尾元素交换,再重新对剩余子堆进行调整为大顶堆
for (int i = arr.length-1; i >0;i--) {
temp= arr[i];
arr[i]=arr[0];
arr[0]=temp;
bigtop(arr, 0, i);//建立在上一个for循环已经构建成大顶堆的情况下
//大顶堆已排好,只是交换头顶元素此时将堆底元素与堆顶元素交换后,对顶节点数肯定小于子节点
}
System.out.println(Arrays.toString(arr));
}
//注意应用数学抽象,将树抽象为数组,参数length为某一子树的大小
public static void bigtop(int[]arr,int i,int length) {
//该方法是对于局部而言的
int temp=arr[i];//先保存,再插入防止覆盖
for (int k = 2*i+1; k <length; k=2*k+1) {//注意这里的长度为局部长度不是整个数组的长度
//往下找,直到没有节点
if (arr[k]<arr[k+1]&&k+1<length) {//左节点小于右节点,用右节点比较
k++;
}
if (temp<arr[k]) {//当前节点小于子节点,交换
arr[i]=arr[k];
i=k;//将当前节点指向下一层,继续循环比较
}else {
break;//当前节点的子节点都比当前节点小
}
}
arr[i]=temp;
}
}