八种常用的排序方法
1.插入排序——直接插入排序(Straight Insertion Sort)
算法:
将一个无序的数组,以第一个记录作为有序,然后进行排序。(在这里就以升叙为例子)设有i个记录是一个有序的数列,则从i+1个记录如果大于i个记录就继续,如果小于的话就往前继续比较直至发现一个比它小的,在此之前的记录向前移一位。(这个道理就像打扑克牌时摸牌排序一样。)
代码实现:
#include <stdio.h>
int Insertsort(int n,int a[])
{
int x,i,j;
for(i=1;i<n;i++){
x=a[i]; //把要排序的一个记录赋值给x
j=i-1;
while(x<a[j]&&j>=0){a[j+1]=a[j];j--;}
/*找到一个小于等于它的记录,并且把此前的记录向前移动一位。
注意j>=0要写,防止数组溢出*/
a[j+1]=x; //把x插入到这个记录的右边
}
}
int main()
{
int n;
while(~scanf("%d",&n))
//在这里使用的是多组输入,首先输入记录的个数,再输入记录
{
int i,a[n];
for(i=0;i<n;i++){
scanf("%d",&a[i]);
}
Insertsort(n,a);
for(i=0;i<n;i++){
printf("%d ",a[i]);
}
printf("\n");
}
return 0;
}
2.插入排序——希尔排序(Shell`s Sort)
希尔排序(Shell Sort)是插入排序的一种。因D.L.Shell于1959年提出而得名。
算法:
先取一个小于n的整数k1作为第一个增量,把文件的全部记录分成k1个组。所有距离为kl的倍数的记录放在同一个组中。先在各组内进行直接插人排序;然后,取第二个增量k2 < k1重复上述的分组和排序,直至所取的增量kt=1(kt < kt-l < … < k2 < k1),即所有记录放在同一组中进行直接插入排序为止。该方法实质上是一种分组插入方法。
算法分析:
1、Shell排序的执行时间要依赖于增量序列的多少,增量序列的选取有很多种,在这里我们用的减半的方式,但所有种类都要保证最后一个增量为1。
2、虽然希尔排序是进行多次的直接插入排序,但是希尔排序的时间性能是优于直接插入排序的。
①当数组初态是有一定顺序时,此时记录移动较少的次数。
②当n比较小的时候,直接排序的复杂度的最好最坏时间差别不大。
③当n比较大时,即增量比较大,分组比较多,当增量比较小时数组也接近有序,所以排序较快。
3、希尔排序是不稳定的
代码实现:
#include <stdio.h>
int Shell_InsertSort(int a[], int n, int dk)
{
int x,i,j;
for(i=dk;i<n;i++){
j = i-dk;
x = a[i];
while(x < a[j]&&j>=0){a[j+dk] = a[j];j -= dk;}
a[j+dk] = x;
}
}
//这里不在进行过多的解释,利用的就是直接插入排序。
int Shellsort(int a[], int n){
int dk = n/2;
while( dk >= 1 ){
Shell_InsertSort(a, n, dk);
dk = dk/2;
}
}
//每次的增量除以二,直到增量为一
int main()
{
int n;
while(~scanf("%d",&n))
{
int i,a[n];
for(i=0;i<n;i++){
scanf("%d",&a[i]);
}
Shellsort(a,n);
for(i=0;i<n;i++){
printf("%d ",a[i]);
}
printf("\n");
}
return 0;
}
3.交换排序——冒泡排序
冒泡排序也是我学习排序时学习的第一种排序,这种排序就像排气泡一样,比较两个气泡的大小,根据气泡的大小来排序,只要发现有违背一定规则的气泡,就改变气泡的位置,如此反复,即可排好顺序。
算法:
对于一组无序数组,进行多次扫描(我们依旧是做升序)。
第1次扫描:通过两两比较,交换位置找出最大的气泡,并让他沉到最下面(即将此记录放到最右边)。
第2次扫描:找出“次重”的气泡,让他沉到最大气泡的上面
……
……
第n-1次扫描:经过重新的排序,此时数组成为一个升序数组了。
冒泡排序其实就是将记录从大到小依次找出,每找出一个记录就将其排出顺序。
代码实现:
#include <stdio.h>
int Bubblesort(int n,int a[])
{
int i,j,tmp;
for(i=n-2;i>=0;i--){ //注意:这里i要从n-2开始取值,n-2到0为n-1次扫描
for(j=0;j<=i;j++){ //之所以从n-2开始是因为如果j=i,要注意j+1不能越界
if(a[j]>a[j+1]){tmp=a[j];a[j]=a[j+1];a[j+1]=tmp;}
//利用中间值tmp将两个记录交换
}
}
}
/*在我开始使用冒泡排序时,我经常犯得一个错误就是数组越界,所以一定要注意进行第一次时数组是否越界*/
int main()
{
int n;
while(~scanf("%d",&n))
{
int a[n],i;
for(i=0;i<n;i++){
scanf("%d",&a[i]);
}
Bubblesort(n,a);
for(i=0;i<n;i++){
printf("%d ",a[i]);
}
printf("\n");
}
return 0;
}