• 堆排序


        本文参考《算法导论》,整理者:华科小涛@http://www.cnblogs.com/hust-ghtao/眨眼

        堆排序和归并排序一样,时间复杂度为CodeCogsEqn(15),而且可以实现原址排序:任何时候都只需要常数个额外的元素空间存储临时数据。

    1. 最大堆

        (二叉)堆是一个数组,可以看成一个近似的完全二叉树。树上的每个结点对应数组中一个元素。除了最底层之外,该树是完全充满的,而且是从左到右填充。表示对的数组A包括两个属性:A.length给出数组元素的个数,A.heap-size表示有多少个堆元素存储在数组中。树的根结点为A[1],给定结点的下标i,则它的父节点、左孩子和又孩子的下标:

    image                    image

       二叉堆可分为最大堆与最小堆。在最大堆中,最大堆的性质是除了根结点以外的所有结点i都要满足:CodeCogsEqn

      在堆排序算法中我们使用的就是最大堆。

    2. 维护堆的性质

          MAX-HEAPIFY是用于维护最大堆性质的重要过程。

    输入:数组 A 和一个下标 i 。

    前提:在调用MAX-HEAPIFY的时候,假定根结点为 LEFT(i) 和 RIGHT(i) 的二叉树都是最大堆,但A[i]可能小于其孩子,这就违背了最大堆的性质。

    思路:通过让A[i]逐级下降的方式,使得下标为以i为根结点的子树遵循最大堆的性质。

    伪代码如下:

    image在程序的每一步中,从A[i]、A[LEFT(i)]、和A[RIGHT(i)]中选出最大的,并将其下标存储在largest中。如果A[i]是最大的,那么以i为根结点的子树已经是最大堆,程序结束。否则,最大元素是i的某个孩子结点,则交换A[i]和A[largest]的值。从而使i及其孩子都满足最大堆的性质。在交换后,下标为largest的结点的值是原来的A[i],于是以该结点为根的子树又有可能会违反最大堆的性质。因此需要对该子树递归调用MAX-HEAPIFY。

    MAX-HEAPIFY时间复杂度为CodeCogsEqn(1)

    3. 建堆

    可以采用自底向上的方法利用过程MAX-HEAPIFY把一个大小为 n=A.length 的数组A[1…n]转换为最大堆。我们知道,子数组CodeCogsEqn(2) 中的元素都是树的叶结点。每个叶结点可以看成只包含一个元素的堆。建堆的过程BUILD-MAX-HEAP对树中的其他结点都调用一次MAX-HEAPIFY:

    image

    BUILD-MAX-HEAP的复杂度为CodeCogsEqn(3)

    4.堆排序算法

    伪代码:

    image

    说明:首先建堆。

    因为数组中的最大元素总在根结点A[1]中,通过把它与A[n]进行互换,我们可以让该元素放到正确的位置。这时候,如果我们从堆中去掉结点n,剩余的结点中,原来根的孩子结点仍然是最大堆,而新的根结点可能会未被最大堆的性质。为了维护最大堆的性质,我们调用MAX-HEAPIFY(A,1),从而在A[1…n]构造一个新的最大堆。堆排序算法不断重复这一过程,直到堆的大小降为2。

    HEAPSORT(A)的时间复杂度为CodeCogsEqn(4),因为建堆为CodeCogsEqn(3),加上(n-1)次调用MAX-HEAPIFY

     

  • 相关阅读:
    测试管理工具
    测试用例--zy
    测试计划和测试用例
    测试用例
    软件测试基础
    异步任务 ---- django-celery
    图片验证码接口
    测试作业
    数据库原理
    HTTPS原理
  • 原文地址:https://www.cnblogs.com/hust-ghtao/p/4161998.html
Copyright © 2020-2023  润新知