所谓排序,就是使一串记录,按照其中的某个或某些关键字的大小,递增或递减的排列起来的操作。
一 选择排序
选择排序很简单,他的步骤如下:
- 从左至右遍历,找到最小(大)的元素,然后与第一个元素交换。
- 从剩余未排序元素中继续寻找最小(大)元素,然后与第二个元素进行交换。
- 以此类推,直到所有元素均排序完毕。
#include<stdio.h>
#include<stdlib.h>
typedef int Item;
#define key(A) (A)
#define less(A,B) (key(A)<key(B))
#define exch(A,B) {Item t=A;A=B;B=t;}
#define compexch(A,B) if(less(B,A)) exch(A,B)
void selectSort(Item a[],int l,int r)
{
int i,j;
for(i=l;i<=r;i++)
{
int min=i;
for(j=i;j<=r;j++)
{
if(less(a[j],a[min]))
min=j;
}
exch(a[min],a[i]);
}
}
int main(int argc,char *argv[])
{
int N=atoi(argv[1]);
Item *a=(Item*)malloc(N*sizeof(Item));
for(int i=0;i<N;i++)
a[i]=1000*(1.0*rand()/RAND_MAX);
for(int i=0;i<N;i++)
printf("%3d ",a[i]);
printf("\n");
selectSort(a,0,N-1);
for(int i=0;i<N;i++)
printf("%3d ",a[i]);
printf("\n");
return 0;
}
二 冒泡排序
冒泡排序算法实际上也是一种选择排序算法,实现原理也比较简单。
- 比较相邻的前后二个数据,如果前面数据大于后面的数据,就将二个数据交换。
- 这样对数组的第0个数据到N-1个数据进行一次遍历后,最大的一个数据就“沉”到数组第N-1个位置。
- N=N-1,如果N不为0就重复前面二步,否则排序完成。
实现:
#include<stdio.h>
#include<stdlib.h>
typedef int Item;
#define key(A) (A)
#define less(A,B) (key(A)<key(B))
#define exch(A,B) {Item t=A;A=B;B=t;}
#define compexch(A,B) if(less(B,A)) exch(A,B)
void bubbleSort(Item a[],int l,int r)
{
int i,j;
for(i=r;i>l;i--)
for(j=l+1;j<=i;j++)
{
compexch(a[j-1],a[j]);
}
}
int main(int argc,char *argv[])
{
int N=atoi(argv[1]);
int i;
Item *a=(Item*)malloc(N*sizeof(Item));
for(i=0;i<N;i++)
{
a[i]=1000*(1.0*rand()/RAND_MAX);
printf("%3d ",a[i]);
}
printf("\n");
bubbleSort(a,0,N-1);
for(i=0;i<N;i++)
printf("%3d ",a[i]);
printf("\n");
return 0;
}
三 插入排序
插入排序也是一种比较直观的排序方式。可以以我们平常打扑克牌为例来说明,假设我们那在手上的牌都是排好序的,那么插入排序可以理解为我们每一次将摸到的牌,和手中的牌从左到右依次进行对比,如果找到合适的位置则直接插入。具体的步骤为:
- 从第一个元素开始,该元素可以认为已经被排序
- 取出下一个元素,在已经排序的元素序列中从后向前扫描
- 如果该元素小于前面的元素(已排序),则依次与前面元素进行比较如果小于则交换,直到找到大于该元素的就则停止;
- 如果该元素大于前面的元素(已排序),则重复步骤2
- 重复步骤2~4 直到所有元素都排好序 。
#include<stdio.h>
#include<stdlib.h>
typedef int Item;
#define key(A) (A)
#define less(A,B) (key(A)<key(B))
#define exch(A,B) {Item t=A;A=B;B=t;}
#define compexch(A,B) if(less(B,A)) exch(A,B)
void insertSort(Item a[],int l,int r)
{
int i,j;
for(i=r;i>l;i--) compexch(a[i-1],a[i]);
for(i=l+1;i<=r;i++)
{
Item v=a[i];
for(j=i;less(v,a[j-1]);j--)
{
a[j]=a[j-1];
}
a[j]=v;
}
}
int main(int argc,char *argv[])
{
int N=atoi(argv[1]);
Item *a=(Item*)malloc(N*sizeof(Item));
for(int i=0;i<N;i++)
a[i]=1000*(1.0*rand()/RAND_MAX);
for(int i=0;i<N;i++)
printf("%3d ",a[i]);
printf("\n");
排序算法的运行时间是和算法所执行的比较次数、元素的移动次数或者交换次数成正比的。三种基本排序算法的时间复杂度都是N的平方,但是在复杂度的常数因子上有所不同,所以复杂度总体是插入排序<选择排序<冒泡排序。除此,三种排序算法均不需要额外的空间。