尚硅谷-数据结构与算法-二叉树-堆排序

 

 

 

 

 

 

package com.atguigu.tree.threadebinarytree;

import java.text.SimpleDateFormat;
import java.util.Arrays;
import java.util.Date;

/**
 * @author WZ
 * @create 2021-10-23 14:07
 */
public class HeapSort {
    public static void main(String[] args) {
        //要求将数组进行升序排列----大顶锥
//        int[] arr=new int[]{4,6,8,5,9};
//        headSort(arr);
        //测试性能
        int []arr=new int[8000000];
        for (int i = 0; i < arr.length; i++) {
            arr[i]=(int) (Math.random()*8000000);
        }
        System.out.println("排序前");
        Date date = new Date();
        SimpleDateFormat simpleDateFormat=new SimpleDateFormat("yyyy-MM-dd HH-mm-ss");
        String str1 = simpleDateFormat.format(date);
        System.out.println("排序前的时间是"+str1);
        headSort(arr);
        Date date1=new Date();
        String str2 = simpleDateFormat.format(date1);
        System.out.println("排序后的时间是"+str2);


    }





    //编写一个堆排序的方法
    public static void  headSort(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);
//        System.out.println("第二步完成局部大顶锥"+ Arrays.toString(arr));//9.6.8.5.4

        //完成最终代码,将无序序列建成一个堆,根据升序降序需求选择大顶堆或者小顶堆
        for (int i = arr.length/2-1; i >=0; i--) {//arr.length/2-1=5/2-1=2-1=1;先1后0从下至上
            adjustHeap(arr,i,arr.length);
        }

        /*
        将堆顶的元素与末尾元素交换,将最大的元素“沉”到数组末端;
        重新调整结构,使其满足堆定义,然后继续交换堆顶元素与当前末尾元素,反复执行调整+交换的步骤,直到这个序列有序
         */
        for (int j = arr.length-1; j >0 ; j--) {//总共5个数,调整4次即可
            //开始交换,首尾交换
            temp=arr[j];
            arr[j]=arr[0];
            arr[0]=temp;
            adjustHeap(arr,0,j);//写0的目的是始终从顶部开始找
        }
//        System.out.println("数组="+ Arrays.toString(arr));


    }

    //将一个数组(二叉树),调整成一个大顶锥的方法

    /**
     *功能:完成将以i对应的非叶子节点的树调整成大顶锥
     * 举例:int arr[]={4,6,8,5,9};=> i先等于1(非叶子节点在数组中的索引为1)进去后,
     * 调整数组成{4,9,8,5,6};(从左至右,从下至上进行调整)
     * 再次调用,第二次进行调整,应该调整角标为i=0对应非叶子节点为4的数,调整成{9,4,8,5,6}
     * 但此次调整会导致字根4,5,6发生变化,继续调整,4,5,6中6最大交换4,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];//先取出当前元素的值,保存在一个临时变量
        //开始调整
        //k表示以i为非叶子节点的左子节点,最后k表示下次再调整也是左子节点
        for (int k = i*2+1; k <length ; k=k*2+1) {
            if (k+1<length && arr[k] < arr[k+1]) {//这个说明左子节点的值小于右子节点的值
                k++;//在这种情况下让k指向右子节点(k为左子节点,k+1是右子节点)
            }

            if (arr[k]>temp){//如果子节点大于父节点
                arr[i]=arr[k];//把较大的值,赋给当前节点
                i=k;//因为k没有完,下面可能还有左子树或者右子树
            }else {
                break;//如果是小于,直接停止即可,因为是从最后一个非叶子节点开始的,不用判断下面,下面就是有序的。
            }

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




    }

}

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值