堆排序(Heap Sort)

堆排序(Heap Sort)

堆排序(Heapsort)是指利用堆这种数据结构所设计的一种排序算法。堆积是一个近似完全二叉树的结构,并同时满足堆积的性质:即子结点的键值或索引总是小于(或者大于)它的父节点。

1 算法描述

  • 将初始待排序关键字序列(R1,R2….Rn)构建成大顶堆,此堆为初始的无序区;
  • 将堆顶元素R[1]与最后一个元素R[n]交换,此时得到新的无序区(R1,R2,……Rn-1)和新的有序区(Rn),且满足R[1,2…n-1]<=R[n];
  • 由于交换后新的堆顶R[1]可能违反堆的性质,因此需要对当前无序区(R1,R2,……Rn-1)调整为新堆,然后再次将R[1]与无序区最后一个元素交换,得到新的无序区(R1,R2….Rn-2)和新的有序区(Rn-1,Rn)。不断重复此过程直到有序区的元素个数为n-1,则整个排序过程完成。

2 动图演示

img

3 代码实现

public class Sort {

    public void heapSort(int[] nums) {
        int length=nums.length;
        for(int i=length/2-1;i>=0;i--){
            heapAdjust(nums,i,length);
        }
        for(int i=length-1;i>0;i--){
            int temp=nums[0];
            nums[0]=nums[i];
            nums[i]=temp;
            heapAdjust(nums,0,i);
        }
    }

    private void heapAdjust(int[] nums, int index, int length) {
        int max=index;
        int l=max*2+1;
        int r=max*2+2;
        if(r<length&&nums[r]>nums[max]){
            max=r;
        }
        if(l<length&&nums[l]>nums[max]){
            max=l;
        }
        if(max!=index){
            int temp=nums[max];
            nums[max]=nums[index];
            nums[index]=temp;
            //交换完之后需要再次对max进行调整,因为此时max有可能不满足最大堆
            heapAdjust(nums,max,length);
        }
    }

}

4 测试

import org.junit.Test;

public class TestSort {
    private static int[] tem=new int[]{1,5,9,4,3,6,8,2,6,8};
    private static Sort sort=new Sort();

    @Test
    public void testHeapSort(){
        System.out.println("排序前:");
        toArray();
        sort.heapSort(tem);
        System.out.println("排序后:");
        toArray();
    }

    public static void toArray(){
        for(int i=0;i<tem.length;i++){
            System.out.print(tem[i]+" ");
        }
        System.out.println();
    }
}

结果截图:
在这里插入图片描述

5 算法分析

5.1 时间复杂度

建堆的时候初始化堆过程(HeapAdjust)是堆排序的关键,时间复杂度为O(log n),下面看堆排序的两个过程;

第一步,初始化堆,这一步时间复杂度是O(n)

第二步,交换堆顶元素过程,需要用到n-1次循环,且每一次都要用到(HeapAdjust),所以时间复杂度为((n-1)*log n)~O(nlog n)

最终时间复杂度:O(n)+O(nlog n),后者复杂度高于前者,所以堆排序的时间复杂度为O(nlog n)

5.2 空间复杂度

空间复杂度是O(1),因为没有用到额外开辟的集合空间。

5.3算法稳定性

堆排序是不稳定的,比方说二叉树[6a,8,13,6b],(这里的6a和6b数值上都是6,只不过为了区别6所以这样)经过堆初始化后以及排序过后就变成[6b,6a,8,13];可见堆排序是不稳定的。

6 总结

堆排序不同于其他排序算法,它利用了完全二叉树的性质进行排序,如果能充分理解,那就觉得非常有意思的!本文通过图解方式,笔者尽最大努力讲解,但能力有限,若大家有更好的想法欢迎交流~

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值