算法之旅——快速排序算法

       快速排序(Quicksort)是一种平均时间复杂度为O(n*log n)的高效排序法。其基本思想是:先设置一个比较值value,通常value为数组的第一个数(当然也可以设为其他的数,不过设第一个数方便些),通过一趟排序将要排序的数据分割成独立的左右两部分,其中左端的所有数据都小于等于value值,右端的数据都大于value值,然后再按此方法对这两端的数据分别进行快速排序,整个排序过程递归进行,以此达到整个数据变成有序序列。


一趟快速排序的算法是:
设待排序数组为arrary[N],
1)设置两个变量i,j,排序开始的时候令i=0,j=N-1;
2)以第一个数组元素作为比较值,赋值给value,即value=arrary[0];
3)从j开始向前搜索,即由后开始向前搜索(j--),找到第一个小于等于value的值arrary[j],将arrary[j]赋给arrary[i];
4)从i开始向后搜索,即由前开始向后搜索(i++),找到第一个大于value的arrary[i],将arrary[i]赋给arrary[j];
5)重复第3、4步,直到i=j;


示例如下:
设待排序数组arrary[10]={13,45,1,56,6,9,4,22,36}

 数值

  13  

  45 

  1   

   56  

    6  

   9  

   4  

   22  

  36 

下标

  0

  1

  2

   3

   4

  5

  6

  7

  8

 

令i=0; j=9;   value=arrary[i],  即value=13,可以这样理解,由于把arrary[0]赋给了value,故arrary[0]空了,产生了个坑

 数值

    

   45  

   1  

   56  

   6  

    9  

    4  

   22  

   36  

下标

  0  

   1

  2

  3

  4

   5

  6

   7

   8



此时需要其他数值来填补这个坑,那这个其他数值是谁呢?于是arrary数组就从后向前开始找,arrary[8]大于了value,跳过去,继续向前找,找到arrary[7],但是arrary[7]也大于value,跳过去,那就继续向前找,找到arrary[6]=4,这正好比value小,哎,终于找到这个数了,找你真是不容故意啊,于是就把arrary[6],填到arrary[0]的那个坑上去,即arrary[0]=arrary[6],可是把arrary[6]给了arrary[0],arraryp[6]就产生了个坑,这可怎么办?(i=0,j=6)

 数值

   4  

   45  

    1   

   56  

    6  

    9  

        

   22 

    36 

下标

  0

   1

   2

   3

  4

  5

  6

  7

   8



不要急,咱还是找个数将arrary[6]的坑填上,不过这次得从前往后找,找那个大于value的数,此刻arrary[0]是小于value的,那就i++呗,找到了arrary[1],哇,这么幸运,arrary[1]正好大于value,那就将arrary[1]赋给arrary[6],哎,又产生了个坑,就在arrary[1]上,咱继续找(i=1,j=6)

 数值

   4  

      

    1  

    56  

     6  

     9  

    45  

   22  

   36  

下标

  0

  1   

  2

   3

  4

   5

   6

  7

   8



折转方向, (tips:每填一个坑后都要折转方向) j加1就到了arrary[5]=9,耶,它比value小,就把它填到arrary[1]的坑上吧, (i=1,j=5)

 数值

   4  

   9   

    1  

    56 

    6  

      

   45  

   22  

   36  

下标

  0

  1

  2

  3

 4

  5   

  6

   7

   8



很显然,arrary[5]的坑已然出现,折转方向,从i着手,继续i++,arrary[2]小于value,直接pass, i再加1,arrary[3]=56大于value,就是它了,填到arrary[5]的坑上去 (i=3,j=5)

 数值

   4   

   9   

     1  

      

     6   

   56   

   45  

   22  

    36   

下标

  0

  1

   2

   3   

   4

   5

   6

    7

   8



再来填arrary[3]的坑,又折转方向,j++,遇到arrary[4],它小于value,必须的,就用arrary[4]填arrary[3]的坑,可想而知arrary[4]就会产生一个新的坑(i=3,j=4)

 数值

   4   

   9   

      1  

   6   

       

   56   

    45  

   22  

   36  

下标

   0

  1

   2

   3

  4

   5

   6

  7

  8



折转方向, i++,哎呀,i加1后,i就等于4,即i=j=4, 碰到了j,这还得了,i和j会不会打起来,呵呵,碰面了是好事,就像当年红军长征在陕西会师一样,万里长征结束了,胜利在望。 偷笑 咳咳,扯远了哈,这里i遇到了j,确实说明这一轮排序快结束了,可是arrary[4]还有个坑呢,总不能让它空着吧,当然不是啦,不是有个value值吗, 万里长征最后一步就是将value=13填到arrary[4]的坑里去 ,好了,打完收工

 数值

   4   

   9   

    1  

   6   

   13    

   56   

    45  

   22  

   36  

下标

  0

  1

  2

  3 

   4

  5

   6

  7

   8



       看看,value左边的值是不是都小于等于value,value右边的值是不是都比value大,嘿嘿,必须的嘛,不然咱们这么多功夫就白费了。

经过了这一轮比较,效果显著,接下来就好办了,对value左边的那部分继续上面的过程,对value右边的部分也继续上面的过程,这不就是传说中的递归嘛,只要排序没搞完,咱就继续递归下去。


说了这么久,到了给出代码的时候了,下面附上快速排序的源码,仅供参考。(此源码已经编译通过得意


[cpp]  view plain copy 在CODE上查看代码片 派生到我的代码片
  1. //description:quicksort  
  2. //author:hust_luojun  
  3. //data:2014-7-15  
  4.   
  5. #include <iostream>  
  6. #include <iomanip>  
  7. #include <stdlib.h>  
  8. #include <time.h>  
  9.   
  10. #define NUM 200  //NUM为数组大小,值可以自己设置  
  11.   
  12. using namespace std;  
  13.   
  14. int main()  
  15. {  
  16.     int  partition(int arrary[],int left,int right);  
  17.     void quicksort(int arrary[],int left,int right);  
  18.   
  19.     int*ptr = new int[NUM];     //开辟一个大小为NUM的数组  
  20.     srand(time(NULL));  
  21.     int i;  
  22.   
  23.     for(i=0;i<NUM;i++)  
  24.     {  
  25.         ptr[i] = rand()&0xffff;    //产生0~65535之间的随机数  
  26.     }  
  27.   
  28.     cout<<"the origin numbers are:"<<endl;  
  29.   
  30.     for(i=0;i<NUM;i++)              //输出未排序的数  
  31.     {  
  32.         if(i%10==0)  
  33.         cout<<endl;  
  34.         cout<<setiosflags(ios::right);  
  35.         cout<<setw(5)<<ptr[i]<<" ";  
  36.   
  37.     }  
  38.     quicksort(ptr, 0, NUM-1);  
  39.   
  40.     cout<<endl;  
  41.     cout<<endl;  
  42.   
  43.     cout<<"the sorted numbers are:"<<endl;  
  44.   
  45.     for(int i = 0;i < NUM;i++)         //输出已排序的数  
  46.     {  
  47.         if(i%10==0)  
  48.         cout<<endl;  
  49.         cout<<setiosflags(ios::right);  
  50.         cout<<setw(5)<<ptr[i]<<"  ";  
  51.   
  52.     }  
  53.   
  54.     delete []ptr;  
  55.     return 0;  
  56.   
  57. }  
  58.   
  59. int partition(int arrary[],int left,int right)  
  60. {  
  61.     int value = arrary[left];       //取数组第一个数为比较值  
  62.     int i = left;  
  63.     int j = right;  
  64.   
  65.     while(i < j)  
  66.     {  
  67.         while((i<j)&&(value <= arrary[j]))      //若右端数字大于value,就j--,直到找到第一个小于value的值,  
  68.             j--;  
  69.             arrary[i] = arrary[j];              //将其赋给arrary[i]  
  70.         while((i < j)&&(value >= arrary[i]))    //若左端数字小于value,就i++,直到找到第一个大于value的值,  
  71.             i++;  
  72.             arrary[j] = arrary[i];              //将其赋给arrary[j]  
  73.   
  74.     }  
  75.   
  76.     arrary[i] = value;  
  77.     return i;                                   //返回i的值  
  78. }  
  79.   
  80.     void quicksort(int arrary[],int left,int right)  
  81.     {  
  82.         if(left < right)  
  83.         {  
  84.             int k = partition(arrary,left ,right);  
  85.             quicksort(arrary,left,k-1);           //递归调用quicksort  
  86.             quicksort(arrary,k+1,right);  
  87.         }  
  88.     }  
[cpp]  view plain copy
  1.   

原始数据:



快速排序后的数据:


     

  /******码字不易,转载请注明出处*****/

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值