快速排序
快速排序由托尼 · 霍尔于1961年提出。
-
分解原问题
数组 arr[p…r] 被划分为两个(可能为空)子数组 arr[p…q - 1] 和 arr[q + 1,…r],使得 arr[p…q - 1] 中的每一个元素都小于等于 arr[q],arr[q + 1,r] 中的每一个元素都大于等于 arr[q]。
-
解决子问题
递归调用快速排序,对子数组 arr[p…q - 1] 和 arr[q + 1…r] 进行排序。
-
合并问题解
对于快速排序来说,数组进行的是原址排序,所以不需要进行合并操作。
数组划分(Partition)
数组划分 Partition O(n) 主元一般选择尾位,也可任意选,之后再与尾位交换,且这个过程的时间复杂度为O(1),与直接选择尾位作为主元无异。
Partition 的每一次迭代中都会有两种不同的情况:
<1>. 如果 arr[ i ] > X,需要做的只是将 j 的值加 1。
<2>. 如果 arr[ i ] <= X,则要将 i 的值加1,并交换 arr[ i ] 和 arr[ j ],再将 j 的值加1。
伪代码
最好情况 : nlogn
最坏情况 : n2
代码实现
public static int Partition(int[] arr,int p, int r){
int temp;
int X = arr[r];
int i = p - 1;
for(int j = p; j <= r - 1; j++){
if(arr[j] <= X){
i = i + 1;
temp = arr[i];
arr[i] = arr[j];
arr[j] = temp;
}
}
temp = arr[i + 1];
arr[i + 1] = arr[r];
arr[r] = temp;
int q = i + 1;
return q;
}
public static int[] QuickSort(int[] arr,int p,int r){
int q;
if(p < r){
q = Partition(arr,p,r);
QuickSort(arr,p,q - 1);
QuickSort(arr,q + 1,r);
}
return arr;
}
算法实例
随机化的快速排序
随机划分,主元先随机选,之后与最后一个元素交换
期望复杂度为:O(nlogn)
代码实现
public static int RandomizedPartition(int[] arr,int p,int r){
// 在arr中随机选取主元
Random random = new Random();
int s = random.nextInt(r)%(r-p+1) + p;
// 将选取的主元与arr最后一个元素交换
int temp = arr[s];
arr[s] = arr[r];
arr[r] = temp;
return Partition(arr,p,r);
}
public static int[] RandomizedQuickSort(int[] arr,int p,int r){
int q;
if(p < r){
q = RandomizedPartition(arr,p,r);
RandomizedQuickSort(arr,p,q - 1);
RandomizedQuickSort(arr,q + 1,r);
}
return arr;
}
归并排序侧重合并过程,简化分解过程
快速排序侧重分解过程,简化合并过程
基于两个元素比较的排序算法的算法下界为O(nlogn)