参考:快速排序法(《C++程序设计教程 第三版 通用版 钱能 P138页》例ch7_11.cpp)
#include<iostream>
using namespace std;
//---------------------
void qsort(int[],int,int);
//---------------------
int main(){
int array[]={55,2,6,4,11,12,9,73,26,37};
int len=sizeof(array)/sizeof(int);
for(int i=0; i<len; i++) //原始顺序输出
cout<<array[i]<<",";
cout<<"\n\n";
qsort(array,0,len-1); //调用排序函数
for(int i=0; i<len; i++) //排序结果输出
cout<<array[i]<<",";
cout<<endl;
system("pause");
}//--------------------
void qsort(int a[], int left, int right){ //快速排序法
int pivot=a[right],l=left,r=right,temp; //①
while(l<r){ //②
temp=a[l], a[l]=a[r], a[r]=temp; //交换③
while(l<r && a[r]>pivot) --r; //④
while(l<r && a[l]<=pivot) ++l; //⑤
}
temp=a[left], a[left]=a[r], a[r]=temp; //使得a[r]成为分界元⑥
if(left<r-1) qsort(a,left,r-1); //⑦
if(r+1<right) qsort(a,r+1,right); //⑧
}//----
快速排序法原理:
二分法。选择数组末尾的值作为分界值,把数组分为两部分,大于分界值的元素集中到数组的右边,小于等于分界值的元素集中到数组左边。对于分出来的左右两边的数组重复上述过程(末位置作为分界值,其他元素按大小分到左右两边),不断迭代,直至排序结束。
编程思路:
①首先,将数组最左边元素和最右边元素(第一次的分界值)对调,把分界值放在最左边,便于本次分界完后可快速找回分界值并把他放回正确的分界位置(注释⑥)。
②进入循环后,经过④和⑤的移位,如果l<r,则证明依旧有大于分界值的元素依旧在左边,小于分界值的元素在右边,所以需要进入while循环将他们进行对调,并继续执行④和⑤进行元素检查并移位。
③对元素进行对调。尽管进入while循环的第一次对调有可能会适得其反,把小于分界值的元素放到了右边,但是④和⑤的移位判断会使其在下一次while循环中重新对调回正确位置。
④对r位置上的元素进行判断,如果r上的元素大于分界值,则该元素已分界完,可以检查左边一个位置的元素,所以r左移一位。
⑤对l位置上的元素进行判断,如果r上的元素小于等于分界值,则该元素已分界完,可以检查右边一个位置的元素,所以r右移一位。由于while循环开始时,分界值被换到了最左边,而判断条件是≤,所以分界值会一直保持在最左边。等待第⑥步中可重新放到正确分界点。
⑥如果l<r不成立,循环结束。l<r不成立,可证明所有元素都已经分界完毕,r已经处于分界点位置上了。所以将分界值从数组左边换回分界点,而分界点上的位置换到数组最左边(因为r位置上的元素不满足a[r]>pivotj,所以它肯定是小于等于分界点的值,换到最左边不影响分界。)
⑦此时,分界点左边的元素全部满足小于等于分界值。所以可以对分界点左侧的元素(不需要再包含分界点的值)进行①-⑥的再次分界,即迭代运算,直到最后变成从小到大的排序。
⑧此时,分界点右边的元素全部满足大于分界值。所以可以对分界点右侧的元素(不需要再包含分界点的值)进行①-⑥的再次分界,即迭代运算,直到最后变成从小到大的排序。