核心代码如下:
int partition(int a[],int left,int right){
srand((unsigned)time(NULL));
int p=(round(1.0*rand()/RAND_MAX*(right-left))+left); //选择轴元素
swap(a[left],a[p]);
int temp=a[left]; //将轴元素存放至临时变量temp
while(left<right){ //只要left和right不相遇
while(left<right && a[right]>temp) right--; //反复左移right
a[left]=a[right];
while(left<right && a[left]<=temp) left++; //反复右移left
a[right]=a[left];
}
a[left]=temp; //把temp放到left与right相遇的地方
return left; //返回相遇的下标
}
void quickSort(int a[],int left,int right){
if(left<right){
int pos=partition(a,left,right); //将a[left,right]一分为二
quickSort(a,left,pos-1); //对左子区间递归进行快速排序
quickSort(a,pos+1,right); //对右子区间递归进行快速排序
}
}
快速排序的核心思想在于每次选择一个轴,根据这个轴进行排序,比轴小的元素放在轴的左侧,比轴大的元素放在轴的右侧,当左右指针相遇时为排序边界,其思想理解起来很容易,在具体实现时有以下需要注意的地方。
(1)随机数的生成。先用rand()函数生成一个[0,RAND_MAX]范围内的随机数,然后再用这个随机数除以RAND_MAX,这样就会得到一个[0,1]范围内的浮点数。我们只需要用这个浮点数乘以(right-left),再加上left即可,即(round(1.0*rand()/RAND_MAX*(right-left))+left),相当于这个浮点数就是[left,right]范围内的比例位置。
(2)每次选择轴时最好是利用随机数随机选择,而不是适中使用最左侧元素作为轴,这是因为当始终使用最左侧元素作为轴时,可能会导致算法的最坏时间复杂度达到。但采用随机数生成轴时算法对于任意输入数据的时间复杂度都能达到。
(3)两侧指针在进行移动时采用分批连续移动的方法,如上述代码所示。先从右侧开始,判断当前元素是否大于轴元素,若大于则持续左移,直至遇到第一个小于等于轴元素的数,然后将该元素与左侧指针所指的数进行交换;然后从左侧开始看,判断当前元素是否小于等于轴元素,若小于等于则持续右移,直至遇到第一个大于轴元素的数,然后将该元素与右侧指针所指的数交换;再从右边看….直至左右指针重合为止。
(4)具体排序的时候就直接递归调用,不断地选择轴元素、分块,最后达到有序的状态。