排序算法:堆排序

前置知识

 

       堆排序主要利用的是大顶堆的思想(父节点大于等于子节点),在数组中可以用二叉树的表示为第n个元素的左子节点为2*n+1,右子节点为2*n+2,父节点为(n-1)/2。即arr[i]>=arr[2*i+1]&&arr[i]>=arr[2*i+2]。

堆排序的基本思想

      1.将排序数组构造为一个大顶堆

      2.此时,整个序列的最大值就是堆顶的根节点

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

      4.然后将剩余的n-1个元素重新构造成一个堆,重复1,2,3,步最后得到一个有序序列。

图解如下

       步骤一:构造大顶堆

       1.原始数组为arr=[4,6,8,5,9]

       2.从最后一个非叶子节点进行调整,即i=(arr.length/2)-1=1,从0到i都是父节点,从左至右,从下到上依次进行调整。

       3.找到第二个非叶子节点arr[0]=4,进行调整。

      4.调整完发现[4,5,6]不是一个大顶堆,继续调整

       步骤二:将堆顶元素与末尾元素进行交换,再继续调整堆,交换,调整,交换......

         1.将堆顶元素9与末尾元素4交换

      2.继续调整堆结构       3.将元素8与5进行调换。

 

        4.继续调整,交换直到数组有序。

 

 

代码如下

        1.构建大顶堆

 public static void adjust(int[] arr,int index,int len){
        int temp=arr[index];
        for(int i=2*index+1;i<len;i=2*i+1){
            //比较两个叶子节点的值,让i指向最大的值
            if(i+1<len&&arr[i]<arr[i+1]){
                i++;
            }
//            如果叶子节点的值大于父节点,将叶子节点的值赋给父节点,同时该叶子节点
//            成为下一个父节点。
            if(arr[i]>temp){
                arr[index]=arr[i];
                index=i;
            }else {
                break;
            }
        }
        //最后将最开始的存储的父节点赋给叶子节点
        arr[index]=temp;
    }

        2.首先构造一个大顶堆,在进行首尾交换,继续构造大顶堆。

public static void sort(int[] arr){
        for(int i=arr.length/2-1;i>=0;i--){
            adjust(arr,i,arr.length);
        }
        for(int i=arr.length-1;i>=0;i--){
            int temp=arr[i];
            arr[i]=arr[0];
            arr[0]=temp;
            adjust(arr,0,i);
        }

    }

 完整代码

import java.util.Arrays;

public class test {
    public static void main(String[] args) {
        int[] arr={4,6,1,2,9,8,3,5,-1,-100,0,9} ;
        sort(arr);
        System.out.println(Arrays.toString(arr));

    }
    public static void sort(int[] arr){
        for(int i=arr.length/2-1;i>=0;i--){
            adjust(arr,i,arr.length);
        }
        for(int i=arr.length-1;i>=0;i--){
            int temp=arr[i];
            arr[i]=arr[0];
            arr[0]=temp;
            adjust(arr,0,i);
        }

    }
    public static void adjust(int[] arr,int index,int len){
        int temp=arr[index];
        for(int i=2*index+1;i<len;i=2*i+1){
            //比较两个叶子节点的值,让i指向最大的值
            if(i+1<len&&arr[i]<arr[i+1]){
                i++;
            }
//            如果叶子节点的值大于父节点,将叶子节点的值赋给父节点,同时该叶子节点
//            成为下一个父节点。
            if(arr[i]>temp){
                arr[index]=arr[i];
                index=i;
            }else {
                break;
            }
        }
        //最后将最开始的存储的父节点赋给叶子节点
        arr[index]=temp;
    }
}

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值