当前位置:首页 > 公众号精选 > 嵌入式客栈
[导读]关注、星标 嵌入式客栈 ,干货及时送达 [导读] 前面文章《聊聊改变世界的5大算法》,一文中提到快速排序算法对世界影响巨大,估计很多人不以为然,本文来尝试解读一下为啥。 快排有多快 说到快我只推崇葵花宝典,那叫一个快啊~~~ 皮一下哈哈,言归正传。快

关注、星标 嵌入式客栈 ,干货及时送达


[导读] 前面文章《聊聊改变世界的5大算法,一文中提到快速排序算法对世界影响巨大,估计很多人不以为然,本文来尝试解读一下为啥。

快排有多快

说到快我只推崇葵花宝典,那叫一个快啊~~~

皮一下哈哈,言归正传。快速排序算法如其名一样,快!来看看快排和其他几大排序算法的并行运行对比视频(中间那个就是快排),你就知道它到底有多快了,请全屏横屏播放更清晰:

啥是快排?

分治思想

  • 从待排元素集中选取一个元素作为摆动基准pivot,pivot这词比较形象,记为P
  • 将元素重新排列为3个子块:
  1. 左子块S1:由 P的元素组成
  2. 中间块M:仅有P一个元素
  3. 右子块S2:由≥P的元素组成
  • 对左子块S1和右子块S2递归地重复上述过程,Return {quicksort(S 1 ), P, quicksort(S 2 )}.
  • 代码实现

    代码如下:

    typedef int T_ELEMENT; int partition(T_ELEMENT A[ ], int left, int right); /* sort A[left..right] */ void quicksort(T_ELEMENT A[ ], int left, int right) { int q; if( right <= left ) return; if ( right > left )
      {  
         q = partition(A, left, right); /* partition分块后 */ //-> A[left..q-1] ≤ A[q] ≤ A[q+1..right] quicksort(A, left, q-1);     
         quicksort(A, q+1, right);
       } 
    } int partition(T_ELEMENT A[], int left, int right);
    { 
        T_ELEMENT P = A[left];
        i = left;
        j = right + 1; /*无限循环,使用break退出*/ for(;;) 
        { while (A[++i] < P) if (i >= right) break; /* 此时 A[i] ≥ P */ while (A[--j] > P) if (j <= left) break; /* 此时 A[j] ≤ P */ if (i >= j ) break; /*退出for循环*/ else swap(A[i], A[j]); 
        } if (j == left) return j ;
        swap(A[left], A[j]); return j;
    }

    举栗子分析:

    分成三块了,再递归子块迭代,直到right<=left.

    算法分析

    • 这种快速排序的优点是我们可以“就地”排序,即无需依赖于输入大小的临时缓冲区。没有缓冲区内存开销,仅有栈开销。(注还有一种非递归的栈实现版本,本文就先不聊了)
    • partition步骤:时间复杂度为θ(n)。
    • 快速排序涉及分区和2个递归调用。故:

    T(n) = θ(n) + T(i) + T(n-i-1) = cn+ T(i) + T(n-i-1)

    其中,i是分区后第一个子块的大小,将T(0)=T(1)= 1作为初始条件。

    • 具体运行时间对不同特性的待排数据,其结果差异比较大,来看一下最好、最坏以及平均情况分析。

    最差情况

    • 当待排数据序列为正序或者逆序时,pivot将是在大小为n的待排块时中的最小(或最大)元素时。则阶段1迭代中生成一个空子块、pivot,及一个大小(n-1)的子块,则时间复杂度为θ(n)
    • 递归方程:

    如果这种情况在每个分区中都重复发生,那么每个递归调用处理一个比前一个列表小1的列表。因此需要在达到大小为1的列表之前进行n - 1次嵌套调用。这意味着调用树是n - 1个嵌套调用的线性链。第i次调用需要做O(n-i)复杂度来进行分区,则

    最好情况

    • 如每次分区时枢轴(pivot)都能取到中间值,即每次分区后,将产生两个大小大致相等的子块,并且枢轴(pivot)元素处于中间值位置,需要做n次比较运算。

    • 递归方程:


    如前所说,如每次执行分区时,都能将列表分成两个几乎相等的两个子块。这意味着每次递归调用都要处理一个只有一半大小的列表。因此,在到达大小为1的列表之前,我们只能进行 嵌套调用。这意味着调用树的深度为 ,但是在调用树的同一级别上没有两个调用处理原始列表的相同部分;因此,每个级别的调用总共只需要O(n)个时间(每个调用都有一些固定的开销,但是由于每个级别上只有O(n)个调用,所以这被包含在O(n)因子中)。结果是,该算法只使用c(n log n)的时间。故时间复杂度为O(n log n)。

    平均情况

    要对n个不同元素的数组进行排序,快速排序需要O(n log n)的预期时间,推导很枯燥就不罗嗦了。

    其他排序算法

    注:快排不需要额外的缓冲区开销,但是需要栈开销,其空间复杂度为O(log n).

    这里对上表其中几个效率相对较高的做个简要介绍,后面如有机会再深入学习总结:

    • Introsort内省排序,在C++ STL中有应用。内省排序(英语:Introsort)是由David Musser在1997年设计的排序算法。这个排序算法首先从快速排序开始,当递归深度超过一定深度(深度为排序元素数量的对数值)后转为堆排序。采用这个方法,内省排序既能在常规数据集上实现快速排序的高性能,又能在最坏情况下仍保持O(n log n) 的时间复杂度。由于这两种算法都属于比较排序算法,所以内省排序也是一个比较排序算法。

    • Timsort排序算法:是一种混合稳定排序算法,它是从合并排序和插入排序中派生而来的,旨在对多种实际数据表现良好。由Tim Peters在2002年实现,用于Python编程语言。该算法查找已排序(运行)的数据的子序列,并使用它们对其余部分进行更有效的排序。这是通过合并运行直到满足特定条件来完成的。自2.3版以来,Timsort一直是Python的标准排序算法。还应用在Android平台上的Java SE 7、GNU Octave(是一个开源的类MATLAB数序软件)、V8(开源Java script引擎)以及Swift中,用于对非原始类型的数组进行排序。

    • MergeSort归并排序:在计算机科学中,是一种高效的,通用的,基于比较的排序算法。大多数实现产生稳定的排序,这意味着相等元素的顺序在输入和输出中是相同的。归并排序是约翰·冯·诺伊曼(John von Neumann)在1945年发明的分而治之算法。早在1948年,Goldstine和von Neumann的报告就对自下而上的合并排序进行了详细描述和分析。

    • Tournament sort:通过使用优先级队列来查找排序中的下一个元素,它改进了选择排序。在原始的选择排序中,需要O(n)个操作才能选择n个元素中的下一个元素;在锦标赛排序中,需要进行O(log n)运算(在O(n)中建立初始锦标赛之后)。锦标赛排序是堆排序的一种变体。

    • 树形选择排序又称锦标赛排序(Tournament Sort:是一种按照锦标赛的思想进行选择排序的方法。首先对n个记录的关键字进行两两比较,然后在 个较小者之间再进行两两比较,如此重复,直至选出最小的记录为止。

    • 块排序或块合并排序Block sort: 它将至少两个合并操作与插入排序组合在一起,以达到O(n log n)的位置稳定排序。合并两个排序的列表,A和B,等价于将A分成大小相等的块,在特殊规则下将每个块插入到B中,并合并AB对。

    • 平滑排序smoothsort,是一种基于比较的排序算法。它是堆排序的一种变体,由Edsger Dijkstra于1981年发明并发布。它的时间复杂度上限是O(n log n),但它不是一个稳定的排序。平滑排序的优点是,如果输入已经排序到一定程度,那么它会更接近O(n)的时间,而堆排序的平均值是O(n log n),而不管初始排序状态如何。

    • 希尔排序Shellsort,也称为Shell排序或Shell的方法,是一种就地比较排序。它可以被看作是交换排序(冒泡排序)或插入排序(插入排序)的泛化。该方法首先对彼此相距很远的元素对进行排序,然后逐步缩小要比较的元素之间的差距。通过从相隔很远的元素开始,它可以比简单的最近邻交换更快地将一些位置错误的元素移动到正确的位置。Donald Shell在1959年出版了第一个版本。Shellsort的运行时间很大程度上依赖于它使用的间隙序列。

    算法应用

    说到排序算法复杂度,请一定要与应用场景结合。主要需要考虑待排数据的集的尺寸,如果数据量小的时候反而是插入排序算法应用最为广泛;而对于海量数据场合,则应使用渐近有效排序策略。这是什么意思呢?说白了就是常使用混合算法!主要策略是利用快速排序、堆排序或归并排序将整体快速分治排序,同时对递归底部的小列表采用插入排序。事实上,在实际应用中有更复杂的变体,例如在Android,Java和Python中使用的Timsort(合并排序,插入排序和其他逻辑),以及在某些C++中用的introsort(快速排序和堆排序) 在.NET中排序实现。

    再说白一点,在海量数据场景,利用快速排序、堆排序或归并排序将海量数据快速迭代成收敛的小块,而在小块中采用最为常见的插入排序尽快完成小块排序,小块中采用插入排序则可以更大程度减少递归深度。

    总结一下

    在信息时代,有海量信息需要处理,即便有非常强劲的处理器,但如没有很好的算法,仍然无法满足对这些信息的处理。在处理过程中,免不了要进行信息进行排序,快排在时空两个维度的开销都比较均衡,大量的应用软件、开发工具以及软件包都基于快排做了大量的应用。所以说快速排序改变世界,个人认为并不为过。同时对于求职面试,快速排序算法也是高频面试主题,值得深入研究掌握。

    原创不易,如觉得本文有价值,请点再看或者分享给身边的小伙伴,让更多看到。

    END

    往期精彩推荐,点击即可阅读




    Linux内核中I2C总线及设备长啥样? [强烈推荐]
    学习AI之机器学习概念篇
    手把手教系列之IIR数字滤波器设计实现


    免责声明:本文内容由21ic获得授权后发布,版权归原作者所有,本平台仅提供信息存储服务。文章仅代表作者个人观点,不代表本平台立场,如有问题,请联系我们,谢谢!

    本站声明: 本文章由作者或相关机构授权发布,目的在于传递更多信息,并不代表本站赞同其观点,本站亦不保证或承诺内容真实性等。需要转载请联系该专栏作者,如若文章内容侵犯您的权益,请及时联系本站删除。
    换一批
    延伸阅读

    2023年10月18日,中国在第三届“一带一路”国际合作高峰论坛期间发布《全球人工智能治理倡议》,围绕人工智能发展、安全、治理三方面系统阐述了人工智能治理中国方案。

    关键字: 人工智能 大模型 代码

    我们看到这么多的安全问题,部分原因在于我们对待安全的方式:安全性通常被认为是事后考虑的问题,是在开发结束时才添加到设备上的东西。然而,复杂的系统,尤其是嵌入式系统,有一个很大的攻击面,这让攻击者有机可乘,能够在“盔甲”上...

    关键字: 代码 嵌入式系统 软件漏洞

    新富人群财务需求多元发展,投顾服务迎来新机遇 上海2023年9月20日 /美通社/ -- 2023年9月19日,上海交通大学上海高级金融学院(高金)与全球领先的金融服务机构嘉信理财(Charles Schwab)联合发...

    关键字: BSP ADVANCED INA 代码

    北京2023年9月14日 /美通社/ -- 生物医药高科技公司诺诚健华(港交所代码:09969;上交所代码:688428)今日宣布,新型蛋白酪氨酸磷酸酶SHP2变构抑制剂ICP-189联用针对表皮生长因子受体(EGFR)...

    关键字: IC HP 代码 ARMA

    上海2023年9月1日 /美通社/ -- 2023上半年,安集科技(股票代码:688019)市场拓展规划成效显现,营业收入稳健增长。 全球半导体产业挑战持续存在的情形下,安集科技秉承发扬"克难攻坚,敢打硬...

    关键字: 安集科技 BSP 代码 半导体材料

    国际酒店运营商升级其在线支付功能 上海2023年8月28日 /美通社/ -- 加拿大金融科技公司Nuvei Corporation(以下简称“Nuvei”或“公司”)(纳斯达克代码:NVEI)(多伦多证券交易所代码:N...

    关键字: 代码 IP SE 纳斯达克

    2023年上半年收入7.459亿元 同比增长5.1% 毛利率水平上升 海外收入同比增长65.4% 香港2023年8月22日 /美通社/ -- 金邦达宝嘉控股有限公司及其附属公司(以下合称「金邦达」、「...

    关键字: 数字化 代码 嵌入式软件 COM

    我们经常对正在进行数字化转型的亚马逊云科技客户建议,将云迁移视为其数字化转型的一部分,数字化转型本身必须由业务成果驱动。其中治理计划的有效性决定了云迁移和数字化转型的成功与否。数字化转型中的云迁移总有结束的时候,但是如果...

    关键字: 代码 数字化 云服务

    广州及苏州生产基地产品均实现"出口"零突破 北京2023年8月21日 /美通社/ -- 百济神州(纳斯达克代码:BGNE;香港联交所代码:06160;上交所代码:688235)是一家全球性生物科技公...

    关键字: 神州 代码 TI PD

    近年来,国内电子公司和芯片设计企业大举进攻汽车、医疗和工业等高可靠应用(mission-critical)领域,为自己找到了摆脱红海的新领域。但是高可靠应用多数都需要功能安全认证,在许多行业在诸如汽车、航空电子、医疗和工...

    关键字: 代码 代码分析工具
    关闭
    关闭