说起快排,其实是很熟悉的一个算法了,对于自己而言,只是不断的在会了忘,看了会的循环往复中。今天决定把这个算法彻底的搞清楚,铭记在心,故写此文章。
快排的基本思路:
例如给定数组a[],如下表所示:
下标i | 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 |
a[i] | 3 | 6 | 1 | 2 | 8 | 9 | 3 | 7 |
第一步:找一个基准值。可以是数组中的任何一个元素。在此,我选择数组a的第一个元素3作为基准值。
第二步:想办法将比基准值小的值全放在其左边,比基准值大的值全放在其右边。可以设置两个指针left和right,分别指向数组的开头和结尾,从后往前找第一个比基准值小的值,交换找到的值和基准值的位置;然后,从前往后找第一个比基准值大的值,交换找到的值和基准值的位置;重复以上操作,直到left和right指向同一个位置。
第二步完成之后,基准值3已经处在了正确的位置,其左边的值小于3,右边的值大于3;
第三步:分别对3左右的两个部分(分区)重复递归进行第二步的操作。直到整个数组有序。程序完成。
代码实现与解释:
int partition(int a[],int left,int right){
int key = a[left];
while(left<right){
while(left<right && a[right]>=key)
right--;
swap(a[left],a[right]);
while(left<right && a[left]<=key)
left++;
swap(a[left],a[right]);
}
a[left]=key;//a[right]=key
return left;//return right 此时left==right 故返回任何一个即可
}
key是基准值,我选择的是数组的第一个元素,其实是数组中的任何一个元素。在第一个while循环中,首先是从后往前找,如果值比key值大,则说明它本来就在key值的右侧,right--;直到找到a[right]<=key,跳出循环,交换基准值和a[right];然后从前往后找,如果值比key值小,则说明它本来就在key值的左侧,left++;直到a[left]>=key,跳出循环,交换两者的值;不停的进行以上步骤,直到left==right,即两者处在同一位置,无需再进行交换为止。
此时,第一个元素已经处在数组中的正确位置了,将其位置返回。
void quicksort(int a[],int left,int right){
if(left<right){
int correctPos = partition(a,left,right);
quicksort(a,left,correctPos-1);
quicksort(a,correctPos+1,right);
}
}
递归进行,直至所有元素均处在正确的位置。
int main()
{
int a[]={3,6,1,2,8,9,4,3,7};
quicksort(a,0,8);
for(int i=0;i<9;i++){
cout << a[i] << " ";
}
return 0;
}
对以上写的方法进行测试
测试结果如上图所示。
总结:
快速排序的每一轮处理其实就是将这一轮的基准数归位,直到所有的数都归位为止,排序就结束了。
快速排序之所比较快,因为相比冒泡排序,每次交换是跳跃式的。每趟排序会设置一个基准值,将<=基准点的数全部放到基准点的左边,将>=基准点的数全部放到基准点的右边。这样的话,每次交换的时候就不会像冒泡排序一样每次只能在相邻的数之间进行交换,交换的距离就会变大,总的比较和交换次数就少了,速度也就提高了。当然在最坏的情况下,时间复杂度和冒泡排序是一样的都是O(N2),它的平均时间复杂度为O(NlogN)。
#include <iostream>
using namespace std;
int partition(int a[],int left,int right){
int key = a[left];
while(left<right){
while(left<right && a[right]>=key)
right--;
swap(a[left],a[right]);
while(left<right && a[left]<=key)
left++;
swap(a[left],a[right]);
}
a[left]=key;//a[right]=key
return left;//return right 此时left==right 故返回任何一个即可
}
void quicksort(int a[],int left,int right){
if(left<right){
int correctPos = partition(a,left,right);
quicksort(a,left,correctPos-1);
quicksort(a,correctPos+1,right);
}
}
int main()
{
int a[]={3,6,1,2,8,9,4,3,7};
quicksort(a,0,8);
for(int i=0;i<9;i++){
cout << a[i] << " ";
}
return 0;
}