安庆大理运城常德铜陵江西
投稿投诉
江西南阳
嘉兴昆明
铜陵滨州
广东西昌
常德梅州
兰州阳江
运城金华
广西萍乡
大理重庆
诸暨泉州
安庆南充
武汉辽宁

一文搞定十大排序算法(动画图解)

6月2日 无镇楼投稿
  排序算法是测试开发技术面试中的常考题目,本文用动画图解面试必会十大排序算法,由浅入深、形象记忆,再也忘不掉。排序基础知识
  排序的定义
  排序,就是重新排列表中的元素,使表中的元素满足按关键字递增或递减的过程。为了査找方便,通常要求计算机中的表是按关键字有序的。
  排序的确切定义如下:输入:n个记录R1,R2,R3Rn,对应的关键字为K1,K2,K3Kn输出:输入序列的一个重排R1’,R2’,R3’Rn’,使得有K1’K2’K3’Kn’(其中可以换成其它的比较大小符号)。
  算法的稳定性:
  若待排序表中有两个元素Ri和Rj,其对应的关键字keyikcyj,且在排序前Ri在Rj的前面。使用某一排序算法排序后,Ri仍然在Rj的前面尽的前面,则称这个排序算法是稳定的。否则称排序算法是不稳定的。
  需要注意的是,算法是否具有稳定性并不能衡量个算法的优劣,它主要针对算法的性质进行描述。只需举出一组关徤字的实例,即可说明一个算法是不稳定的。
  时间复杂度:〔1〕(来自百度百科)
  算法中基本操作重复执行的次数是问题规模n的某个函数,用T(n)表示,若有某个辅助函数f(n),使得T(n)f(n)的极限值(当n趋近于无穷大时)为不等于零的常数,则称f(n)是T(n)的同数量级函数。记作T(n)O(f(n)),称O(f(n))为算法的渐进时间复杂度,简称时间复杂度。
  分析:随着模块n的增大,算法执行的时间的增长率和f(n)的增长率成正比,所以f(n)越小,算法的时间复杂度越低,算法的效率越高。
  在计算时间复杂度的时候,先找出算法的基本操作,然后根据相应的各语句确定它的执行次数,再找出T(n)的同数量级(它的同数量级有以下:1,log2n,n,nlogn,n的平方,n的三次方,2的n次方,n!),找出后,f(n)该数量级,若T(n)f(n)求极限可得到一常数c,则时间复杂度T(n)O(f(n))
  空间复杂度:〔2〕(来自百度百科)
  类似于时间复杂度的讨论,一个算法的空间复杂度S(n)定义为该算法所耗费的存储空间,它也是问题规模n的函数。渐近空间复杂度也常常简称为空间复杂度。
  空间复杂度(SpaceComplexity)是对一个算法在运行过程中临时占用存储空间大小的量度。一个算法在计算机存储器上所占用的存储空间,包括存储算法本身所占用的存储空间,算法的输入输出数据所占用的存储空间和算法在运行过程中临时占用的存储空间这三个方面。
  算法的输入输出数据所占用的存储空间是由要解决的问题决定的,是通过参数表由调用函数传递而来的,它不随本算法的不同而改变。存储算法本身所占用的存储空间与算法书写的长短成正比,要压缩这方面的存储空间,就必须编写出较短的算法。
  算法在运行过程中临时占用的存储空间随算法的不同而异,有的算法只需要占用少量的临时工作单元,而且不随问题规模的大小而改变,我们称这种算法是就地进行的,是节省存储的算法,有的算法需要占用的临时工作单元数与解决问题的规模n有关,它随着n的增大而增大,当n较大时,将占用较多的存储单元,例如快速排序和归并排序算法就属于这种情况。
  算法的分类可以按照是否是比较类的算法来分类,也可以按照排序过程中数据是否都存在于内存中来分类:
  如下:
  按照内部排序和外部排序分类:
  image1080152489。7KB
  按照是否为比较类的排序来分:
  image1080150982。8KB算法时间复杂度
  image10801061112KB1。插入排序(InsertionSort)
  插入排序(InsertionSort)的算法描述是一种简单直观的排序算法。它的工作原理是通过构建有序序列,对于未排序数据,在已排序序列中从后向前扫描,找到相应位置并插入。
  算法描述
  一般来说,插入排序都采用inplace在数组上实现。具体算法描述如下:从第一个元素开始,该元素可以认为已经被排序;取出下一个元素,在已经排序的元素序列中从后向前扫描;如果该元素(已排序)大于新元素,将该元素移到下一位置;重复步骤3,直到找到已排序的元素小于或者等于新元素的位置;将新元素插入到该位置后;重复步骤25。
  动图演示
  C代码实现functioninsertionSort(arr){varlenarr。varpreIndex,for(vari1;i){preIndexi1;currentarr〔i〕;while(preIndex0arr〔preIndex〕current){arr〔preIndex1〕arr〔preIndex〕;preI}arr〔preIndex1〕}}
  算法分析
  插入排序在实现上,通常采用inplace排序(即只需用到O(1)的额外空间的排序),因而在从后向前扫描过程中,需要反复把已排序元素逐步向后挪位,为最新元素提供插入空间。2。希尔排序
  1959年Shell发明,第一个突破O(n2)的排序算法,是简单插入排序的改进版。它与插入排序的不同之处在于,它会优先比较距离较远的元素。希尔排序又叫缩小增量排序。
  算法描述
  先将整个待排序的记录序列分割成为若干子序列分别进行直接插入排序,具体算法描述:选择一个增量序列t1,t2,,tk,其中titj,tk1;按增量序列个数k,对序列进行k趟排序;每趟排序,根据对应的增量ti,将待排序列分割成若干长度为m的子序列,分别对各子表进行直接插入排序。仅增量因子为1时,整个序列作为一个表来处理,表长度即为整个序列的长度。
  动图演示
  C代码实现functionshellSort(arr){varlenarr。for(vargapMath。floor(len2);gap0;gapMath。floor(gap2)){注意:这里和动图演示的不一样,动图是分组执行,实际操作是多个分组交替执行for(i){varcurrentarr〔i〕;while(jgap0currentarr〔jgap〕){arr〔j〕arr〔jgap〕;}arr〔j〕}}}
  算法分析
  希尔排序是基于插入排序的以下两点性质而提出改进方法的:插入排序在对几乎已经排好序的数据操作时,效率高,即可以达到线性排序的效率但插入排序一般来说是低效的,因为插入排序每次只能将数据移动一位
  时间复杂度:最坏情况下为O(n2),平均时间复杂度为O(nlogn);
  空间复杂度:归并排序需要一个大小为1的临时存储空间用以保存合并序列,所以空间复杂度为O(1);
  算法稳定性:从上面图片中可以看出,数字5在排序后交换了位置,所以它是不稳定的算法。3。选择排序(SelectionSort)
  选择排序(Selectionsort)是一种简单直观的排序算法。它的工作原理:首先在未排序序列中找到最小(大)元素,存放到排序序列的起始位置,然后,再从剩余未排序元素中继续寻找最小(大)元素,然后放到已排序序列的末尾。以此类推,直到所有元素均排序完毕。
  算法描述
  n个记录的直接选择排序可经过n1趟直接选择排序得到有序结果。具体算法描述如下:初始状态:无序区为R〔1n〕,有序区为空;第i趟排序(i1,2,3n1)开始时,当前有序区和无序区分别为R〔1i1〕和R(in)。该趟排序从当前无序区中选出关键字最小的记录R〔k〕,将它与无序区的第1个记录R交换,使R〔1i〕和R〔i1n)分别变为记录个数增加1个的新有序区和记录个数减少1个的新无序区;n1趟结束,数组有序化了。
  动图演示
  C语言实现functionselectionSort(arr){varlenarr。varminIndex,for(vari0;ilen1;i){minIfor(varji1;j){if(arr〔j〕arr〔minIndex〕){寻找最小的数minI将最小数的索引保存}}temparr〔i〕;arr〔i〕arr〔minIndex〕;arr〔minIndex〕}}
  算法分析
  表现最稳定的排序算法之一,因为无论什么数据进去都是O(n2)的时间复杂度,所以用到它的时候,数据规模越小越好。唯一的好处可能就是不占用额外的内存空间了吧。理论上讲,选择排序可能也是平时排序一般人想到的最多的排序方法了吧。4。堆排序
  堆排序(Heapsort)是指利用堆这种数据结构所设计的一种排序算法。堆积是一个近似完全二叉树的结构,并同时满足堆积的性质:即子结点的键值或索引总是小于(或者大于)它的父节点。
  算法描述将初始待排序关键字序列(R1,R2。Rn)构建成大顶堆,此堆为初始的无序区;将堆顶元素R〔1〕与最后一个元素R〔n〕交换,此时得到新的无序区(R1,R2,Rn1)和新的有序区(Rn),且满足R〔1,2n1〕R〔n〕;由于交换后新的堆顶R〔1〕可能违反堆的性质,因此需要对当前无序区(R1,R2,Rn1)调整为新堆,然后再次将R〔1〕与无序区最后一个元素交换,得到新的无序区(R1,R2。Rn2)和新的有序区(Rn1,Rn)。不断重复此过程直到有序区的元素个数为n1,则整个排序过程完成。
  动图演示
  代码实现:因为声明的多个函数都需要数据长度,所以把len设置成为全局变量functionbuildMaxHeap(arr){建立大顶堆lenarr。for(variMath。floor(len2);i0;i){heapify(arr,i);}}functionheapify(arr,i){堆调整varleft2i1,right2i2,if(leftlenarr〔left〕arr〔largest〕){}if(rightlenarr〔right〕arr〔largest〕){}if(largest!i){swap(arr,i,largest);heapify(arr,largest);}}functionswap(arr,i,j){vartemparr〔i〕;arr〔i〕arr〔j〕;arr〔j〕}functionheapSort(arr){buildMaxHeap(arr);for(variarr。length1;i0;i){swap(arr,0,i);heapify(arr,0);}}
  算法分析:
  堆排序是一种选择排序,整体主要由构建初始堆交换堆顶元素和末尾元素并重建堆两部分组成。其中构建初始堆经推导复杂度为O(n),在交换并重建堆的过程中,需交换n1次,而重建堆的过程中,根据完全二叉树的性质,〔log2(n1),log2(n2)1〕逐步递减,近似为nlogn。所以堆排序时间复杂度一般认为就是O(nlogn)级。5。冒泡排序
  冒泡排序是一种简单的排序算法。它重复地走访过要排序的数列,一次比较两个元素,如果它们的顺序错误就把它们交换过来。走访数列的工作是重复地进行直到没有再需要交换,也就是说该数列已经排序完成。这个算法的名字由来是因为越小的元素会经由交换慢慢浮到数列的顶端。
  算法描述比较相邻的元素。如果第一个比第二个大,就交换它们两个;对每一对相邻元素作同样的工作,从开始第一对到结尾的最后一对,这样在最后的元素应该会是最大的数;针对所有的元素重复以上的步骤,除了最后一个;重复步骤13,直到排序完成。
  动图演示
  C语言实现functionbubbleSort(arr){varlenarr。for(vari0;ilen1;i){for(varj0;jlen1i;j){if(arr〔j〕arr〔j1〕){相邻元素两两对比vartemparr〔j1〕;元素交换arr〔j1〕arr〔j〕;arr〔j〕}}}}
  算法分析
  若文件的初始状态是正序的,一趟扫描即可完成排序。所需的关键字比较次数C和记录移动次数M均达到最小值:CminN1,Mmin0。所以,冒泡排序最好时间复杂度为O(N)。
  若初始文件是反序的,需要进行N1趟排序。每趟排序要进行Ni次关键字的比较(1iN1),且每次比较都必须移动记录三次来达到交换记录位置。在这种情况下,比较和移动次数均达到最大值:
  CmaxN(N1)2O(N2)
  Mmax3N(N1)2O(N2)
  冒泡排序的最坏时间复杂度为O(N2)。因此,冒泡排序的平均时间复杂度为O(N2)。6。快速排序
  快速排序的基本思想:通过一趟排序将待排记录分隔成独立的两部分,其中一部分记录的关键字均比另一部分的关键字小,则可分别对这两部分记录继续进行排序,以达到整个序列有序。
  算法描述
  快速排序使用分治法来把一个串(list)分为两个子串(sublists)。具体算法描述如下:从数列中挑出一个元素,称为基准(pivot);重新排序数列,所有元素比基准值小的摆放在基准前面,所有元素比基准值大的摆在基准的后面(相同的数可以到任一边)。在这个分区退出之后,该基准就处于数列的中间位置。这个称为分区(partition)操作;递归地(recursive)把小于基准值元素的子数列和大于基准值元素的子数列排序。
  动图演示
  C语言实现functionquickSort(arr,left,right){varlenarr。length,partitionIndex,lefttypeofleft!number?0:left,righttypeofright!number?len1:if(leftright){partitionIndexpartition(arr,left,right);quickSort(arr,left,partitionIndex1);quickSort(arr,partitionIndex1,right);}}functionpartition(arr,left,right){分区操作varpivotleft,设定基准值(pivot)indexpivot1;for(i){if(arr〔i〕arr〔pivot〕){swap(arr,i,index);}}swap(arr,pivot,index1);returnindex1;}functionswap(arr,i,j){vartemparr〔i〕;arr〔i〕arr〔j〕;arr〔j〕}
  算法分析:
  当数据有序时,以第一个关键字为基准分为两个子序列,前一个子序列为空,此时执行效率最差。
  而当数据随机分布时,以第一个关键字为基准分为两个子序列,两个子序列的元素个数接近相等,此时执行效率最好。
  所以,数据越随机分布时,快速排序性能越好;数据越接近有序,快速排序性能越差。7。归并排序(MergeSort)
  归并排序是建立在归并操作上的一种有效的排序算法。该算法是采用分治法(DivideandConquer)的一个非常典型的应用。将已有序的子序列合并,得到完全有序的序列;即先使每个子序列有序,再使子序列段间有序。若将两个有序表合并成一个有序表,称为2路归并。
  算法描述把长度为n的输入序列分成两个长度为n2的子序列;对这两个子序列分别采用归并排序;将两个排序好的子序列合并成一个最终的排序序列。
  动图演示
  C语言实现functionmergeSort(arr){varlenarr。if(len2){}varmiddleMath。floor(len2),leftarr。slice(0,middle),rightarr。slice(middle);returnmerge(mergeSort(left),mergeSort(right));}functionmerge(left,right){varresult〔〕;while(left。length0right。length0){if(left〔0〕right〔0〕){result。push(left。shift());}else{result。push(right。shift());}}while(left。length)result。push(left。shift());while(right。length)result。push(right。shift());}
  算法分析
  归并排序是一种稳定的排序方法。和选择排序一样,归并排序的性能不受输入数据的影响,但表现比选择排序好的多,因为始终都是O(nlogn)的时间复杂度。代价是需要额外的内存空间。8。计数排序
  计数排序不是基于比较的排序算法,其核心在于将输入的数据值转化为键存储在额外开辟的数组空间中。作为一种线性时间复杂度的排序,计数排序要求输入的数据必须是有确定范围的整数。
  算法描述找出待排序的数组中最大和最小的元素;统计数组中每个值为i的元素出现的次数,存入数组C的第i项;对所有的计数累加(从C中的第一个元素开始,每一项和前一项相加);反向填充目标数组:将每个元素i放在新数组的第C(i)项,每放一个元素就将C(i)减去1。
  动图演示
  。
  C语言实现functioncountingSort(arr,maxValue){varbucketnewArray(maxValue1),sortedIndex0;arrLenarr。length,bucketLenmaxValue1;for(vari0;iarrLi){if(!bucket〔arr〔i〕〕){bucket〔arr〔i〕〕0;}bucket〔arr〔i〕〕;}for(varj0;jbucketLj){while(bucket〔j〕0){arr〔sortedIndex〕j;bucket〔j〕;}}}
  算法分析
  计数排序是一个稳定的排序算法。当输入的元素是n个0到k之间的整数时,时间复杂度是O(nk),空间复杂度也是O(nk),其排序速度快于任何比较排序算法。当k不是很大并且序列比较集中时,计数排序是一个很有效的排序算法。9。基数排序
  基数排序是按照低位先排序,然后收集;再按照高位排序,然后再收集;依次类推,直到最高位。有时候有些属性是有优先级顺序的,先按低优先级排序,再按高优先级排序。最后的次序就是高优先级高的在前,高优先级相同的低优先级高的在前。
  算法描述取得数组中的最大数,并取得位数;arr为原始数组,从最低位开始取每个位组成radix数组;对radix进行计数排序(利用计数排序适用于小范围数的特点);
  动图演示
  C语言实现varcounter〔〕;functionradixSort(arr,maxDigit){varmod10;vardev1;for(vari0;imaxDi,dev10,mod10){for(varj0;jarr。j){varbucketparseInt((arr〔j〕mod)dev);if(counter〔bucket〕null){counter〔bucket〕〔〕;}counter〔bucket〕。push(arr〔j〕);}varpos0;for(varj0;jcounter。j){if(counter〔j〕!null){while((valuecounter〔j〕。shift())!null){arr〔pos〕}}}}}
  算法分析
  基数排序基于分别排序,分别收集,所以是稳定的。但基数排序的性能比桶排序要略差,每一次关键字的桶分配都需要O(n)的时间复杂度,而且分配之后得到新的关键字序列又需要O(n)的时间复杂度。假如待排数据可以分为d个关键字,则基数排序的时间复杂度将是O(d2n),当然d要远远小于n,因此基本上还是线性级别的。
  基数排序的空间复杂度为O(nk),其中k为桶的数量。一般来说nk,因此额外空间需要大概n个左右。10。桶排序
  桶排序是计数排序的升级版。它利用了函数的映射关系,高效与否的关键就在于这个映射函数的确定。桶排序(Bucketsort)的工作的原理:假设输入数据服从均匀分布,将数据分到有限数量的桶里,每个桶再分别排序(有可能再使用别的排序算法或是以递归方式继续使用桶排序进行排)。
  算法描述设置一个定量的数组当作空桶;遍历输入数据,并且把数据一个一个放到对应的桶里去;对每个不是空的桶进行排序;从不是空的桶里把排好序的数据拼接起来。
  动图演示
  C语言实现functionbucketSort(arr,bucketSize){if(arr。length0){}varminValuearr〔0〕;varmaxValuearr〔0〕;for(i1;iarr。i){if(arr〔i〕minValue){minValuearr〔i〕;输入数据的最小值}elseif(arr〔i〕maxValue){maxValuearr〔i〕;输入数据的最大值}}桶的初始化varDEFAULTBUCKETSIZE5;设置桶的默认数量为5bucketSizebucketSizeDEFAULTBUCKETSIZE;varbucketCountMath。floor((maxValueminValue)bucketSize)1;varbucketsnewArray(bucketCount);for(i0;ibuckets。i){buckets〔i〕〔〕;}利用映射函数将数据分配到各个桶中for(i0;iarr。i){buckets〔Math。floor((arr〔i〕minValue)bucketSize)〕。push(arr〔i〕);}arr。length0;for(i0;ibuckets。i){insertionSort(buckets〔i〕);对每个桶进行排序,这里使用了插入排序for(varj0;jbuckets〔i〕。j){arr。push(buckets〔i〕〔j〕);}}}
  算法分析
  桶排序最好情况下使用线性时间O(n),桶排序的时间复杂度,取决与对各个桶之间数据进行排序的时间复杂度,因为其它部分的时间复杂度都为O(n)。很显然,桶划分的越小,各个桶之间的数据越少,排序所用的时间也会越少。但相应的空间消耗就会增大。(end)
  获取更多相关资料:请添加vx,ceshiren001
  https:qrcode。ceba。ceshiren。comlink?namearticleprojectidqrcodefromtoutiaotimestamp1653037966authorMM
投诉 评论 转载

吃猪皮能抗衰老?医生提醒抗衰老的食物是这4种,建议常吃导语:随着人们生活水平的不断提高,现如今人们早已经实现了吃饱穿暖的问题,就连衣食住行也得到了相应的保障,与此同时大家开始注重关于生命的质量,对于自己的皮肤、身材等方面的保养,也……一文搞定十大排序算法(动画图解)排序算法是测试开发技术面试中的常考题目,本文用动画图解面试必会十大排序算法,由浅入深、形象记忆,再也忘不掉。排序基础知识排序的定义排序,就是重新排列表中的元素,使表……王者后羿顶级玩法(三)前两篇介绍了职业选手华郴的后羿打法,本篇我们接着来说这一局的后续。后羿这个英雄开团成本很低,大招中了就开团,不中就等下一个大招,这可能是这个英雄强的一个……奥克兰一年下74吨微塑料雨,相当于300多万个塑料瓶从天而降过去70年里,耐用和抗降解的塑料生产增长量远远超过其他合成材料。塑料在分解后形成越来越小的颗粒,长度小于5毫米的颗粒被称为微塑料。12月2日,一项计算了一个城市空气中微塑……神十四乘组顺利进入梦天实验舱在北京航天飞行控制中心拍摄的空间站梦天实验舱完成转位的模拟图像11月3日在北京航天飞行控制中心拍摄的神舟十四号航天员陈冬进入梦天实验舱据中国载人航天工程办公室消息,……这才是成年人该发的朋友圈有些事知道就好,不必多说,有些人认识就好,不必深交你连自己都过不好,凭什么去操心别人?你未必出类拔萃,但一定要与众不同一个人在变得铁石心肠之前,也曾付出过全部的温柔和信任该放手……身体若有这8个症状,或是肝脏已经缠上你,需及时检查肝病指的是发生在肝脏的一种疾病,例如日常生活中比较常见的脂肪肝,肝炎,肝硬化等等。肝脏是人体的一个重要器官,一旦出现问题,对于身体的健康影响非常之大,因此在平日里我们一定……福报人生激励福报,福报他人和自己的激励都是最美的。我们不能替任何人做决定,但是我们能做好的正能量的激励。能激励别人就足够了,激励他人,让别人自助和自主行动。我们的激励能激励别人的内心,……刺客信条新作公布,中国背景秒变手游在今天的育碧预览会上,《刺客信条:幻景》正式公布,执行总监MarcAlexisCt在接受IGN采访时表示,该游戏主线时长在1520小时左右。据悉,原本是《英灵殿》的大型dlc,……中国乳业背后赢家外企抽走75利润,伊利蒙牛都为其打工小时候我们经常听父母说,要多喝牛奶,牛奶可以长身体,补充营养。事实上牛奶确实对我们的健康起着很重要的作用。比如牛奶可以提高机体免疫力,帮助我们尽快入睡,还能够促进消化。……日本今日正式开放入境游仅限旅行团入境人数限定2万日受新冠疫情影响,日本时隔2年再次开放日本入境游,今日将以旅行团的形式重新开放(自由行仍需等待)。但由于签证发放手续等原因,实际上游客访日的话,预计最少也要提前1个月时间筹备。……鞠婧祎厉害了,二分裤也能轻松驾驭,真实腿型一目了然鞠婧祎自出道以来,一直都饱受争议,先是被质疑整容,后又被批做作、不真实,甚至有一点时间可谓是人人喊打。但经过这些年她的大胆自黑和不错的业务能力,不少人都开始了黑转粉,毕竟……
儿童乳制品消费仍有巨大上升空间中国三大佛宫,一个比一个富丽堂皇,你去过吗?恭喜eStar获得挑战杯总冠军!FMVP揭晓,花落谁家?iPhone充电飘烤肉味打开背盖巨肥蛆虫蠕动IGN谈腾讯罗技掌机目标用户想给手机省电的玩家一杯茶的时间,带你看不一样的云南美元风暴下,这2国货币逆势而上一个升值2。5,一个飙涨7?又要卖国米?净赚80亿!苏宁模式果然是可以复制的黄雅莉晒行走的房子火了随走随停,岁月静好,网友太爽了原神无关萌新,当前版本最值得抽的角色有哪些?没有你就亏大了气大伤身,推荐一款解气茶你需要吃16种富含蛋白质的蔬菜来促进你的健康胡歌被造谣和杨幂结婚,谣言涉及多位女星,胡歌实名举报删帖?给46个月宝宝添加辅食的要点宽边造句用宽边造句大全初二日记雪花酥房屋抵押合同医师考试总结消化系统肝性脑病常考知识点。表达一个人忧郁的心情短句环境保护演讲稿三年级作文难忘的寒假生活200字夫妻小笑话兴趣是最好的老师豆瓣绿的养殖方法和注意事项选土和控温须注意

友情链接:中准网聚热点快百科快传网快生活快软网快好知文好找七猫云易事利