堆排序代码的理解

基本思想

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

初始堆

构建第一个大顶堆

将序列的最大值即对顶的根节点与末尾元素进行交换,此时末尾就为最大值。最大值就已经排序出来了,如此反复循环可以得到升序序列。

import java.util.Arrays;

public class HeapSort {
    public static void main(String[] args) {
        int[] a = {35, 63, 48, 9, 86, 24, 53, 11};
        int[] nums = heapsort(a);
        System.out.println(Arrays.toString(nums));
    }
public static  int [] heapsort(int []a){
       int len=a.length;
       if(len<=1)return a;
       bulidHeap(a);
       while(len>0){
           swap(a,0,len-1);
           len--;
           adjustHeap(a,0,len);
       }
       return a;
}
/*
我一开始看到这这个代码的时候主要有这个疑惑,为什么第一次构建大顶堆的时候
需要从最后一个分支节点来进行循环调用adjustheap函数直到根节点,而在第一
次构建完大顶堆后,此后每次构建大顶堆时只需要调用一次adjust函数,我把我
具体的理解放在了文章下面。
 */
public  static void bulidHeap(int []a){
        for(int i=(a.length/2)-1;i>=0;i--){
            adjustHeap(a,i,a.length);
        }
}
public  static  void adjustHeap(int []a,int i,int len){
        int maxIndex=i;
        int left=2*i+1;
        int right=2*i+2;
        if(left<len&&a[left]>a[maxIndex])
            maxIndex=left;
        if(right<len&&a[right]>a[maxIndex])
            maxIndex=right;
        if(maxIndex!=i){
            swap(a,maxIndex,i);
            adjustHeap(a,maxIndex,len);
        }
}
public  static void swap(int []a,int i,int j){
        int temp=a[i];
        a[i]=a[j];
        a[j]=temp;
    }
}

第一次构建大顶堆的过程在上面已经用图表示的很清楚了,buildHeap函数里面的循环意思就是从最后一个分支节点开始向上遍历每一个分支节点,把他们都构造成大顶堆,在adjustHeap函数里面的if(maxIndex!=I)判断语句要是为真,if判断语句之后的执行语句执行调整的节点是当前节点的子节点,注意这是重点。

如果没有构建好大顶堆,那么节点的大小顺序按照层次来看是没有规律的,如果直接调用adjustHeap函数并且传递的是第一个节点的参数的话,很可能出现以下的情况

由图我们可以看出来这个是构建不出来一个正确的大顶堆的,因为我写的这里的adjustHeap函数它内部的语句

if(maxIndex!=i){
swap(a,maxIndex,i);
adjustHeap(a,maxIndex,len);
}

是向下调整的。

在第一次构建好大顶堆后,节点的大小顺序是第一层大于第二层依次类推的,所以在第一次构建好大顶堆并且将其首元素与末尾元素进行交换后直接调用adjustHeap函数并且传参传的是堆顶元素的索引,adjustHeap里面的

if(maxIndex!=i){
swap(a,maxIndex,i);
adjustHeap(a,maxIndex,len);
}

语句会让它会自己向下调整构建大顶堆。

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值