十大排序算法

排序规则:从左至右依次增大

一、基于比较的排序算法:

插入排序:逐个遍历未排序序列,将其在已排序序列中从右到左比较,直到遇到比自己小的数,然后将元素插入到那个数的后面,有序序列从左向右生长。

选择排序:在未排序序列中选择最小的元素,将其插入到已排序序列的末尾,有序序列从左向右生长。

冒泡排序:从左至右逐个比较相邻的两个元素,如果左边的元素比右边的大,则交换两个元素位置,继续向右比较;如果左边的元素比右边的元素小,则继续比较右边的元素和右边的右边的元素,直到最大的数到达序列的最右端,与上面两种方法不同,有序序列是从右向左生长。

以上是最容易想到的三种排序算法,平均时间复杂度为O\left ( n^{2}\right )下面是不容易想到的排序算法。

希尔排序:是改进的插入排序,首先需要将未排序序列分成几段,比如将长度为n的序列分为m段,每段长度为n/m。应该如何比较呢,是相邻的段之间进行比较,段与段之间又是如何比较呢,是每段的同样序号的元素进行比较,比如第i段的第2号元素和第i+1段段第2号元素进行比较,如果后者比前者小,就交换两个元素的位置。当相邻的段都比较完了以后,就是使得第i段元素都要比第i+1段对应位置的元素要小,得到了一个大致的排序。接着将段的长度缩短,使得比较的单位进一步缩小,这样比较完了以后就得到了段粒度更小的有序序列,接着进一步缩小段长度,直到段长度变为1,此时排序工作已经进行的差不多了,再进行插入排序的时候需要进行的交换工作就少了很多。这个算法像是冒泡排序和插入排序的混合版,算法的平均复杂度为O\left ( n^{1.3}\right )

归并排序:采用分治法的思想,将一个无序序列分为两段,再递归地一直分下去,直到分到只剩下两个元素,然后将这两个元素排序存好,递归地操作,将排好序的两对元素合并为有序的四个元素,将两对四个元素合并为有序的八个元素依次进行下去,最开始均分的两组元素合并为一组有序元素,这一算法的平均时间复杂度为O\left ( n{log_{2}}^{n}\right )

快速排序:快速排序也是采用递归的思想,首先在无序序列中寻找一个基准,然后将元素分为两组,一组所有元素都比基准小,一组所有元素都比基准大,然后递归地对这两组元素采用同样的处理方式,最后就会得到一个有序的序列,这一算法的平均时间复杂度为O\left ( n{log_{2}}^{n}\right )

堆排序:此法是利用大小堆的性质来进行排序,即父元素总是大于等于子元素,或者总是小于等于子元素。假如使用大堆结构,则每次将堆顶元素和堆底元素(底层最右侧元素)交换,然后剥离堆底元素,或则序列最大值,然后将堆进行调整使其符合大堆的性质,重复上述操作,有序序列是从右向左生长的,这一算法的平均时间复杂度为O\left ( n{log_{2}}^{n}\right )

上述算法都是基于比较多排序算法,无法突破时间复杂度O\left ( n{log_{2}}^{n}\right )的下限,下面介绍非基于比较多排序算法,它们可以达到线性的时间复杂度。

二、非基于比较的排序算法:

计数排序:此法有一定局限性,适用于序列最大最小值相差不多并且元素为整数的情况,它需要一个 max-min+1长度的数组作为存储计数空间。然后将大小为i的元素存放在索引为i的位置,如果没有大小为i的元素,则该位置的值为0,如果有m个元素都为i,则该元素的大小为m。所有元素放好以后,再根据数组中元素的个数纪录,逐个将元素回填,比如有0个元素,则不用输出,如果有m个元素,则连续输出m个元素,最后得到的就是有序序列。

桶排序:这个类似于哈希表,也就是电话薄原理。当每次存入一个电话的时候,电话薄会根据名字将其添加到对应的索引下,索引就是ABCDEF... 也就是名字的首字母,这相当于是一个个大桶,相同首字母的名字都被映射到一个索引下,然后桶内的名字再按照第二个字母的顺序来排序,整个电话薄按照索引排序,然后所有名字就这样有序地排列好了。

基数排序:序列中的元素可以由权重不同的关键字组成,比如数字由个位十位百位组成,然后分别对每一位使用计数排序。比如个位为6的分为一组,个位为7的紧邻其后。分好之后,开始按照十位数字分组,此时原先在同一组的数字可能由于十位不同而分在了不同的组,形成新的排序,然后按照放入顺序依次回填,就会得到按照个位十位排序的有序序列。算法的关键在于迭代地使用计数排序。

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章