常见比较排序算法的耗时测试

一直知道插入排序在输入规模比较小时会有比较好的效率,但这个输入规模多少才算少却无从知晓,今天特意写了几个小程序分别测试了几种排序算法随输入规模增长的耗时情况。

测试环境

CPU 3.0GHz 双核  1G内存   centos虚拟机 g++ 4.9.1

预先构造100W个随机生成的整数数组,计算使用各种排序算法时的总耗时

插入排序  vs  冒泡排序

不出所料,插入排序基本在任何输入规模均优于冒泡排序。

插入排序  vs 快速排序 vs 归并排序

由下图可以看出,在输入规模小于100时,插入排序要好于归并和快速排序。在输入规模小于200时,插入排序优于归并排序。在输入规模在30以下时,插入排序效率要比快速排序高50%以上,在输入规模在50以下时,插入排序比归并排序效率高90%以上。

快速排序  vs std::sort

std::sort要比普通的快排速度快25%左右,简单阅读了一下stl的代码,std::sort的基本流程如下:

1.取begin,end,mid的中位数,将序列分割为两部分

2.1若子序列长度大于16,对子序列执行1

2.2若递归层数超出lg(n),对子序列执行堆排序 //递归层数太深,一般出现在拆分分布极不均匀的情况

3.对序列执行插入排序

在std::sort的实现中,stl选择了16作为阀值,小于此值的子序列将采用插入排序进行优化,但根据在插入排序和快速排序的对比实验中,输入规模<100时插入排序总是优于快速排序,在30以下的时候尤其如此。stl为什么会选择16作为阀值呢?针对这个问题,做了一个小实验,将阀值作为参数加入快速排序中,针对10W个大小为2K的数组进行排序,得出排序效率与阀值之间的对应曲线:

从上图可以看出,在阀值15~100之间时,修改的快速排序要优于std::sort,在30~50左右时更是达到峰值。既然如此,std::sort为何要选择16作为阀值呢?

STL的作者肯定不会胡乱写个数字上去,对比了快排和插入排序的代码后,初步猜测可能是跟他们之间的对数据的比较和复制的次数有关。

下图是在不同的输入规模时插入排序与选择排序的比较次数之比(快速排序swap操作当作3个复制操作计算)、复制次数之比与时间效率之比,可以看出随着输入规模的增长,插入排序相比快速排序的效率优势在逐渐降低,而比较、移动次数却在呈指数级快速增长。对于一些自定义类型而言,他们的比较、复制操作的耗时往往是整数的数倍之多,对于以通用性为目标的std::sort而言,选择16作为阀值或许是一种中庸的选择。而在我们自己开发排序算法时,可以根据输入数据的性质灵活选择插入阀值,对于一些简单的数据结构可以选择相对较大的阀值(如30~50),而对于一些相对复杂的数据结构,则需要选择相对较小的阀值。

归并排序 vs std::stable_sort

std::stable_sort要比递归实现的归并排序效率高50%左右,这主要是由于:

1.stable_sort首先将输入序列以7个元素为单位分成若干小组,每小组内进行插入排序

2.合并插入排序构成的有序序列时,通过mergeto(A,B,step) && mergeto(B,A,step*2)的方式减少了一定的数据拷贝

std::sort  vs  std::stable_sort

在输入规模较小时(<30),sort要比stable_sort效率高30%左右,这可能是由于在规模较小时sort可以更充分的利用插入排序带来的性能提升。

随着输入规模的增长,sort与stable_sort之间的差距逐渐缩小,大约在5%左右。

常见比较排序算法的耗时测试

时间: 2024-10-03 01:29:08

常见比较排序算法的耗时测试的相关文章

常见比较排序算法的比较

几种常见的排序算法之比较 排序的基本概念以及其算法的种类,介绍几种常见的排序算法的算法:冒泡排序.选择排序.插入排序.归并排序.快速排序.希尔排序的算法和分析它们各自的复杂度,然后以表格的形式,清晰直观的表现出它们的复杂度的不同.在研究学习了之前几种排序算法的基础上,讨论发现一种新的排序算法,并通过了进一步的探索,找到了新的排序算法较之前几种算法的优势与不足. 排序算法,是计算机编程中的一个常见问题.在日常的数据处理中,面对纷繁的数据,我们也许有成百上千种要求,因此只有当数据经过恰当的排序后,才

Python全栈开发之5、几种常见的排序算法以及collections模块提供的数据结构

在面试中,经常会遇到一些考排序算法的题,在这里,我就简单了列举了几种最常见的排序算法供大家学习,说不定以后哪天面试正好用上,文章后半段则介绍一下collections模块,因为这个模块相对于python提供的基本数据结构(list,tuple,dict)不被人们所熟悉,但是如果你对他们了解的话,用起来也是非常方便高效的. 排序算法 一.冒泡排序(BubbleSort) 步骤: 比较相邻的元素,如果第一个比第二个大,就交换他们两个. 循环一遍后,最大的数就“浮”到了列表最后的位置. 将剩下的数再次

常见的排序算法--java版

个人总结的常见的排序算法 public class Sort { // 1.冒泡:稳定,最优O(n) 最差O(n^2) 平均O(n^2) private static void sort1(int[] arr) { for (int i = 0; i < arr.length; i++) { for (int j = 0; j < arr.length - 1; j++) { if (arr[j] > arr[j + 1]) { int tmp = arr[j]; arr[j] = ar

【转帖】常见的排序算法

常见的排序算法 总结一下常见的排序算法. 排序分内排序和外排序.内排序:指在排序期间数据对象全部存放在内存的排序.外排序:指在排序期间全部对象个数太多,不能同时存放在内存,必须根据排序过程的要求,不断在内.外存之间移动的排序.内排序的方法有许多种,按所用策略不同,可归纳为五类:插入排序.选择排序.交换排序.归并排序.分配排序和计数排序.插入排序主要包括直接插入排序,折半插入排序和希尔排序两种;选择排序主要包括直接选择排序和堆排序;交换排序主要包括冒泡排序和快速排序;归并排序主要包括二路归并(常用

七种常见经典排序算法总结(C++)

最近想复习下C++,很久没怎么用了,毕业时的一些经典排序算法也忘差不多了,所以刚好一起再学习一遍. 除了冒泡.插入.选择这几个复杂度O(n^2)的基本排序算法,希尔.归并.快速.堆排序,多多少少还有些晦涩难懂,幸好又博客园大神dreamcatcher-cx都总结成了图解,一步步很详细,十分感谢. 而且就时间复杂度来说,这几种算法到底有什么区别呢,刚好做了下测试. 代码参考: http://yansu.org/2015/09/07/sort-algorithms.html //: basic_so

java几种常见的排序算法总结

[java] view plain copy /*************几种常见的排序算法总结***************************/ package paixu; public class PaiXu { final int MAX=20; int num[]=new int[MAX]; { System.out.print("生成的随机数组是:"); for(int i=0;i<20;i++){ num[i]=(int)(Math.random()*100)

数据结构之常见的排序算法c语言实现

常见的简单排序算法有冒泡排序.选择排序.插入排序.快排.堆排序.归并排序.希尔排序等,这些排序的理论在网上有很多,这就只给出常见的排序算法源码,上学时候写的,不足之处欢迎大家指正. 下面几种排序的主函数入口为:     int main(int argc, char* argv[])         {      int i, len;      int a[] = {8,5,6,4,9,10,3,15,2,17};           len = (sizeof(a) / sizeof(a[0

常见的排序算法

描述: 排序算法可谓数据结构模块中的重中之重,常见的哈希表,二叉树,搜索树/平衡树,位图等数据结构只是处理实际问题的抽象方法,实际在处理接受或生成的数据集时,排序算法显得尤其重要,排序算法家族很庞大,其中包括了冒泡排序,选择排序,插入排序,堆排序,快速排序,归并排序,基数排序,计数排序,希尔排序,箱排序,树型排序等众多算法,每种排序都有各自的特性,没有好坏之分,只有在特定的场景使用合适的排序算法才是上策,单纯的来比显得太过绝对,没有可比性.因为实际需求及各方面条件的限制使得排序算法的可选范围往往

用Java来写常见的排序算法

随着校招的临近 算法是校招中很重要的一个部分 总结了常见几种排序算法,各种算法的时间复杂度和空间复杂度大家也需要多了解下 package com.huwei.sort; /** * 各种排序算法 * * @author huwei * */ public class Sort { public static void main(String[] args) { int[] a = { 60, 57, 89, 47, 57, 98, 45, 35, 73 }; Sort sort = new So