八大排序算法(3)

八、堆排序(平均时间复杂度:O(nlogn))

        1、介绍:

         1)堆排序是利用堆这种数据结构而设计的一种排序算法,属于选择排序的一                       种,是不稳定的排序。
         2)堆是具有以下性质的完全二叉树:每个结点的值都大于或等于其左右孩子                      结点的值(没有要求其左右孩子的大小关系),称为大顶堆(常用来升序)。

         3)每个结点的值都小于或等于其左右孩子结点的值,称为小顶堆(用来降序)。

 

        2、思想:

        1)将待排序序列构造成一个大顶堆(以数组形式存放)。

八大排序算法(3)_第1张图片

        2)此时,整个序列的最大数就是堆顶的根节点。

        3)将其与末尾元素进行交换,此时末尾就是最大值。

        4)然后将剩余的n-1个元素重新构造成一个堆,这样就会得到n个元素的次小值,               再反复执行,得到一个有序序列。

        5)可以看到在构建大顶堆的过程中,元素的个数逐渐减少,最后就得到一个有序               序列。

        3、思路图解:

        1)将无序序列构建成一个堆,根据升序降序需求选择大顶堆或者小顶堆

        2)将堆顶元素与末尾元素交换,将最大元素沉到数组末端

        3)重新调整结构,使其满足堆定义,然后继续交换堆顶元素与当前末尾元素,反               复执行调整交换步骤,直到整个序列有序。

        八大排序算法(3)_第2张图片

八大排序算法(3)_第3张图片八大排序算法(3)_第4张图片

八大排序算法(3)_第5张图片

八大排序算法(3)_第6张图片

 4、代码如下:

//堆排序的方法
    public static void heapSort(int[] arr){
        int temp = 0;
        //将无序序列构建成一个堆,根据升序降序需求选择大顶堆或者小顶堆
        for(int i = arr.length / 2 - 1; i >= 0; i--){
            adjustHeap(arr,i,arr.length);
        }
        /*
        将堆顶元素与末尾元素交换,将最大元素沉到数组末端
        重新调整结构,使其满足堆定义,然后继续交换堆顶元素与当前末尾元素,反复执行调整交换步骤,直到整个序列有序。
         */
        for(int j = arr.length - 1; j > 0; j--){
            //交换
            temp = arr[j];
            arr[j] = arr[0];
            arr[0] = temp;
            adjustHeap(arr,0,j);//每次的第一个非叶子节点开始调整
        }
    }
    //将一个二叉树(以数组的形式),调整成大顶堆
    /**
     *完成将以i对应的非叶子结点的局部树调整成大顶堆
     *举例 int arr[] = {4,6,8,5,9}; =>i = 1 =>经过该方法处理=>得到{4,9,8,5,6},会进行局部处理
     * @param arr 调整的数组
     * @param i  表示非叶子节点在数组中的索引
     * @param length 表示对多少个元素继续调整,length是在逐渐的减小
     */
    public static void  adjustHeap(int[] arr,int i,int length){
        int temp = arr[i];//先取出当前元素的值,保存在临时变量
        //开始调整
        //k = i * 2 + 1指的是k是i的结点的左子结点
        for (int k = i * 2 + 1; k < length; k = k * 2 + 1){
            if(arr[k] < arr[k+1] && (k + 1) < length){//说明左子结点的值小于右子结点的值
                k++;//k指向右子节点
            }
            if(arr[k] > temp){//如果子结点大于父结点
                arr[i] = arr[k];//把子结点的值赋给父结点
                i = k;//记录下子结点的下标
            }else {
                break;//因为调整是自下向上,自左向右的,可以直接退出循环
            }
        }
        //循环结束完,我们已经将以i为父结点的树的最大值,放在了最顶上(局部)
        arr[i] = temp;//将temp值放到调整后的位置
    }

九、小结:

        1、总共有8个排序算法:直接插入排序和希尔排序属于插入排序、简单选择排序和堆排序属于选择排序、冒泡排序和快速排序属于交换排序、归并排序、基数排序。

        2、排序算法比较:

        八大排序算法(3)_第7张图片

       

       In-place指的是不占用额外内存    out-place指的是占用额外内存

你可能感兴趣的:(算法)