梳排序(Comb sort)
2016-01-21 12:09
190 查看
梳排序(Comb sort)是一种由Wlodzimierz Dobosiewicz于1980年所发明的不稳定排序算法,并由Stephen Lacey和Richard Box于1991年四月号的Byte杂志中推广。梳排序是改良自泡沫排序和快速排序,其要旨在于消除乌龟,亦即在阵列尾部的小数值,这些数值是造成泡沫排序缓慢的主因。相对地,兔子,亦即在阵列前端的大数值,不影响泡沫排序的效能。
在泡沫排序中,只比较阵列中相邻的二项,即比较的二项的间距(Gap)是1,梳排序提出此间距其实可大于1,改自插入排序的希尔排序同样提出相同观点。梳排序中,开始时的间距设定为阵列长度,并在循环中以固定比率递减,通常递减率设定为1.3。在一次循环中,梳排序如同泡沫排序一样把阵列从首到尾扫描一次,比较及交换两项,不同的是两项的间距不固定于1。如果间距递减至1,梳排序假定输入阵列大致排序好,并以泡沫排序作最后检查及修正。
假设待数组[8 4 3 7 6 5 2 1]
待排数组长度为8,而8÷1.3=6,则比较8和2,4和1,并做交换
[8 4 3 7 6 5 2 1]
[8 4 3 7 6 5 2 1]
交换后的结果为
[2 1 3 7 6 5 8 4]
第二次循环,更新间距为6÷1.3=4,比较2和6,1和5,3和8,7和4
[2 1 3 7 6 5 8 4]
[2 1 3 7 6 5 8 4]
[2 1 3 7 6 5 8 4]
[2 1 3 7 6 5 8 4]
只有7和4需要交换,交换后的结果为
[2 1 3 4 6 5 8 7]
第三次循环,更新距离为3,没有交换
第四次循环,更新距离为2,没有交换
第五次循环,更新距离为1,三处交换
[2 1 3 4 6 5 8 7]
[2 1 3 4 6 5 8 7]
[2 1 3 4 6 5 8 7]
三处交换后的结果为[1 2 3 4 5 6 7 8]
交换后排序结束,顺序输出即可得到[1 2 3 4 5 6 7 8]
如同快速排序和合并排序,梳排序的效率在开始时最佳,接近结束时,即进入泡沫排序时最差。如果间距变得太小时(例如小于10),改用诸如插入排序或鸡尾酒排序等算法,则可提升整体效能。
此方法的最大好处是不再需要检查有否进行过交换程序以将排序循环提早结束。
在泡沫排序中,只比较阵列中相邻的二项,即比较的二项的间距(Gap)是1,梳排序提出此间距其实可大于1,改自插入排序的希尔排序同样提出相同观点。梳排序中,开始时的间距设定为阵列长度,并在循环中以固定比率递减,通常递减率设定为1.3。在一次循环中,梳排序如同泡沫排序一样把阵列从首到尾扫描一次,比较及交换两项,不同的是两项的间距不固定于1。如果间距递减至1,梳排序假定输入阵列大致排序好,并以泡沫排序作最后检查及修正。
假设待数组[8 4 3 7 6 5 2 1]
待排数组长度为8,而8÷1.3=6,则比较8和2,4和1,并做交换
[8 4 3 7 6 5 2 1]
[8 4 3 7 6 5 2 1]
交换后的结果为
[2 1 3 7 6 5 8 4]
第二次循环,更新间距为6÷1.3=4,比较2和6,1和5,3和8,7和4
[2 1 3 7 6 5 8 4]
[2 1 3 7 6 5 8 4]
[2 1 3 7 6 5 8 4]
[2 1 3 7 6 5 8 4]
只有7和4需要交换,交换后的结果为
[2 1 3 4 6 5 8 7]
第三次循环,更新距离为3,没有交换
第四次循环,更新距离为2,没有交换
第五次循环,更新距离为1,三处交换
[2 1 3 4 6 5 8 7]
[2 1 3 4 6 5 8 7]
[2 1 3 4 6 5 8 7]
三处交换后的结果为[1 2 3 4 5 6 7 8]
交换后排序结束,顺序输出即可得到[1 2 3 4 5 6 7 8]
#include <iostream> #include <time.h> using namespace std; void combsort(int *arr, int size) { double shrink_factor = 1.247330950103979; int gap = size; int swapped = 1; int swap; int i; while ((gap > 1) || swapped) { if (gap > 1) { gap = gap / shrink_factor; } swapped = 0; i = 0; while ((gap + i) < size) { if(arr[i]-arr[i+gap] > 0) { swap = arr[i]; arr[i] = arr[i+gap]; arr[i+gap] = swap; swapped = 1; } ++i; } } } void print(int a[],int n) { for(int i=0; i<n; i++) { cout<<a[i]<<" "; } cout << endl; } void main() { int a[10]; srand((unsigned)time(NULL));//初始化随机数 for(int i=0; i<10; i++) { a[i]=rand()%20; } cout << "排序前:"; print(a,sizeof(a)/sizeof(a[0])); int n=sizeof(a)/sizeof(a[0]); combsort(a,n); cout << "排序后:"; print(a,sizeof(a)/sizeof(a[0])); }
递减率的设定影响着梳排序的效率,原作者以随机数作实验,得到最有效递减率为1.3的。如果此比率太小,则导致一循环中有过多的比较,如果比率太大,则未能有效消除阵列中的乌龟。亦有人提议用
混合梳排序和其他
如同快速排序和合并排序,梳排序的效率在开始时最佳,接近结束时,即进入泡沫排序时最差。如果间距变得太小时(例如小于10),改用诸如插入排序或鸡尾酒排序等算法,则可提升整体效能。此方法的最大好处是不再需要检查有否进行过交换程序以将排序循环提早结束。
相关文章推荐
- pyhton 数据结构二
- 编写高质量代码–改善python程序的建议(二)
- DSL简介
- ※回顾※关于阅读TCPIP等源码时遇到的:do while(0) 用法
- jenkins 入门教程(下)
- 解析json数组——TypeToken
- 手机APP测试之ADB常见问题解决方法
- svn 合并的问题
- Android Studio Application Test详解
- asp.net缓存
- centos 下安装tomcat-native
- angular点滴,界面上ng-model绑定的值和scope中的值不一致
- 如何用CSS3+HTML5绘制一个3x3的3D魔方?
- java中queue的使用
- Spring3 MVC 拦截器拦截不到的问题
- 让你提前认识软件开发(50):软件需求
- TNews
- 图解Public,protected ,private和什么也不填的区别
- 抽象类与接口
- Android -下拉刷新,ViewPager和ScrollView嵌套滚动问题解决方案