08堆排序

48 阅读2分钟

08堆排序

基本思想:将数组构成大顶堆,将最大元素其转移至数组(堆)的末尾,再将剩余的n-1个元素构建大顶堆,重复如上操作。
讲解:
//创建一个名为Heap_sort的方法,传入待排数组及其大小
public static void Heap_sort(int a[],int len){
    //i从最后一个非叶子节点(叶子结点的下标就是总大小len / 2 - 1)开始,依次向前遍历直到0
    for(int i = len / 2 - 1;i >= 0;i--){
        //构建大顶堆,传入待排数组a、当前节点i的下标、末尾元素的下标len - 1
        HeapAdjust(a,i,len - 1);
    }
    //第一个循环结束后,此时数组中的第一个元素为数组中的最大值
    //从最后一个元素开始向前遍历
    for(int i = len - 1;i > 0;i--){
        //依次交换相邻元素,目的是将最大元素转移至数组末尾
        swap(a,0,i);
        //每交换一次,进行一次构建堆,传入数组a,起始位置0,结束位置i - 1
        HeapAdjust(a,0,i - 1);
    }
}
//创建一个名为HeapAdjust的方法构建大顶堆,传入待排数组a,起始位置start,结束位置end
public static void HeapAdjust(int a[],int start,int end){
    //定义变量dad为start,即父节点
    int dad = start;
    //定义变量son为当前父节点的左孩子节点
    int son = dad * 2 + 1;
    //循环条件:子节点下标始终不超过边界值
    while(son <= end){
        //判断子节点大小,选取较大值的那个孩子
        if(son + 1 <= end && a[son] < a[son + 1]){
            //左孩子下标+1 = 右孩子下标
            son++;
        }
        //若父节点的值大于子节点的值,说明当前的大顶堆构建完成,直接退出
        if(a[dad] > a[son]){
            return;
        //如果不是,则说明仍需要调整
        }else{
            //首先交换父节点和子节点的值
            swap(a,dad,son);
            //其次让父节点赋值为子节点的下标
            dad = son;
            //子节点下标更新为当前父节点下标 * 2 + 1
            son = dad * 2 + 1;
        }
    }
}
//创建一个名为swap的方法,用于交换数组中的元素,传入数组a、待交换元素下标n1、n2
public static void swap(int a[],int n1,int n2){
    int temp = a[n1];
    a[n1] = a[n2];
    a[n2] = temp;
}