快速排序(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会不会打起来,呵呵,碰面了是好事,就像当年红军长征在陕西会师一样,万里长征结束了,胜利在望。

数值 | 4 | 9 | 1 | 6 | 13 | 56 | 45 | 22 | 36 |
下标 | 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 |
看看,value左边的值是不是都小于等于value,value右边的值是不是都比value大,嘿嘿,必须的嘛,不然咱们这么多功夫就白费了。
经过了这一轮比较,效果显著,接下来就好办了,对value左边的那部分继续上面的过程,对value右边的部分也继续上面的过程,这不就是传说中的递归嘛,只要排序没搞完,咱就继续递归下去。
说了这么久,到了给出代码的时候了,下面附上快速排序的源码,仅供参考。(此源码已经编译通过)
- //description:quicksort
- //author:hust_luojun
- //data:2014-7-15
- #include <iostream>
- #include <iomanip>
- #include <stdlib.h>
- #include <time.h>
- #define NUM 200 //NUM为数组大小,值可以自己设置
- using namespace std;
- int main()
- {
- int partition(int arrary[],int left,int right);
- void quicksort(int arrary[],int left,int right);
- int*ptr = new int[NUM]; //开辟一个大小为NUM的数组
- srand(time(NULL));
- int i;
- for(i=0;i<NUM;i++)
- {
- ptr[i] = rand()&0xffff; //产生0~65535之间的随机数
- }
- cout<<"the origin numbers are:"<<endl;
- for(i=0;i<NUM;i++) //输出未排序的数
- {
- if(i%10==0)
- cout<<endl;
- cout<<setiosflags(ios::right);
- cout<<setw(5)<<ptr[i]<<" ";
- }
- quicksort(ptr, 0, NUM-1);
- cout<<endl;
- cout<<endl;
- cout<<"the sorted numbers are:"<<endl;
- for(int i = 0;i < NUM;i++) //输出已排序的数
- {
- if(i%10==0)
- cout<<endl;
- cout<<setiosflags(ios::right);
- cout<<setw(5)<<ptr[i]<<" ";
- }
- delete []ptr;
- return 0;
- }
- int partition(int arrary[],int left,int right)
- {
- int value = arrary[left]; //取数组第一个数为比较值
- int i = left;
- int j = right;
- while(i < j)
- {
- while((i<j)&&(value <= arrary[j])) //若右端数字大于value,就j--,直到找到第一个小于value的值,
- j--;
- arrary[i] = arrary[j]; //将其赋给arrary[i]
- while((i < j)&&(value >= arrary[i])) //若左端数字小于value,就i++,直到找到第一个大于value的值,
- i++;
- arrary[j] = arrary[i]; //将其赋给arrary[j]
- }
- arrary[i] = value;
- return i; //返回i的值
- }
- void quicksort(int arrary[],int left,int right)
- {
- if(left < right)
- {
- int k = partition(arrary,left ,right);
- quicksort(arrary,left,k-1); //递归调用quicksort
- quicksort(arrary,k+1,right);
- }
- }
原始数据:
快速排序后的数据:
/******码字不易,转载请注明出处*****/