06排序之堆排序

堆排序

参考

基本介绍

  1. 堆排序是利用堆这种数据结构而设计的一种排序算法,堆排序是一种选择排序,它的最坏 ,最好,平均时间复杂度均为O(nlogn),它也是不稳定排序
  2. 堆是具有以下性质的完全二叉树:每个节点的值都大于或等于其左右孩子节点的值,称为大顶堆注意没有要求节点的左孩子的值和右孩子的值的大小相等
  3. 每个节点的值都小于或等于其左右孩子节点的值,称为小顶堆

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-oFoblBWF-1578562267616)(images/01.png)]

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-AaZaUyNW-1578562267618)(images/02.png)]

4.一般升序采用大顶堆,降序采用小顶堆

基本思想

…建堆,交换…建堆,交换…建堆,交换…建堆,交换…

  1. 将待排序序列构成一个大顶堆
  2. 此时,整个序列的最大值就是堆顶的根节点
  3. 将其与末尾元素交换,此时末尾就成为最大值
  4. 然后将剩余n-1个元素重新构造成一个堆。这样会得到n个元素的次小值。如此反复执行,便能得到一个有序序列

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

思路分析

以 int[] arr = {4,6,8,5,9};数组堆排序的分析过程为例

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-2WdZqDFr-1578562267619)(images/03.png)]

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-uilDCr0n-1578562267619)(images/04.png)]

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-Z4pl7n13-1578562267620)(images/05.png)]

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-TCfmyFIz-1578562267620)(images/06.png)]

代码

package J树的提高;

import sun.misc.LRUCache;

import java.util.Arrays;

/**
 * @Author Zhou  jian
 * @Date 2020 ${month}  2020/1/9 0009  13:57
 * 堆排序
 */
public class HeapSort {

    public static void main(String[] args) {
        //要求将数组升序排列
        int[] arr = {4,6,8,5,9};

        heapSort(arr);

    }

    //编写一个堆排序的方法
    public static void heapSort(int[] arr){
        int temp = 0;
        System.out.println("堆排序");

        //分步完成
//        adjustHeap(arr,1,arr.length);
//        System.out.println("第一次"+ Arrays.toString(arr));//4 9 8 5 6
//
//        adjustHeap(arr,0,arr.length); //9 6 8 5 4
//        System.out.println("第而次"+ Arrays.toString(arr));//9 6 8 5 4


        //完成最终代码
        //将无需序列构建成一个堆,根据升序降序需求选择大顶堆或小顶堆
        for(int i=arr.length/2-1;i>=0;i--){
            adjustHeap(arr,i,arr.length);
        }
//        System.out.println(Arrays.toString(arr));

        //将堆顶元素与末尾元素交换,将最大元素 “沉”到数组末端
        //重新调整结构,使其满足堆定义,然后继续交换堆顶元素与当前末尾元素,反复执行调整+交换步骤,直到整个序列有序
        for(int j=arr.length-1;j>0;j--){
            //交换
            temp = arr[j];
            arr[j]=arr[0];
            arr[0]=temp;
            adjustHeap(arr,0,j);
        }

       System.out.println(Arrays.toString(arr));


    }

    //将一个数组(二叉树)调整成一个大顶堆
    /**
     * 功能:完成将以i指向对应的非叶子节点对应的树调整成大顶堆
     * 举例:int[] arr = {4,6,8,5,9} ;=> i=1=>adjustHeap =>得到{4,9,8,5,6}
     *       再次调用adjustHeap传入的i=0=> 得到{4,9,8,5,6}=>{9,6,8,5,4}
     * @param arr   待调整的数组
     * @param i    表示非叶子结点在数组中的索引
     * @param length  表示对多少个元素进行调整,length在逐渐减少
     */
    public static void  adjustHeap(int[] arr,int i,int length){

        //先取出当前元素的值,保存在临时变量
        int temp = arr[i];

        //开始调整
        //说明
        //1、k=i*2+1 k是i的左子节点
        for(int k=i*2+1;k<length;k=k*2+1){
            //找左右节点哪个节点大
            if(((k+1)<length) && (arr[k]<arr[k+1])){//说明左子节点值小于右子节点的值
                k++; //k指向右子节点
            }

            if(arr[k]>temp){//如果子节点大于父节点
                arr[i]=arr[k]; //把较大的值赋给当前节点
                i=k;//让i指向k,继续循环比较
            }else{
                break; //从左到右从下到上调整
            }

        }

        //当for循环结束后,我们已经将i为父节点的树最大值,放在了最顶(局部)
        arr[i]=temp;//将temp值放到调整后的位置

    }




}

发布了101 篇原创文章 · 获赞 17 · 访问量 1万+

猜你喜欢

转载自blog.csdn.net/ZHOUJIAN_TANK/article/details/103912954