数据结构-堆排序(Java实现)

堆排序算法 主要是要先把数组看成二叉树
然后把二叉树变成一个大顶堆(任何一个节点大于它的左右节点,但是左右节点两者的大小不确定)
然后把大顶堆的第一个元素和最后一个元素换位,依次类推,最后就的得出一个有规律的数组

package datastructure.tree;

/*
    @CreateTime 2021/9/5 10:27
    @CreateBy cfk
    堆排序算法
*/

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


public class HeapSort {
    public static void main(String[] args) {
        int[] arr = {4,-1,6,0,8,5,9};
        int tmp = 0;
        // ajustHeap(arr, 1, arr.length);
        // ajustHeap(arr, 0, arr.length);
        // System.out.println(Arrays.toString(arr));


        //根据升序和降序选择生成大顶堆和小顶堆
        //arr.length/2-1为最后一个非叶子节点
        for (int i = arr.length/2-1; i >= 0; i--) {
            ajustHeap(arr,i,arr.length);
        }
        System.out.println(Arrays.toString(arr));


        //上面得出大顶堆 已经确定了一个最大值 所以这里的次数会减一
        for (int j = arr.length-1; j > 0; j--) {
            tmp = arr[0];
            arr[0] = arr[j];
            arr[j] = tmp;

            //从0开始是因为数组已经是大顶堆了,把最大值换位置后,第二第三大的值会重新选举最大的值
            ajustHeap(arr,0,j);
        }
        System.out.println(Arrays.toString(arr));
        }


    //测试8000000数据的性能 2s
/*    public static void main(String[] args) {
        int tmp = 0;
        int[] arr = new int[8000000];
        for (int i = 0; i < 8000000; i++) {
            arr[i] = (int) (Math.random()*8000000);
        }

        System.out.print("排序前");
        Date date1 = new Date();
        SimpleDateFormat sdf1 = new SimpleDateFormat("yyy-MM-dd HH:mm:ss");
        String timeBefore1 = sdf1.format(date1);
        System.out.println(timeBefore1);


        for (int i = arr.length/2-1; i > 0 ; i--) {
            ajustHeap(arr,i,arr.length);

        }

        for (int i = arr.length-1; i > 0; i--) {
            tmp = arr[0];
            arr[0] = arr[i];
            arr[i] = tmp;
            ajustHeap(arr,0,i);
        }



        System.out.print("排序后");
        Date date2 = new Date();
        SimpleDateFormat sdf2 = new SimpleDateFormat("yyy-MM-dd HH:mm:ss");
        String timeBefore2 = sdf2.format(date2);
        System.out.println(timeBefore2);
        // System.out.println(Arrays.toString(arr));
    }*/

    /*
            4
          6   8
        5 9
     */
    //此方法将数组调整成为大顶堆
    /**
     *
     * @param arr 传入数组
     * @param i 传入调整的非叶子节点
     * @param length 传入调整的数组的长度
     * @return 在这里不需要返回值,因为可以直接调整数组,让数组内容发生改变
     */
    public static void ajustHeap(int[] arr,int i,int length){

        int tmp = arr[i];

        for (int j = 2*i+1; j < length; j=2*j+1) {
            //通过循环遍历把j指针指向下一位 如果左节点比右节点小的话
            //这里j+1判不判断都可以 判断了如果j+1大于length的话直接就可以退出循环了 提高了效率
            if (j+1<length && arr[j]<arr[j+1]){
                j++;
            }

            //判断当前非叶子节点和其子节点数值大小变化

            if (tmp<arr[j]){
                arr[i] = arr[j];
                //把i指向j是为了继续循环判断,i赋值后就继续往i下的子树进行循环,直到最后
                i = j;
            }else {
                break;
            }


        }
            arr[i] = tmp;




    }

}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值