ICode9

精准搜索请尝试: 精确搜索
首页 > 编程语言> 文章详细

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

2021-04-13 08:35:08  阅读:208  来源: 互联网

标签:nlogn 复杂度 学习 算法 n2 排序 数据


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

排序算法的执行效率

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()就退化为插入排序。

标签:nlogn,复杂度,学习,算法,n2,排序,数据
来源: https://www.cnblogs.com/OneSky-Mi/p/14643110.html

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有