快速排序实现与分析

来源:互联网 发布:什么叫数字字符c语言 编辑:程序博客网 时间:2024/05/21 06:29

问题描述:快速排序是数据结构中经典算法,在各种内部排序中拥有非常高的效率——时间复杂度为O(NlogN),同时常数因子最小,但是同时也有可能出现最坏情况——在待排序元素几乎有序或者完全有序时候性能非常差,时间复杂度退化到O(N*N)。对快速排序性能影响最关键的就是基准元素的选择,所以为了平滑最坏情况,本程序使用了随机选择基准元素的方法。当然,聪明的读者可能会这样问到,就算随机选择,也有可能随机选择到的基准元素为最大或者最小的元素(这是出现最坏性能的情况),当然我们不排除这种可能。不过鉴于我们随机选择划分元,出现这种情况的概率非常小,也就是说,我们只有最坏的情况,但是不会出现最坏的实例了。如果要完全避免这种最坏的情况,可以使用中位数的方法选择划分元,这个方法相对比较麻烦,在此就不说了。

     说得太多了,上面的最坏情况、最坏实例的区别可能大家一时无法理解,不过也没事,我们不讨论这个问题了,毕竟过于专业化了。为了便于大家对快速排序的性能有个感性上的认识,代码中给出了一个对比的排序——冒泡排序,相信学过C语言或者其他语言的读者对这个排序不会陌生的。实例中,我做了10万个随机整数的排序,快速排序需要58clocks,而冒泡排序需要123720clocks,至于一个clokc是多少秒我也没有查了,反正就是个时间基准单元吧。可以看出,对于10万个数据的排序,冒泡排序花的时间是快速排序的2000倍以上。

 

 

#include<stdio.h>
#include<stdlib.h>
#include<time.h>
#define MAXLEN 10000//请大家注意这个MAXLEN不能太大,因为程序(进程)栈空间有限

//使用type替代int为了方便比较不同类型的数据,
//但是如果使用其他类型的数据或许需要根据情况进行运算符重载
typedef int type;

#define do_swap(x,y) {type tmp;tmp=x;x=y;y=tmp;}//使用宏展开式为了避免频繁函数调用的开销

int partion(type a[],int p,int r)
{
 type x=a[p];
 int i=p,j=r+1;
 while(1)
 {
  while(a[++i]<x&&i<r);
  while(a[--j]>x) ;
  if(i>=j) break;
  do_swap(a[i],a[j]);
 }
 a[p]=a[j];
 a[j]=x;
 return j;
}
int randpartion(type a[],int p,int r)
{
 if(p<r){
  int x=p+rand()%(r-p);
  do_swap(a[p],a[x]);
 }
 return partion(a,p,r);
}

void quicksort(type a[],int p,int r)//快速排序
{
 if(p<r){
  int q=randpartion(a,p,r);//使用随机选择划分元,平滑最坏的实例
  //int q=partion(a,p,r);//未使用随机选择划分元,划分元固定选择为a[p]
  quicksort(a,p,q-1);
  quicksort(a,q+1,r);
 }
}

void bubblesort(type a[],int p,int r)//冒泡排序
{
 int i,j;
 for(i=p;i<=r;++i)//在此处i++,++i效果相同,可能大家问到为什么使用++i而不使用i++,
  //这个比较微妙,相信不是每个人都有兴趣知道,不废话了。
  for(j=i+1;j<=r;++j)
   if(a[i]>a[j]){
    do_swap(a[i],a[j]);
   }
}

int main()
{
 type a[MAXLEN],b[MAXLEN];
 int i;

    srand(time(NULL));
 for(i=0;i<MAXLEN;++i)
 {
  b[i]=a[i]=rand();
 }
 time_t start_of_quicksort,end_of_quicksort;
 time_t start_of_bubblesort,end_of_bubblesort;


    start_of_bubblesort=clock();
 bubblesort(b,0,MAXLEN-1);
 end_of_bubblesort=clock();

    start_of_quicksort=clock();
 quicksort(a,0,MAXLEN-1);
 //quicksort(b,0,MAXLEN-1);//可以在使用未随机选择划分元的情况,测试快速排序的最坏实例
 end_of_quicksort=clock();


 
 
//观看排序后的结果,如果不想看结果可以屏蔽这段代码
 for(i=0;i<MAXLEN;++i)
 {
  printf("%6d",a[i]);
  if(i%10==9) printf("/n");
 }

printf("/n******************************************************/n");
printf("********************************************************/n");
printf("*****************************************************/n");
printf("*******************************************************/n");

 for(i=0;i<MAXLEN;++i)
 {
  printf("%6d",b[i]);
  if(i%10==9) printf("/n");
 }


printf("/n");
printf("*******************************************************/n");

 printf("%the time of quicksort is :%ld clocks/n",end_of_quicksort-start_of_quicksort);
 printf("%the time of bubblesort is :%ld clocks/n",end_of_bubblesort-start_of_bubblesort);

 return 0;
}