• 数据机构与算法学习(八)- 排序


    一、如何分析一个“排序算法”

    排序算法的执行效率

    1. 最好情况、最坏情况、平均情况时间复杂度

    第一,有些排序算法会区分,为了好对比做一下区分。第二,对于要排序的数据,有的接近有序有的接近无序。有序度不同的数据对于排序的执行时间肯定是有影响的,我们要知道在不同的数据下的性能表现。

    2. 时间复杂度的系数、常数、低阶

    时间复杂度是一个增长趋势,它在表示的时候会忽略系数、常数、低阶。但是在实际的开发中需要考虑。

    3.比较次数和交换次数

    基于比较的排序算法, 在执行的过程中,会涉及两种操作,一种比较元素大小,另一种交换或移动元素。在分析 执行效率时也要考虑。

    排序算法的内存消耗

    算法的内存消耗可以通过空间复杂度来衡量,排序算法也不例外。针对排序算法有一个原地排序的概念。特指空间复杂度为O(1)的排序算法

    排序算法的稳定性

    如果待排序的序列中存在值相等的元素,经过排序后相等的元素的先后顺序不变。比如一组数据括号内为原始序列2(1),9(2),3(3),4(4),8(5),3(6), 排序后为2(1),3(3),3(6),4(4),8(5),9(2),那么这种排序算法叫做稳定排序算法,否则叫做不稳定排序算法

    二、排序算法

    冒泡排序、插入排序、选择排序、归并排序、快速排序这几种常用的排序算法。已经有单独的文章介绍原理和代码(从百度百科摘录的),这里就不在说明了。将各种算法的分析结果列在这里。

      原地排序 稳定排序 最好 最坏 平均
    冒泡排序 O(n) O(n2) O(n2)
    插入排序 O(n) O(n2) O(n2)
    选择排序 × O(n2) O(n2) O(n2)
    归并排序 × O(nlogn)
    快速排序 × O(nlogn)

    桶排序

    核心思想是将要排序的数据分到几个有序的桶里,每个桶里的数据再单独进行排序。桶内排序完成之后,再把每个桶里的数据按照顺序依次取出,组成的序列就是有序的了。

     时间复杂度分析如果要排序的数据有n个,我们要把它们均匀地划分到m个桶内,每个桶里就有k=n/m个元素。每个桶内使用快速排序,时间复杂度就是O(k*logk).m个桶排序的时间复杂度就是o(m*k*logk),因为k=n/m,所以整个桶排序的时间复杂度就是O(n*log(n/m)).当桶的个数m接近数据个数n的时,log(n/m)就是一个非常小的常量,这个时候桶排序的时间复杂度接近O(n).

    对数据要求:首先排序的数据需要很容易就能划分成M个桶,并且桶与桶之间有着天然的大小顺序。这样每个桶内的数据排完序后,桶与桶之间的数据不需要在进行排序。其次,数据在桶之间的分布必须是均匀的。极端情况下,数据都被划分到一个桶里,那就退化为O(nlogn)的排序算法了。

    应用场景:比较适合用在外部排序中。就是数据存储在外部磁盘中数据量比较大,内存有限,无法将数据全部加载到内存中。

    计数排序

    计数排序其实是桶排序的一种特殊情况。当要排序n个数据,所处的范围并不大的时候,比如最大值是k,我们就可以吧数据划分成K个桶。每个桶内数值相等,省掉了桶内排序的时间。

    计数排序只能用在数据范围不大的场景中,如果数据范围K比要排序的数据n大的多,就不适合用计数排序了。而且,计数排序只能给非负整数排序,如果要排序的数据是其他类型,要将其在不改变相对大小的情况下,转化为非负整数。

    基数排序

    基数排序对要排序的数据是有要求的,需要可以分割出独立的“位”来比较,而且位之间有递进关系,如果a数据的高位比b数据大,那剩下的低位就不用比较了。除此之外,每一位的数据范围不能太大,要可以用线性排序算法来排序,否则,基数排序的时间复杂度就无法做到o(n)了。

     三、排序算法优化

    如何选择合适的排序算法

    线性排序算法适用场景比较特殊。所以如果要写一个通用的排序算法,不能选择线性排序算法。对于小规模数据进行排序,可以选择时间复杂度是O(n2)的算法;如果对于大规模的数据进行排序,O(nlogn)的算法更加高效。所以一般首选O(nlogn)的排序算法来实现排序函数。

    O(nlogn)的算法前面介绍过快速排序和归并排序还有堆排序。因为归并排序不是原地排序,那么只有快速排序比较适合实现排序函数。但是快速排序在最坏的情况下时间复杂度是O(n2),如何解决复杂度恶化的问题呢?

    如何优化快速排序?

    主要原因还是因为我们分区点选的不够合理。最理想的分区点:被分区点分开的两个分区中,数据的数量差不多。不能粗暴的选择第一个或最后一个。

    常用的分区算法:

    1. 三数取中法:从收尾中间分别取出一个数,然后对比大小,取中间值作为分区点。如果数据较大,可能要五数取中,十数取中。

    2. 随机法:每次从要排序的区间中,随机选择一个元素作为分区点。

    举例分析排序函数

    用qsort()函数举例说明

    qsort()会优先使用哦归并排序来排序输入数据,要排序的数据量比较大的时候,qsort()会改为用快速排序算法来排序。qsort()选择分区点的方法就是“三数取中法”。在元素小于等于4的时候qsort()就退化为插入排序。

  • 相关阅读:
    迅雷极速版 2020年 防止升级方法
    微PE WEPEMENU.INI CDLINUX BEINI 启动菜单
    tcping 0.39
    海康威视楼宇可视对讲解码器拨码规则计算器-安卓版
    博客园-文字互动插件
    WSL-Ubuntu 安装Xubuntu-Desktop 记录
    html css的冷门相关基础知识整理
    git hub 的冲突解决方案
    css实现垂直居中的方式
    js中BOM相关知识
  • 原文地址:https://www.cnblogs.com/OneSky-Mi/p/14643110.html
Copyright © 2020-2023  润新知