记录学习排序算法时个人感觉比较难理解的堆排序

89 阅读2分钟

八大排序算法中个人感觉最难理解的堆排序,做一个学习记录 基本思想是把树化为大根堆,然后把这个树的顶和末尾交换,就把最大元素排好了,依次交换后,整个数组就排好了

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;



}