排序算法不管是在学习、面试、工作中都很重要,其中,快速排序在比较排序算法中效率较高,时间复杂度为O(nlogn),最坏情况下时间复杂度为O(n^2)。空间复杂度为:O(nlogn)。
1.快速排序算法原理
快速排序采取的是一种分治策略,假设将数的队列进行从小到大进行排列,其基本的步骤可分为:
(1) 从待排序的数中取一个数作为比较的基准;
(2) 对待排序数进行划分,将小于这个基准数的都放在左边,将大于基准数的都放在右边;
(3) 划分完成后,问题的规模减小了,符合分而治之的基本思想。然后将小规模的待排的数据再进行第二步,一直重复此过程,直到划分区间只有一个数了。
比如下边的示例:
如上图所示,nums[]是一个待排序的数组,第一步就是取一个比较的基准数,这里取nums[]数组的第一个数作为基准数index =nums[0]。创建两个查找下标指针L和r,l=0,r=9,r从右往左依次与基准数比较,l从左往右依次与基准数index比较。当r=9时,nums[r]=11,大于基准数index=7,则r-1,变成r=8继续与index进行比较,发现nums[r]小于index=7,这时将l=0,nums[0]=nums[8],同时将左边的标志l+1。下一步就开始从左边开始比较,当l变成3时,发现nums[3]=8大于index=7,这时,将nums[r]=nums[l],也就是nums[8]=nums[3],同时r-1。进行完这一步后,nums[]数组变为:
这时候l=3,r=7,然后再进行上边的步骤,先从后往前比较,再从前往后比较,直到l=r。如下图:
如上图所示,当l=r=5时,停止比较。将index的值填入到nums[r]=nums[l]中,完成第一次划分:
如上图所示,可以明显看到,待排数组以基准数index=7划分为了两个部分,前部分都小于它,后部分都大于它。这相当于划分了两个子问题,缩小了待解决问题的规模。
子问题的解决重复上边的步骤。直到子问题的规模为1,则完成了排序。
2.Java代码实现
解决分治问题,用了递归的方法,比较简单明了。核心代码如下:
/**
* QuickSort
* Created by Jz Wang on 2017/1/10.
*/
public class QuickSort {
public static void quickSort(int[] nums,int left,int right){
if (left<right){
int index = nums[left];
int l = left;
int r = right;
while (l<r){
while (l<r && nums[r]>=index){
r--;
}
if (l<r){
nums[l] = nums[r];
l++;
}
while (l<r && nums[l]<index){
l++;
}
if (l<r){
nums[r] = nums[l];
r--;
}
}
nums[l] = index;
quickSort(nums,left,l-1);
quickSort(nums,l+1,right);
}
}
}
还可以用非递归的方式以及快排的一些改进方法进行解决。在后边的文章中再介绍。
3.快排时间复杂度分析
快排的时间复杂度为O(nlogn),是基于比较排序中的效率较高的排序算法。最坏情况下的时间复杂度为O(n^2),发生的情况为:
最坏情况发生在划分过程产生的俩个区域分别包含n-1个元素和一个0元素的时候,即假设算法每一次递归调用过程中都出现了,这种划分不对称。那么划分的代价为O(n)。所以其时间的复杂度就可以用下边的式子表示:
T(n)=T(n-1)+T(0)+O(n)=T(n-1)+O(n)
可以得到T(n)=O(n^2)。换句话说,就是最坏情况出现在,每次划分都最大程度的不对称情况下。
所以,基准数的选择方法是一个可以改进快排的方式。会在以后的文章中再进行分析。
本文详细介绍了快速排序算法的原理及其实现方法,包括选取基准数、数据划分等关键步骤,并通过示例进行了具体说明。此外,还分析了快速排序的时间复杂度。
5904

被折叠的 条评论
为什么被折叠?



