快速排序
基本思想
(1)分解(divide):对于数组 a [p : r],以a[ p ]为基准将其分解为三段 a[ p ]的a[p : q-1],a[ q ] ,a[q+1 : r],前者都比a[q]小,后者都比a[q]大。
(2)递归求解(conquer)
递归调用快速排序算法,分别对a[p : q-1]和a[q+1 : r]进行排序。
(3)合并(merge)
排序时并没有分解所以不用合并。
核心算法如下
1、QuickSort:
private static void QuickSort( int p, int r) {
if(p<r) {
int q = partition(p,r);//分区
QuickSort(p,q-1);//递归调用对前半部分排序
QuickSort(q+1,r);//递归调用对后半部分排序
}
}
2、partition: 以下俩个方法类似,下图为第一个方法的配图
private static int partition(int p, int r) {
int x = a[p];
int i=p,j;
for(j=p+1;j<=q;j++){
if(a[j]<=x){
i++;
swap(a,i,j);
}
}
swap(a,p,i);
return i;
}
private static int partition(int p, int r) {
int i=p,j=r+1;
int x = a[p];//以待排序的第一个数作为基准
while(true) {
while(a[++i]<x&&i<r);//有数大于x则停止
while(a[--j]>x);//有数小于x则停止
if(i>=j)//i>=j排序结束
break;
swap(i,j);//交换i,j位置数组的值
}
a[p] = a[j];//循环结束后,将第一个(作为基准的数)与a[i] 交换位置
a[j] = x;
return j;
}
改进
该算法在不同情况时间复杂度为:
√ 最好情况:O(n*n)
√ 最坏情况:O(nlogn)
√ 一般情况:O(nlogn)
辅助空间:O(nlogn)
稳定性:不稳定
1、最坏情况
-
如果数组已经有序,每次只能将数组划分为1和n-1两段,此时,快速排序退化为冒泡排序。
-
T(n) = T(1) + T(n-1) +O(n)
T(n) = T(1) + T(1) + T(n-2) + O(n-1) + O(n)
T(n) = T(1) + T(1) + T(1)+ T(n-3) +T(n-2) + O(n-1) + O(n)
T(n) = O(n) + O(n*n)
T(n) = O(n*n)
2、最好情况
T(n) = 2*T(n/2) +O(n)
由主定理可知
T(n) = O(nlongn)
3、一般情况
假设规模为N的问题分为一个规模为9/10N的问题和规模为1/10N的问题,即T(n) = T(9n/10) + T(n/10) + Θ(n),用递归树分析可得 T(n) = O(nlongn)
数学证明老师讲了,忘了 qwq
4、主定理
f(n) = c*n(c为常数) | |
---|---|
a<b | T(n) = O(n) |
a=b | T(n) = O(nlogn) |
a>b | T(n) = O(n的logba次方) |
f(n) = c | |
---|---|
a=1 | T(n) = O(n) |
a!=1 | T(n) = O(n的logba次方) |
5、Random改变基准数
改QuickSort:
private static void QuickSort( int p, int r) {
if(p<r) {
Random ran = new Random();
int k =ran.nextInt(100);
swap(p,(p+1+k%(r-p)));
int q = partition(p,r);//
QuickSort(p,q-1);
QuickSort(q+1,r);
}
}
汇总
import java.util.Random;
import java.util.Scanner;
public class Oj1_QuickSort {
static int[] a;
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
while(sc.hasNext()) {
int n = sc.nextInt();
a = new int[n];
for(int i=0;i<n;i++) {
a[i] = sc.nextInt();
}
QuickSort(0,n-1);//分区
for(int i=0;i<n;i++) {
System.out.print(a[i]+" ");
//a[i] = sc.nextInt();
}
System.out.println();
}
}
private static void QuickSort( int p, int r) {
if(p<r) {
Random ran = new Random();
int k =ran.nextInt(100);
swap(p,(p+1+k%(r-p)));
int q = partition(p,r);//
QuickSort(p,q-1);
QuickSort(q+1,r);
}
}
private static int partition(int p, int r) {
int i=p,j=r+1;
int x = a[p];
while(true) {
while(a[++i]<a[p]&&i<r);
while(a[--j]>a[p]);
if(i>=j)
break;
swap(i,j);
}
a[p] = a[j];
a[j] = x;
return j;
}
private static void swap(int i, int j) {
int z = a[i];
a[i] = a[j];
a[j] = z;
}
}