选择排序,插入排序,插入排序(移位),冒泡排序,希尔排序(移位)的C++实现及性能测试
选择排序:
1 | /* |
插入排序
1 | /* |
冒泡排序
1 | /* |
希尔排序-移位
1 | /* |
排序工具class.h
1 | /* |
测试-主函数
1 | /* |
测试结果
1 | 随机数组长度为==》20000 |
总结:
选择排序:取得外循环的被选择的元素的下标,然后将该元素与右侧所有元素依次比较大小,如右侧元素小于取得下标的元素,则将下表赋值为较小元素的下标,直至到数列最后一个元素停止内层循环,
特点:
1.外循环被选中的元素的左侧的元素总是排好序的而且是最终所在的位置。
2.换位操作在外循环中实现,比插入排序在内层循环中换位性能要好。
3.对乱序,中度有序,接近有序的排序的耗时稳定在O($N^2$)级别
插入排序:取得外层循环中的元素,将其与其左侧元素做比较,如果左侧元素较大,则将当前元素与左侧元素换位。
特点:
1.当前元素的左侧元素总是有序的,因此,如果当前元素比其左侧元素大时,可以直接终止内层循环。这使得插入排序对接近有序的数列的排序耗时接近O(N),也就是说插入排序在特定的,有序性较强的数列排序时比选择排序耗时更短。
2.换位操作发生在内层循环,换位耗时较长,因此衍生出改进型的插入排序:插入排序-移位
插入排序-移位:选择在内存里保存一份外层循环(外循环下标从1开始,即从第二个元素开始)的需要插入的元素(记为C)的副本(记为T),然后将该元素的副本T逐次地与其左侧元素做比较,如果左侧元素较大,则将左侧元素(记为L)与L右侧的元素移位(即L的位置空出,L+1的位置赋值成L,因为C的值已被复制成副本T,所以C的位置可以被其左侧的元素的值覆盖),直至没有元素比T大时,将空置的位置下标的元素赋值成T。
特点:
1.内层循环中由换位操作(开辟新内存,三次赋值操作)改良为赋值操作(移位操作),外层每次循环也仅有一次赋值操作。与选择排序相比,既保留了对接近有序数列排列耗时的优势,又在对无序数列排序时获得较好的性能优势。
2.仍然存在数列中的较小的值在数列右侧远端,需要逐次移位其左侧所有元素的操作。而希尔排序则为解决此类问题作出进一步的优化。
希尔排序:采用特定的数列作为步进数列,将待排序数列(记为arr)按照步进数列的每次取得的值(记为n)做切分。必须注意到,数列总能将下标按照n的步进切分成n个数列。于是,可以将arr按照被切分的数列,按照每次步进n进行插入排序(可以选用插入排序-移位做进一步的优化)。对同一步进的所有数列做插入排序,意味着,在程序上,就是从步进n开始到arr最右侧元素终止,做步进是n的插入排序操作。
特点:
1.采用步进数列,解决了arr数列右侧远端是较小值的逐次比较的问题,改良为按照步进大小进行n位移的大跨步的调整。
2.如果采用3n+1的步进数列,在arr数量级较小的情况下,相对归并,快速排序,代码实现起来较为简单,但能获得相近的性能。