算法-详解堆排序算法

Posted 蓝桥杯

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了算法-详解堆排序算法相关的知识,希望对你有一定的参考价值。

堆排序是利用堆的性质进行的一种选择排序。

时间复杂度:

  • 时间复杂度:O(nlogn)

  • 空间复杂度:O(1)(就地排序,用于堆化(又称筛选)的辅助空间)

性能:

  1. 由于建初始堆所需的比较次数较多,所以堆排序不适宜于记录数较少的。

  2. 堆排序的时间,主要由建立初始堆和反复重建堆这两部分的时间开销构成。

  3. 堆排序是一种不稳定排序。 
    科普:(排序的稳定性是指如果在排序的序列中,存在前后相同的两个元素的话,排序前和排序后他们的相对位置不发生变化)。

  4. 即使在最坏情况堆排序的时间复杂仍然为O(nlogn)。而快速排序在最坏情况下会达到O(N^2),所以快排在最好和平均情况下比堆排快,堆排在最坏情况下比快排快。

基本思想:

利用大(小)顶堆堆顶记录的是最大(小)关键字这一特性,使得每次从无序中选择最大(小)记录变得简单。

下面的讨论全部基于大顶堆(小顶堆同理,不再赘述)。

  1. 将初始待排序关键字序列(R1,R2….Rn)构建成大顶堆,此堆为初始的无序区;

  2. 将堆顶元素R[1]与最后一个元素R[n]交换,此时得到新的无序区(R1,R2,……Rn-1)和新的有序区(Rn),且满足R[1,2…n-1]<=R[n];

  3. 由于交换后新的堆顶R[1]可能违反堆的性质,因此需要对当前无序区(R1,R2,……Rn-1)调整为新堆(堆化、筛选),然后再次将R[1]与无序区最后一个元素交换,得到新的无序区(R1,R2….Rn-2)和新的有序区(Rn-1,Rn)。不断重复此过程直到有序区的元素个数为n-1(原堆剩最后一个元素),则整个排序过程完成。

操作过程如下:

  1. 初始化堆:将R[1..n]构造为堆;

  2. 将当前无序区的堆顶元素R[1]同该区间的最后一个记录交换,然后将新的无序区调整为新的堆(不断堆化)。

因此对于堆排序,最重要的两个操作就是构造初始堆和调整堆,其实构造初始堆事实上也是调整堆的过程,只不过构造初始堆是对所有的非叶节点都进行调整。

给定一个整形数组a[]={16,7,3,20,17,8},对其进行堆排序。

首先根据该数组元素构建一个完全二叉树,得到:

算法-详解堆排序算法

然后需要构造初始堆,则从最后一个非叶节点开始调整,调整过程如下:

以下为构造初始堆:

  1. 8和3交换,满足;

  2. 20和7交换,导致20和16不满足; 

算法-详解堆排序算法
算法-详解堆排序算法

  1. 20和16交换,导致17和16不满足;

  2. 17和16交换; 

算法-详解堆排序算法
算法-详解堆排序算法


1.完成构建(大顶堆)。

即每次调整都是从父节点、左孩子节点、右孩子节点三者中选择最大者跟父节点进行交换(交换之后可能造成被交换的孩子节点不满足堆的性质,因此每次交换之后要重新对被交换的孩子节点进行调整)。有了初始堆之后就可以进行排序了。

以下为交换元素并每步堆化(排序):

  1. 交换3与20; 如下图: 
    此时3位于堆顶不满大顶堆的性质,则需继续调整。 
    交换3与17,导致3与16不满足; 
    交换3与16; 
    满足; 

算法-详解堆排序算法
算法-详解堆排序算法
算法-详解堆排序算法


  1. 交换17与3;如下图: 
    此时3位于堆顶不满大顶堆的性质,则需继续调整。 
    交换3与16,导致3与7不满足; 
    交换3与7; 
    满足;

算法-详解堆排序算法
算法-详解堆排序算法
算法-详解堆排序算法


3. 交换16与3;如下图: 
此时3位于堆顶不满大顶堆的性质,则需继续调整。 
交换3与8; 
满足;

4. 交换3与8;如下图: 
此时3位于堆顶不满大顶堆的性质,则需继续调整。 
交换3与7; 
满足;


算法-详解堆排序算法
算法-详解堆排序算法


5. 交换3与7;如下图: 
满足,完成排序。


算法-详解堆排序算法


这样整个区间便已经有序了。

从上述过程可知,堆排序其实也是一种选择排序,是一种树形选择排序。只不过直接选择排序中,为了从R[1…n]中选择最大记录,需比较n-1次,然后从R[1…n-2]中选择最大记录需比较n-2次。事实上这n-2次比较中有很多已经在前面的n-1次比较中已经做过,而树形选择排序恰好利用树形的特点保存了部分前面的比较结果,因此可以减少比较次数。对于n个关键字序列,最坏情况下每个节点需比较logn次,因此其最坏情况下时间复杂度为nlogn。

算法实现(java):

算法-详解堆排序算法


测试程序:

算法-详解堆排序算法


打印内容如下:




以上是关于算法-详解堆排序算法的主要内容,如果未能解决你的问题,请参考以下文章

九种经典排序算法详解(冒泡排序,插入排序,选择排序,快速排序,归并排序,堆排序,计数排序,桶排序,基数排序)

Heapsort 堆排序算法详解(Java实现)

必须知道的八大种排序算法java实现 归并排序算法堆排序算法详解

算法知识详解堆排序算法

经典排序算法和python详解:归并排序快速排序堆排序计数排序桶排序和基数排序

数据结构c语言版八大算法(上)图文详解带你快速掌握——希尔排序,堆排序,插入排序,选择排序,冒泡排序!