对排序的一点研究(选择排序,交换排序,插入排序)。望补充。
最近看了些排序的东西,感觉收获挺多,不过就是不全,希望大家看了之后说说自己的想法。
以下代码中,EleType是自定义的数据类型,这不是什么关键。
1、简单选择排序
思路:选择最小的数放在数组的前端。
代码如下:
程序代码:
void SelectSort(EleType a[],int n) //a[n]是要排序的最后一个数 { int i,j,min; EleType temp; for(i=0;i<n-1;i++) { min=i; for(j=i+1;j<n;j++) //找出最小的数字 if(a[j]<a[min]) min=j; if(min!=i) //如果min和i不等,就交换 { temp=a[min]; a[min]=a[i]; a[i]=temp; } } }代码很简单,理解起来也没什么难度。
2、直接插入排序
思路:把前面的序列作为已经排序好的序列,将未排序的数逐个插入到适当位置。
代码如下:
程序代码:
void InsertSort(EleType a[],int n) { int i,j; EleType Flag; //作为监视哨 for(i=1;i<=n;i++) { Flag=a[i]; //要插入的数赋值给Flag,作为监视哨 j=i-1; while(Flag<a[j])//寻找插入位置 { a[j+1]=a[j]; j--; } a[j+1]=Flag; //将原a[i]中的值存入第j+1个位置 } }
3、折半插入排序
思路:与直接插入排序的不同仅仅在于查找插入位置的方法不同,用折半查找的方法,
代码就不贴了。
4、希尔排序
思路:将要排序的数据分组,相隔为d的数据做一组,组内做直接插入排序,缩小d的值,
循环排序,直至结束。
代码如下:
程序代码:
void ShellSort(EleType a[],int n) { int i,j,d; EleType Flag; for(d=n/2;d>=1;d=d/2) { for(i=d;i<=n;i++) { Flag=a[i]; //监视哨 j=i-d; //j为同一组的i的前一个元素下标 while(j>=0 && Flag<a[j]) { a[j+d]=a[j]; //同一组内做简单插入 j=j-d; } a[j+d]=Flag; } } }希尔算法十分巧妙,效率也比较高。
5、冒泡排序
思路:比较相邻两数的大小,如果位置不对就交换,就像气泡像上冒一样。
代码如下:
程序代码:
void BubbleSort(EleType a[],int n) { int i,j,Last,flag,m,temp; Last=n-1; for(i=n;i>=2;i--) { flag=0; //标记设置为0 m=Last; //记录最后交换的位置 for(j=0;j<=m;j++) if(a[j]>a[j+1]) { temp=a[j]; a[j]=a[j+1]; a[j+1]=temp; flag=1; //如果发生过交换,置1 Last=j; //最后交换位置赋值给Last } if(flag == 0) break;//如果未发生交换,说明已排序完成,退出函数 } }这是我最早会的排序方法,最简单,但是效率比较低。
6、快速排序
思路:将temp数放置在正确位置,左边的数都比它小,右边的数都比它大,然后递归
调用进行再次排序,直至结束。
代码如下:
程序代码:
void QuickSort(EleType a[],int Left,int Right) { EleType temp; int i,j; i=Left;j=Right;temp=a[i]; //设置初始排序区 while(i<j) { while(temp <= a[j]) //从右侧开始扫描 j--; //找到第一个小于基准记录的数据 a[i]=a[j]; //覆盖 while(a[i]<=temp) //从左侧开始扫描 i++; //找到第一个大于基准记录的数据 a[j]=a[i]; //覆盖 } a[i]=temp; //找到正确位置 if(Left<i-1) QuickSort(a,Left,i-1); //判断是否需要再排序 if(i+1<Right) QuickSort(a,i+1,Right); }快速排序应该算是这些排序算法中效率最高的了。
用100个随机数据进行排序,比较移动次数和比较次数
直接插入 折半插入 希尔排序 冒泡排序 快速排序 简单选择
比较次数 2666 257 401 4950 622 4950
移动次数 2864 2864 1407 7581 398 270
上面的数据很直观的看出了各个排序方法的差距。
还有其他排序方法希望补充补充,或者有什么深入想法也说说。