首页 > 技术文章 > [编程题] 堆排序(数组与大顶堆的转换过程)

jiyongjia 2020-08-09 14:25 原文

[编程题] 堆排序(数组与大顶堆的转换过程)

参考这个大神讲解的堆排序,思路清晰


数组和树的关系

题目信息

​ 如何把数组转换为二叉树呢?

思路

数组对应树的公式:

数组一个节点的左孩子:2*i+1

数组一个节点的右孩子:2*i+2

某节点的父亲节点:(i-1)/2

注意


数组转为大顶堆

思路

思路:在每一个节点进入的时候,就会比较其与父节点的大小关系,调整树结构。(这里即是交换数组中的元素),建立出了大顶堆的数组。

建立大顶堆的时间复杂度

时间复杂度:O(nlogn)

Java代码

package Demo11_堆;

import java.lang.reflect.Parameter;
import java.util.Arrays;

/**
 * @author jiyongjia
 * @create 2020/8/9 - 13:23
 * @descp:
 */
public class P3_堆排序 {
    public static void main(String[] args) {
        int[] arr = {10, 131,3,42,221,3,2,-1,0,-32, 40, 5, 2, 18};
//        heapify(arr,arr.length,0);
//        heap_build(arr);
        heapSort(arr);
        System.out.println(Arrays.toString(arr));
    }
    /**
     * 1 heapify操作(需要按照传入的i的父节点进行递归的heapify操作)
     * @param arr 数组
     * @param n  数组的个数
     * @param i  传入的父节点的索引号(如0)
     */
    public static void heapify(int[] arr,int n,int i){
        //递归的出口
        if(i>=n){return;}
        int l = 2*i+1;
        int r = 2*i+2;
        int maxIndex = i;
        if(l<n && arr[l]>arr[maxIndex]){ //TODO:注意
            maxIndex = l;
        }
        if(r<n && arr[r]>arr[maxIndex]){
            maxIndex = r;
        }
        if(maxIndex != i){
            swap(arr,i,maxIndex);//只有不等才交换
            //递归处理
            heapify(arr,n,maxIndex);
        }
    }

    public static void swap(int[] arr,int i,int j){
        int temp = arr[i];
        arr[i] = arr[j];
        arr[j] = temp;
    }

    /**
     *2 使用heapify从最后一个非叶子节点往前遍历每个父节点,然后生成一个大顶堆
     * @param arr
     */
    public static void heap_build(int[] arr){
        int n = arr.length;
        int lastNodeParent = (n-1-1)/2;   //根据公式计算最后一个非叶子节点(即最后一个父节点)
        for (int i = lastNodeParent; i >=0 ; i--) {
            heapify(arr,arr.length,i);   //倒着推的从下往上构建好堆
        }
    }

    //3 构建好堆之后,每次把堆顶的元素和最后一个元素交换,得到一个最大值放最后了
    public static void heapSort(int[] arr){
        heap_build(arr);//先构造出一个堆
        for(int i=arr.length-1;i>=0;i--){
            //经过交换,最大的堆顶到了最后一个元素的地方
            swap(arr,i,0);
            //下次heapfify就不考虑这个最后的这个堆即可
            heapify(arr,i,0); //从0开始heapify这个堆来调整堆。此次最大值已经在最后位置了,所以这里传的数组长度为i
        }
    }
}

输出:

int[] arr = {10, 131,3,42,221,3,2,-1,0,-32, 40, 5, 2, 18};

image-20200809142235734

推荐阅读