public class HeapSort {
/**
* 初始化
* 根据数组建立一个堆,此处为大顶堆,大顶堆的每个节点的值都大于其左右孩子的值
* @param arr
*/
public static void buildHeap(int[] arr) {
int len = arr.length;
int lastNode = len/2;//最后一个节点
for(int i=lastNode;i>=1;i--) {
// 对所有的非叶子节点进行循环 ,且从最后一个非叶子节点开始
heapAdjust(arr, i, len);
}
}
/**
* 对堆进行调整
* @param arr
* @param parentNodeIndex 非叶子节点的index
* @param len
*/
public static void heapAdjust(int[] arr,int parentNodeIndex,int len) {
int maxNodeIndex = parentNodeIndex;
// 如果有左子树,i * 2为左子树节点索引
// i 节点和叶子节点的关系为 2*i 和 2*i+1 根节点的i为1 , 索引值需要减去1
if(parentNodeIndex*2<=len) {
// 如果父节点小于左子树时
if ((arr[parentNodeIndex - 1]-(arr[parentNodeIndex * 2 - 1])) < 0) {
maxNodeIndex = parentNodeIndex * 2;// 记录最大索引为左子节点索引
}
// 只有在有左子树的前提下才可能有右子树,再进一步断判是否有右子树
if (parentNodeIndex * 2 + 1 <= len) {
// 如果右子树比最大节点更大
if ((arr[maxNodeIndex - 1]-(arr[(parentNodeIndex * 2 + 1) - 1])) < 0) {
maxNodeIndex = parentNodeIndex * 2 + 1;// 记录最大索引为右子节点索引
}
}
}
// 如果在父节点、左、右子节点三者中,最大节点不是父节点时需要交换,把最大的与父节点交换,创建大顶堆
if (maxNodeIndex != parentNodeIndex) {
swap(arr, parentNodeIndex - 1, maxNodeIndex - 1);
// 交换后可能需要重建堆,原父节点可能需要继续下沉 因为交换后 maxNodeIndex位置的值就不一定是三个节点中最大的了!
//向下递归怎么保证最大值到根结点,因为初始化之后元素有序??除根结点外,左右是次大值
if (maxNodeIndex * 2 <= len) {// 是否有子节点,注,只需判断是否有左子树即可知道
heapAdjust(arr, maxNodeIndex, len);
}
}
}
public static void swap(int[] arr,int i,int j) {
if (i != j) {// 只有不是同一位置时才需交换
int tmp = arr[i];
arr[i] = arr[j];
arr[j] = tmp;
}
}
public static void heapSort(int[] arr) {
//初始化一个大顶堆
buildHeap(arr);
/*for (int i : arr) {
System.out.print(i+" ");
}*/
/*
* 对初始堆进行循环,且从最后一个节点开始,直到树只有两个节点止 每轮循环后丢弃最后一个叶子节点,再看作一个新的树
*/
for (int i = arr.length; i >= 2; i--) {
// 根节点与最后一个叶子节点交换位置,即数组中的第一个元素与最后一个元素互换
swap(arr, 0, i - 1);
// 交换后需要重新调整堆,堆的末尾少1,即不计入结果
heapAdjust(arr, 1, i - 1);//递归重新的构建一个大顶堆
}
}
public static void main(String[] args) {
int[] arr = {6, 9, 0, 4, 5, 9, 1, 4, 2, 6, 3, 8, 0, 7, 0, -7, -1, 34};
heapSort(arr);
for (int i : arr) {
System.out.println(i);
}
System.out.println("--------------------");
int[] arr2 = new int[]{49, 38, 65, 97, 76, 13, 27, 48, 55, 4};
heapSort(arr2);
for (int i : arr2) {
System.out.println(i);
}
}
}
排序算法-----堆排序
猜你喜欢
转载自blog.csdn.net/weixin_42061676/article/details/81093074
今日推荐
周排行