在简书上看到一篇博文介绍快速排序,于是在这里介绍一下
维基百科:快速排序,又称划分交换排序,简称快排,最早由东尼.霍尔提出。在平均状况下,排序n个项目需要O(nlogn)次比较。在最坏的情况下,需要O(n^2)次比较,但这种状况并不常见。事实上,快速排序通常明显比其他算法更快,因为它的内部循环可以在大部分架构上很有效率的达成
快速排序思想
1.先从数列中取出一个数作为基准数
2.分区过程,将比这个数大的数全放在它的右边,小于或等于它的数全放到它的左边。
3.再对左右区间重复第2步,直到各区间只有一个数。
public class Main {
public static int[] a={8,4,9,1,10,16};
public static void main(String[] args) {
sortNomalArray();
}
private static void sortNomalArray() {
quickSort(a,0,a.length-1);
for (int i = 0; i <a.length ; i++) {
System.out.print(a[i]+" ");
}
}
private static void quickSort(int[] a, int left, int right) {
if(left<right){
int i=left;
int j=right;
int sign = a[left];
while(i<j){
while(i<j&&a[j]>=sign){
j--;
}
while (i < j && a[i] <=sign) {
i++;
}
if (i < j) {
int tmp=a[i];
a[i]=a[j];
a[j]=tmp;
}
}
a[left]=a[i];
a[i] = sign;
//递归排序
quickSort(a, left, i - 1);
quickSort(a, i + 1, right);
}
}
}
我们从一个数组来逐步逐步说明快速排序的方法和思路。
- 假设我们对数组{7, 1, 3, 5, 13, 9, 3, 6, 11}进行快速排序。
- 首先在这个序列中找一个数作为基准数,为了方便可以取第一个数。
- 遍历数组,将小于基准数的放置于基准数左边,大于基准数的放置于基准数右边。此时得到类似于这种排序的数组{3, 1, 3, 5, 6, 7, 9, 13, 11}。
- 在初始状态下7是第一个位置,现在需要把7挪到中间的某个位置k,也即k位置是两边数的分界点。
- 那如何做到把小于和大于基准数7的值分别放置于两边呢,我们采用双指针法,从数组的两端分别进行比对。
先从最右位置往左开始找直到找到一个小于基准数的值,记录下该值的位置(记作 i)。
再从最左位置往右找直到找到一个大于基准数的值,记录下该值的位置(记作 j)。
如果位置i<j,则交换i和j两个位置上的值,然后继续从(j-1)的位置往前和(i+1)的位置往后重复上面比对基准数然后交换的步骤。
如果执行到i==j,表示本次比对已经结束,将最后i的位置的值与基准数做交换,此时基准数就找到了临界点的位置k,位置k两边的数组都比当前位置k上的基准值或都更小或都更大。 - 上一次的基准值7已经把数组分为了两半,基准值7算是已归位(找到排序后的位置)。
通过相同的排序思想,分别对7两边的数组进行快速排序,左边对[left, k-1]子数组排序,右边则是[k+1, right]子数组排序。
利用递归算法,对分治后的子数组进行排序
。