C语言中的排序算法--冒泡排序,选择排序,希尔排序

冒泡排序Bubble Sort,台湾译为:泡沫排序气泡排序)是一种简单的排序算法。它重复地走访过要排序的数列,一次比较两个元素,如果他们的顺序错误就把他们交换过来。走访数列的工作是重复地进行直到没有再需要交换,也就是说该数列已经排序完成。这个算法的名字由来是因为越小的元素会经由交换慢慢“浮”到数列的顶端

维基百科:点击打开链接

 

[cpp] view plain copy
 
  1. /* 
  2. 用选择法对10个数进行排序 
  3. */  
  4. #include<stdio.h>  
  5. void main()  
  6. {  
  7.     int i,j,a[10];  
  8.     for(i=0;i<10;i++)  
  9.         scanf("%d",&a[i]);  
  10.   
  11.     for(i=0;i<9;i++)    
  12.         {//n个数要进行n-1趟比较  
  13.         for(j=0;j<=9-i;j++)          //每趟比较n-i次  
  14.             if(a[j]>a[j+1])          //依次比较两个相邻的数,将小数放在前面,大数放在后面  
  15.             {  
  16.                 int t=a[j];  
  17.                 a[j]=a[j+1];  
  18.                 a[j+1]=t;  
  19.             }  
  20.     }  
  21.   
  22.     for(i=0;i<10;++i)               //输出比较之后的数组  
  23.         printf(" %d",a[i]);  
  24. }  

 

另一种常见的写法

 

[cpp] view plain copy
 
  1. /* 
  2. 冒泡排序的另外一种写法 
  3. */  
  4. #include<stdio.h>  
  5. void BubbleSort(int a[],int n)  
  6. {  
  7.     int i,j;  
  8.     for(i=n-1;i>0;--i)          //从n-1循环的到0,也是n次  
  9.         for(j=0;j<i;j++)  
  10.             if(a[j]>a[j+1])  
  11.             {  
  12.                 int temp=a[j];  
  13.                 a[j]=a[j+1];  
  14.                 a[j+1]=temp;  
  15.             }  
  16.   
  17. }  
  18. void main()  
  19. {  
  20.     int a[10],i;  
  21.     for(i=0;i<10;i++)  
  22.         scanf("%d",&a[i]);  
  23.     BubbleSort(a,10);  
  24.     printf("排序后的数组:\n");  
  25.     for(i=0;i<10;i++)  
  26.         printf(" %d",a[i]);  
  27. }  

 

选择排序(Selection sort)是一种简单直观的排序算法。它的工作原理如下。首先在未排序序列中找到最小元素,存放到排序序列的起始位置,然后,再从剩余未排序元素中继续寻找最小元素,然后放到排序序列末尾(目前已被排序的序列)。以此类推,直到所有元素均排序完毕。

 

[cpp] view plain copy
 
  1. #include<stdio.h>    
  2. void SelectSort(int a[],int n)    
  3. {    
  4.     int i,j;    
  5.     for(i=0;i<n-1;i++)              //n个数要进行n-1趟比较,每次确定一个最小数放在a[i]中    
  6.     {    
  7.         int k=i;                    //假设a[0]是最小的数,把下标0放在变量K里面,    
  8.         for(j=i+1;j<n;j++)              
  9.             if(a[k]>a[j])  k=j;     //如果a[k]>a[j] 前面的数比后面的数大,交换下标,此时k指向小的数    
  10.         if(k!=i)    
  11.         {    
  12.             int temp=a[i];    
  13.             a[i]=a[k];    
  14.             a[k]=temp;    
  15.         }    
  16.     }    
  17.     
  18. }    
  19. void main()    
  20. {    
  21.     int a[10],i;    
  22.     for(i=0;i<10;i++)    
  23.         scanf("%d",&a[i]);    
  24.     SelectSort(a,10);    
  25.     printf("排序后的数组:\n");    
  26.     for(i=0;i<10;i++)    
  27.         printf(" %d",a[i]);    
  28. }    

 

 

希尔排序通过将比较的全部元素分为几个区域来提升插入排序的性能。这样可以让一个元素可以一次性地朝最终位置前进一大步。然后算法再取越来越小的步长进行排序,算法的最后一步就是普通的插入排序,但是到了这步,需排序的数据几乎是已排好的了(此时插入排序较快)。

假设有一个很小的数据在一个已按升序排好序的数组的末端。如果用复杂度为O(n2)的排序(冒泡排序或插入排序),可能会进行n次的比较和交换才能将该数据移至正确位置。而希尔排序会用较大的步长移动数据,所以小数据只需进行少数比较和交换即可到正确位置。

一个更好理解的希尔排序实现:将数组列在一个表中并对列排序(用插入排序)。重复这过程,不过每次用更长的列来进行。最后整个表就只有一列了。将数组转换至表是为了更好地理解这算法,算法本身仅仅对原数组进行排序(通过增加索引的步长,例如是用i += step_size而不是i++)。

例如,假设有这样一组数[ 13 14 94 33 82 25 59 94 65 23 45 27 73 25 39 10 ],如果我们以步长为5开始进行排序,我们可以通过将这列表放在有5列的表中来更好地描述算法,这样他们就应该看起来是这样:

13 14 94 33 82
25 59 94 65 23
45 27 73 25 39
10

然后我们对每列进行排序:

10 14 73 25 23
13 27 94 33 39
25 59 94 65 82
45

当我们以单行来读取数据时我们得到:[ 10 14 73 25 23 13 27 94 33 39 25 59 94 65 82 45 ].这时10已经移至正确位置了,然后再以3为步长进行排序:

10 14 73
25 23 13
27 94 33
39 25 59
94 65 82
45

排序之后变为:

10 14 13
25 23 33
27 25 59
39 65 73
45 94 82
94

最后以1步长进行排序(此时就是简单的插入排序了)。

[cpp] view plain copy
 
  1. //希尔排序  
  2. #include<stdio.h>  
  3. #define LT(a,b) ((a)<(b))  
  4. #define MAX_SIZE 20  
  5. #define T 3      
  6. #define N 10  
  7. typedef int KeyType;  
  8. typedef int InfoType;  
  9.   
  10. typedef struct   
  11. {  
  12.     KeyType key;  
  13.     InfoType otherinfo;  
  14. }RedType;  
  15.   
  16. typedef struct   
  17. {  
  18.     RedType r[MAX_SIZE+1];  
  19.     int length;  
  20.   
  21. }SqList;  
  22. void PrintSqList(SqList L)  
  23. {  
  24.     int i;  
  25.     for(i=1;i<L.length;i++)  
  26.     {  
  27.         printf("(%d %d)",L.r[i].key,L.r[i].otherinfo);  
  28.     }  
  29.     printf("\n");  
  30. }  
  31. int   PrintSqlListKey(SqList L)  
  32. {  
  33.     int i;  
  34.     for(i=1;i<L.length;i++)  
  35.     {  
  36.         printf("%d ",L.r[i].key);  
  37.     }  
  38.     printf("\n");  
  39.     return 0;  
  40. }  
  41. void ShellInsert(SqList &L,int dk)  
  42. {  
  43.     int i,j;  
  44.     for(i=dk+1;i<=L.length;i++)  
  45.     {  
  46.         if LT(L.r[i].key,L.r[i-dk].key)  
  47.         {  
  48.             L.r[0]=L.r[i];  
  49.             for(j=i-dk;j<0&& LT(L.r[i].key,L.r[j].key);j-=dk)  
  50.             {  
  51.                 L.r[j+dk]=L.r[j];  
  52.             }  
  53.             L.r[j+dk]=L.r[0];  
  54.         }  
  55.     }  
  56.   
  57. }  
  58. void ShellSort(SqList &L,int dlta[],int t)  
  59. {  
  60.     int k;  
  61.     for(k=0;k<t;k++)                                  //对所有增量序列  
  62.     {  
  63.         ShellInsert(L,dlta[k]);  
  64.          printf("dlta[%d]=%d,第%d趟排序结果(仅输出关键字):",k,dlta[k],k+1);  
  65.   
  66.         PrintSqlListKey(L);  
  67.   
  68.     }  
  69.   
  70. }  
  71. void main()  
  72. {  
  73.     RedType d[N]={{49,1},{38,2},{65,3},{97,4},{76,65},{13,6},{27,7},{49,8},{55,9},{4,10}};  
  74.     SqList m;  
  75.     int i,dt[T]={5,3,1};  
  76.     for(i=0;i<N;i++)  
  77.     {  
  78.         m.r[i+1]=d[i];  
  79.     }  
  80.     m.length=N;  
  81.     printf("希尔排序前:\n");  
  82.     PrintSqList(m);  
  83.     printf("\n");  
  84.     ShellSort(m,dt,T);  
  85.     printf("希尔排序后:\n");  
  86.     PrintSqList(m);  
  87.     printf("\n");  
  88.   
  89. }  

posted on 2016-01-23 23:10  张鱼  阅读(799)  评论(0编辑  收藏  举报

导航