快速排序-三路快排
程序员文章站
2022-03-12 17:09:34
...
快速排序可能是应用最广泛的排序算法了,它的实现简单,只需要一个很小的辅助栈,将长度为N的数组排序所需时间和NlogN成正比,在本篇文章讲述一下改进的快速排序-三路快排
三路快排
所谓三路快排,一言以蔽之,就是同时排序小于选定值,等于选定值和大于选定值三种情况
在这里我们随机选取一个值v作为分界点,分别排序小于v,等于v和大于v的,这里之所以随机选取是考虑到如果我们选取数组第一个值,那么在一个完全有序的数组里,我们的快速排序就会退化为log(n^2)
先来看代码:
package vip.lanco;
import java.util.*;
public class QuickSort3 {
// 我们的算法类不允许产生任何实例
private QuickSort3(){}
// 递归使用快速排序,对arr[left...right]的范围进行排序
private static void sort(Comparable[] arr, int left, int right){
// 对于小规模数组, 使用插入排序会更加快速
if( right <left ){
//自己实现插入排序
}
/* 随机在arr[l...r]的范围中, 选择一个数值作为标定点pivot*/
swap( arr, left, (int)(Math.random()*(right-left+1)) + left );
Comparable v = arr[left];
//设置边界值
int lt = left; // arr[left+1...lt] < v
int gt = right + 1; // arr[gt...right] > v
int i = left+1; // arr[lt+1...i) == v
while( i < gt ){
if( arr[i].compareTo(v) < 0 ){
swap( arr, i, lt+1);
i ++;
lt ++;
}
else if( arr[i].compareTo(v) > 0 ){
swap( arr, i, gt-1);
gt --;
}
else{ // arr[i] == v
i ++;
}
}
swap( arr, left, lt );
sort(arr, left, lt-1);
sort(arr, gt, right);
}
public static void sort(Comparable[] arr){
int n = arr.length;
sort(arr, 0, n-1);
}
//两值交换
private static void swap(Object[] arr, int i, int j) {
Object t = arr[i];
arr[i] = arr[j];
arr[j] = t;
}
//输出显示
private static void show(Comparable[] a) {
for (int i = 0; i < a.length; i++) {
System.out.print(a[i]+"--");
}
}
// 测试 QuickSort3
public static void main(String[] args) {
Comparable[] arr = new Comparable[] {23,45,1,21,67,78,89,55,12,34,22,11,5,6,9};
sort(arr);
show(arr);
return;
}
}
如上,我们以数组[23,45,1,21,67,78,89,55,12,34,22,11,5,6,9]为例
一开始设置的边界值lt=0,gt=15,i=1,假设随机选取pivot标志后为5;
则arr[1]=45 > v=5 所以交换45和9的位置,同时gt-1,此时arr[1]=9;
接着继续判断arr[1]=9 > v=5 ,所以这时候交换6和9的位置 ,此时arr[1]=6
如此下去直到最后只剩下:
v(left) | <v(lt) | ==v(gt,i) | >v(right) |
再去交换left和lt的值。
小改进,在right-left<=15左右时候,我们可以改为插入排序,效率会有所改进