软考:排序

来源:互联网 发布:临沂淘宝客服外包公司 编辑:程序博客网 时间:2024/06/01 07:37

    该文章是关于数据结构部分排序的总结,包括各种排序方法的时间和空间复杂度的分析,主要从直接插入、交换(冒泡、快速)、选择(直接选择、堆排序)和归并四类来分析。


直接插入:

    依次将每个记录插入到一个已排好序的有序表中,从而得到一个新的、记录数增加1的有序表。具体:插入第i个记录时,前i-1已经排好序,此时将第i个记录的关键字和第i-1i-2比较,从而找到插入位置插入位置及其后记录依次向后移动。

    举例:9  6 15 8 11


         复杂度: 直接插入最好情况下每趟只需做一次比较且不用移动元素,因此n个元素总比较次数n-1,总移动0次;最坏情况下进行第j趟排序时与前面每个记录都有比较,双重循环,此时是关于n^2的式子;又排序过程中仅需一个元素的辅助空间,空间复杂度O1),且是稳定排序。

交换:

        冒泡:首先将第一个记录键值和第二个记录键值比较,如果R[1].key>R[2].key,则交换,然后继续比较第二个和第三个,比较n-1次后完成最大记录在n的位置,此为第一趟起泡;然后进行第二次起泡完成最大记录在n-1位置,重复此过程直至没有进行记录交换的操作时结束。

    举例:9  6 15 8 11


       冒泡排序最理想情况,一组排序好的序列,只需比较n-1次,完成一次起泡即可,时间复杂度为On),最坏情况,一为n个元素逆序列,每趟比较次数为n-1n-2…1,所以On^2);排序过程仅需一个元素的辅助空间用于元素交换,空间复杂度O1),且是稳定排序。     

       快速:通过一趟排序将待排序记录分为独立两部分,其中一部分记录关键字不小于另一部分关键字,然后再对两部分继续快速排序。做法:附设两指针ij,初值分别指向第一个记录和最后一个记录,通常假设第一个记录值作为关键字key,首先从j所指位置向前搜索,找到第一个关键字小于key的记录并与之交换,然后从i所指位置向后搜索,找到第一个关键字大于key的记录并与之交换,重复这两步直至ij相等。


   选取第一个记录9为关键字,完成第一趟排序后,再对9左右两部分快速排。

       时间复杂度:通过主定理:T [n] = aT[n/b] + f (n)其中 a >= 1 and b> 1 是常量 并且 f(n) 是一个渐近正函数, 为了使用这个主定理,您需要考虑下列三种情况:


       快速排序的每一次划分把一个 问题分解成两个子问题,其中的关系可以用下式表示:T[n] = 2T[n/2] +O(n) 其中O(n)为PARTITION()的时间复杂度,对比主定理, T [n] =aT[n/b] + f (n),我们的快速排序中:a = 2, b =2, f(n) = O(n)


选择:

    直接选择:在第i次选择操作中,通过n-i次键值比较,从n-i+1个记录中选择键值最小的记录,并和第iI<=i<=n-1)个记录交换。

     举例:9  6 15 8 11


    复杂度分析:直接选择包含两层嵌套for循环,时间复杂度为On^2),且是不稳定的。

   堆排序:对一组待排序记录建立初始堆(建堆过程:将待排序关键字放到一课完全二叉树各个结点中,从n/2开始筛选,逐步把n/2-1n/2-2…1为根的子树筛选成堆)排序过程中先和最后一个结点比较,每比较交换一次都有重新建堆,直至完成前两个结点的比较,基于最小堆的堆排序输出由大到小的序列。

    举例:9  6 15 8 11

         放在一棵二叉树中为:


    建堆:从n/2即第二个结点6开始筛选,然后筛选第一个结点,建好堆如下:


    堆排序过程:堆顶元素6和最后结点11比较,交换,重新构建堆:

    

    然后堆顶元素8和倒数第二个结点比较,交换之后重新构建堆,直至前两个结点比较交换后结束。

    时间复杂度:包括筛选和堆比较两部分。那么要执行多少次筛选呢?每一次筛选根结点都往下沉,所以筛选次数不会超过完全二叉树的深度([log2n]向下取整+1),其中n为结点个数,2为底数,即时间复杂度为Olog2n,堆比较是堆顶结点和最后一个结点开始比直至第二个结点,呈线性,所以为On),所以时间复杂度Onlog2n)。

 归并(以二路归并来说):反复讲两个有序文件归并呈一个有序文件的排序方法。

     举例:9  6 15 8 11


    时间复杂度Onlog2n),且是稳定的。关于时间复杂度分析不是很理解,欢迎交流。

    参考:快速排序复杂度分析、归并排序复杂度分析 堆排序复杂度分析

0 0
原创粉丝点击