快速排序是冒泡排序的改进版,也是最好的一种内排序,在很多面试题中都会出现,也是作为程序员必须掌握的一种排序方法。
1.在待排序的元素任取一个元素作为基准(通常选第一个元素)称为基准元素;
2.将待排序的元素进行分区,比基准元素大的元素放在它的右边,比其小的放在它的左边;
3.对于基准元素左边的元素进行上述步骤的递归调用进行排序,基准元素右边的元素也是如此。
你可以把快速排序联想成东拆西补或西拆东补,一边拆一边补,直到所有元素达到有序状态。
看看下图来理解一下快速排序的思想
以上相当于一趟的排序,然后对基准左边的元素和右边的元素重复上述步骤进行递归就可以了。
快速排序实现代码如下:
#include<stdio.h> void quickSort(int arr[],int _left,int _right){ if(_left<_right){ //待排元素至少需要两个才会进入if int temp=arr[_left]; //定义基准元素 int left=_left; int right=_right; while(left<right){ //从左右两边交替扫描,直到left=right while(left<right&&arr[right]>temp){ right--; //从右往左扫描,寻找比基准元素小的元素 } arr[left]=arr[right]; //找到这种元素arr[right]后与arr[left]交换 while(left<right&&arr[left]<temp){ left++; //从左往右扫描,寻找比基准元素大的元素 } arr[right]=arr[left]; //找到这种元素arr[left]后,与arr[right]交换 } arr[left]=temp; //基准元素放到arr[left]位置上 quickSort(arr,_left,left-1); //对基准元素左边元素递归排序 quickSort(arr,left+1,_right); //对基准元素右边元素递归排序 } } int main(void){ int arr[7]={3,2,5,8,4,7,6}; quickSort(arr,0,6); for(int i=0;i<7;i++){ printf("%3d",arr[i]); } }
接下来我们来讨论快速排序的最优情况和最差情况:
最优情况:最优情况就是数组每次划分都很均匀,例如如果排序n个关键字,其递归树的深度就为 [log2n]+1( [x] 表示不大于 x 的最大整数),即仅需递归 log2n 次。而每一次排序需要遍历一次当前排序的数组,因此最优情况下,快速排序的时间复杂为O(nlog2n)
最坏情况:最坏情况就是当待排序的序列为正序或逆序排列时,且每次划分只得到一个比上一次划分少一个记录的子序列,注意另一个为空。如果递归树画出来,它就是一棵斜树。此时需要执行n‐1次递归调用,且第i次划分需要经过n‐i次关键字的比较才能找到第i个记录,也就是枢轴的位置,因此比较次数为,最终其时间复杂度为O(n^2)。
总结:快速排序时间复杂度为,空间复杂度为,是一种不稳定的交换排序。