首先,先哔哔下什么是快速排序算法。
快速排序由C. A. R. Hoare在1962年提出。基本思想是使一串无序数据,选取其中一条数据,使该数据左边放置全部都是小于该数据的数据,使右边放置大于该数据的数据。这样便完成一趟快速排序,然后可以针对该串数据左边进行下一趟快速排序,右边也进行一趟,这样一次次的进行递归操作,便可得到有序的数据序列。快速排序主要采用的是分治思想。
具体算法如下:
public static void QuickSort(int[] arr, int l, int r){
if(l < r){
//递归的边界条件,当 L == R时数组的元素个数为1个
int pivot = arr[l];//最左边的元素作为中轴,L表示left, R表示right
int i = l+1;
int j = r;
//当i == j时,i和j同时指向的元素还没有与中轴元素判断,
//小于等于中轴元素,i++,大于中轴元素j--,
//当循环结束时,一定有i = j+1, 且i指向的元素大于中轴,j指向的元素小于等于中轴
while(i <= j){
while(i <= j && arr[i] <= pivot){
i++;
}
while(i <= j && arr[j] > pivot){
j--;
}
//当 i > j 时整个切分过程就应该停止了,不能进行交换操作
//这个可以改成 i < j, 这里 i 永远不会等于j, 因为有上述两个循环的作用
if(i <= j){
exchange(arr, i, j);
i++;
j--;
}
}
//当循环结束时,j指向的元素是最后一个(从左边算起)小于等于中轴的元素
exchange(arr, l, j);//将中轴元素和j所指的元素互换
QuickSort(arr, l, j-1);//递归左半部分
QuickSort(arr, j+1, r);//递归右半部分
}
}
private static void exchange(int[] arr , int a , int b){
//交换数组arr指定的两个元素的位置
int temp;
temp= arr[a];
arr[a] = arr[b];
arr[b] = temp;
}
快速排序算法是一种原地排序,只需要一个很小的栈作为辅助空间,时间复杂度为O(nlogn)。空间复杂度为O(log2n),所以适合在数据集比较大的时候使用。
然后,就开始进入正题:
说说什么事三项切分的快速排序算法。
其实说来也很简单,普通的快速排序是依据选取的固定节点作为一趟排序活动的基准,大于它的放一边,小于它的放另一边,然鹅:你有没有想到要是有其他数据等于你选定的基准咋办?这个时候,就是使用我们今天主角的时候了,把相等的放在中间(与其说放在中间倒不如说交换数组中的位置时放在了一起),大于和小于的分列两边,这样数组分成了三分,比起普通的快速排序,简化了当元素相等时某些元素在数组里面交换来交换去的“逛街”。
本咩咩狠话不多,直接上代码:
public static void QuickSortThreeWay(int[] arr, int l, int r){
if(l >= r){//递归终止条件,少于等于一个元素的数组已有序
return;
}
int i,j,k,pivot;
pivot = arr[l]; //首元素作为中间元素
i = l;
k = l+1;
j = r;
while(k <= j){
if(arr[k] < pivot){
exchange(arr, i, k);
i++;
k++;
}else
if(arr[k] == pivot){
k++;
}else{// 遇到arr[k]>pivot的情况,j从右向左扫描
while(arr[j] > pivot){//arr[j]>pivot的情况,j继续向左扫描
j--;
if(j < k){
break;
}
}
if(arr[j] == pivot){//arr[j]==pivot的情况
exchange(arr, k, j);
k++;
j--;
}else{//arr[j]<pivot的情况
exchange(arr, i, j);
exchange(arr, j, k);
i++;
k++;
j--;
}
}
}
QuickSortThreeWay(arr, l, i-1); // 对小于pivot的部分进行递归
QuickSortThreeWay(arr, j+1, r); // 对大于pivot的部分进行递归
}
元素重复率特别高的时候经典的快速排序算法是不适合的。但三向切分的快速排序算法,针对重复率高的时候,避免相同元素来回交换,节省交换次数。对于包含大量重复元素的数组,这个算法将排序时间从线性对数级降到了线性级别。
算法代码来自这位大佬:nullzx - 博客园