快速排序
- 以整个数组为对象执行quickSort
- quickSort流程如下
2.1 通过分割将对象局部数组分割为前后两个局部数组。
2.2 对前半部分数组执行quickSort。
2.3 对后半部分数组执行quickSort。
分割
如下图,数组A的分割范围为p ~ r(包含p和r)。这里分割的基准(即A[r],数组的最后一个元素)为x。接下来移动A中的元素,将小于等于 x 的元素移到p ~ i的范围内(包含 i),大于 x 的元素移到i+1 ~ j 的范围内(不包含 j)。其中i初始化为p-1,j初始化为p。
当A[j]>X时不必移动元素,j直接向前移动,A[j]自动归入i+1 ~ j的组。
当A[j]≦X时,先让i 向前移动一个位置,然后交换A[j]和A[i]。这样A[j]就归入p ~ i 的组,随着j向后移动,原本位于A[j]的元素又会被归入 i+1 ~ j的组。
当j和r相遇时,分割结束,将A[i+1]和A[r] 交换,然后X左面的数组都小于等于X,右面的数组都大于X。
代码:
public static void partition(int[] a, int p, int r) {
int x,i,j,temp;
x = a[r];
i = p-1;
for(j=p;j<r;j++) {
if(a[j] <= x) {
i++;
temp = a[i];
a[i] = a[j];
a[j] = temp;
}
}
temp = a[i+1];
a[i+1] = a[r];
a[r] = temp;
}
分割的算法复杂度为O(n)。
快速排序
快速排序的函数quickSort通过分割将数组一分为二,然后对两个数组递归执行quickSort,从而完成数组的排序。
以A=[13,19,9,5,12,8,7,4,21,2,5,3,14,6,11]为例使用快速排序过程:
注:红色数字为执行顺序。
代码:
import java.util.Arrays;
public class QuickSort {
//分割
public static int partition(int[] a, int p, int r) {
int x,i,j,temp;
x = a[r];
i = p-1;
for(j=p;j<r;j++) {
if(a[j] <= x) {
//先移动i,再交换
i++;
temp = a[i];
a[i] = a[j];
a[j] = temp;
}
}
//交换a[i+1]和a[r]
temp = a[i+1];
a[i+1] = a[r];
a[r] = temp;
//返回基准位置
return i+1;
}
public static void quickSort(int[] a, int p, int r) {
int index;
if(p<r) {
index = partition(a,p,r);
//左半部分数组
quickSort(a,p,index-1);
//右边部分数组
quickSort(a,index+1,r);
}
}
public static void main(String[] args) {
int[] a = {13,19,9,5,12,8,7,4,21,2,5,3,14,6,11};
quickSort(a,0,a.length-1);
System.out.println(Arrays.toString(a));
}
}
结果:[2, 3, 4, 5, 5, 6, 7, 8, 9, 11, 12, 13, 14, 19, 21]
总结:
- 快速排序在分割过程中会交换不相邻元素,所以属于不稳定的排序算法。
- 快速排序不需要额外占用内存空间,是一种内部排序(原地排序)。
- 如果快速排序分割时恰好选择到中间值,则一共可以分割成log2 n层。每层排序的复杂度为O(n),所以快速排序的平均复杂度为O(nlogn);最坏情况下可以分割为n层,所以最坏复杂度是O(n2)。
来源:CSDN
作者:爱吃鱼的ねこ
链接:https://blog.csdn.net/weixin_43982698/article/details/104223418