《算法(第四版)》排序-----堆排序


1.什么是堆?

讲堆排序之前,先了解一下什么是堆。堆其实相当于一种数据结构,它的本质是一种数组对象,但是它里面的内同又是一颗完全二叉树结构,它的特点是父节点的值大于(或小于)两个子节点的值,常常用于优先队列、堆排序等。

堆在数组中的索引有如下的特点。数组索引为k的元素,它的父节点的索引为[k/2](下取整),它的两个子节点索引为2k, 2k+1,依次类推


2.堆排序的基本过程

(1)构造一个堆

如果给定一个数组,只需要从左到右遍历数组,用swim()保证扫描指针左侧的所有元素已经是一颗堆有序的完全二叉树即可,就像连续向优先队列中插入元素一样,但是更有效的办法是由又想做用sink()下浮的方式来构造堆。

(2)基本思想

用白话来讲,堆排序是很简单的,你先用下沉的方法构造了一个堆后,堆有一个特点啊,那就是它的第一个元素永远是最大(或最小)的,如果你想从小到大排,那就把首元素和最后一个元素交换,肯定没毛病,这样最大的就归位了。下一步再把前n-1个元素利用下沉恢复堆的结构,这样倒数第二大的有跑到最前面了,那就让它再和倒数第二个交换就行了,依次类推。。。。

参照《算法第四版》图解



(3)具体代码实现:

public static void  heapSort(Comparable[] a){
    int N = a.length;
    for(int k = N/2; k >= 1; k--){//利用下沉将堆
        sink(a, k, N);
    }
    while(N>1){
        exch(a, 1, N--);//将最前面的和后面交换,此处注意N--了,所以下一行的N已经是N--后的值了
        sink(a, 1,N);   //利用下沉恢复堆有序
    }
}

//观察可以发现,此处的sink不是之前的博客讲的只传入int  k  让某个元素下沉就好,此处传入了a[]  ,N,因为这个N是变化的,不断的在减小
public static void sink(Comparable[] a, int i, int j){
    while( 2*i < j){
        int k = 2 * i;
        if(k < j && less(k, k+1))   k++;
        if(less(k, i))  break;
        exch(a, i, k);
        i = k;
    }
}


(4)说明

堆排序在现代系统的许多应用很少用到它,因为它无法利用缓存,但是用堆实现的优先队列在现在应用中越来越重要,因为它能插入操作和删除最大元素混合动态场景中保证对级数级别的运行时间,尤其是数据量较大时用,比如10亿个元素中,选出最大的10个等。

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值