八大排序算法中个人感觉最难理解的堆排序,做一个学习记录 基本思想是把树化为大根堆,然后把这个树的顶和末尾交换,就把最大元素排好了,依次交换后,整个数组就排好了
public class HeapSort {
public static void heapSort(int[] arr) {
for (int i = arr.length/2-1; i >=0 ; i--) {//从后往前遍历非叶子节点,这些节点就是要被比较的父节点
adjustHeap(arr,i, arr.length);
}
//经过上面这样就得到了一个最大的大跟堆
for (int i = arr.length-1; i >0; i--) {
//把第一个元素(最大元素)和最后一个元素交换位置
int temp = arr[0];
arr[0] = arr[i];
arr[i]=temp;
//交换完之后最后一个元素就是最大的,就不用再考虑最后一个元素,现在只需要考虑前面的,把前面的元素再调整为大根堆
adjustHeap(arr,0,i);
}
//循环结束后就依次把最大,第二大。。。的元素从后往前排,排完就排序好了
}
/**
*用来把一个树调整为大根堆
* @param arr 待调整的树对应的数组(树)
* @param i 将要被比较的数父节点,也就是把这个节点为父节点的树变为大顶堆
* @param length 要处理的树是数组的前length位
*/
public static void adjustHeap(int[] arr, int i, int length) {
int temp=arr[i];//保存父节点的值
for (int j = i*2+1; j <length ; j=j*2+1) {
if (j+1<length&&arr[j] < arr[j + 1]) { //这一步是为了得到左右子节点中最大的节点,下面交换时直接交换最大的子节点
j++;
}
if (arr[j] > temp) {//其中最大的一个子节点大于这个方法的最上面父节点
arr[i] = arr[j];//当前循环的父节点置为大于最上面父节点的那个值
i = j; //j记录了这次被换上去的值原先所在的位置,随着i的迭代,i就变成了最底层树种被换上去的子节点所在的原位置
} else {
break;//由于是从下往上循环(见heapSort方法第一个循环体),且每次循环都是得到大根堆,
// 故上面的都小于temp的话,下面不可能大于temp,直接break
}
}
arr[i]=temp;
}