版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/majinlei121/article/details/83902497
前两篇博客介绍了快速排序算法以及对快速排序算法的两种改进,
下面开始介绍三路快速排序算法,之所以称为三路快速排序算法,是因为其考虑了三个部分(如下图),分别为大于
的部分, 小于
的部分, 等于
的部分。
如上图所示,随机选择一个元素
作为参考元素,并与最左边元素交换位置,交换后参考元素
的索引为
. 然后定义小于
的元素中最后一个元素索引为
,大于
的元素中第一个元素索引为
,当前处理元素索引为
,三路排序就是使
,
,
(1)当前元素
大于
时,
,
(2)当前元素
小于
时,
,
,
(3)当前元素
等于
时,
(4)最后排序的结果是
,如下图所示
(5)最后一步,将参考元素
交换到合适的位置,
下面是C++程序实现:
#include <iostream>
#ifndef _SORTINGHELP_H_
#define _SORTINGHELP_H_
#include "SortingHelp.h"
#endif // _SORTINGHELP_H_
#include "MergeSorting.h"
using namespace std;
//对arr[l...r]进行partition操作
//
template<typename T>
int __partition2(T arr[], int l, int r){
//随机找一个元素与最左边元素进行交换位置
swap(arr[l], arr[rand()%(r-l+1)+l]);
T v = arr[l];
//arr[l+1...i)<=v; arr(j...r]>=v
int i = l + 1;
int j = r;
while(true){
while(arr[i] < v && i <= r) i++;
while(arr[j] > v && j >= l + 1) j--;
if (i > j) break;
swap(arr[i], arr[j]);
i ++;
j --;
}
swap(arr[l], arr[j]);
return j;
}
//对arr[l...r]部分进行排序
template<typename T>
void __quickSorting2(T arr[], int l, int r){
if (l >= r)
return;
srand(time(NULL));
int p = __partition2(arr, l, r);
__quickSorting2(arr, l, p - 1);
__quickSorting2(arr, p + 1, r);
}
template<typename T> //快速排序
void quickSorting2(T arr[], int n){
__quickSorting2(arr, 0, n-1);
}
//////////////////////////////////////////////////
//////////////////////////////////////////////////
//对arr[l...r]部分进行排序
template<typename T>
void __quickSorting3ways(T arr[], int l, int r){
if (l >= r)
return;
srand(time(NULL));
//随机找一个元素与最左边元素进行交换位置
swap(arr[l], arr[rand()%(r-l+1)+l]);
T v = arr[l];
//arr[l+1...lt]<v, arr[gt...r]>v, arr[lt+1...i-1]==v
int lt = l, gt = r + 1, i = l + 1;
while(i < gt){
if (arr[i] > v){
swap(arr[i], arr[gt-1]);
gt--;
}
else if (arr[i] == v){
i++;
}
else{
swap(arr[i], arr[lt + 1]);
lt++;
i++;
}
}
swap(arr[l], arr[lt]);
__quickSorting3ways(arr, l, lt - 1);
__quickSorting3ways(arr, gt, r);
}
template<typename T> //快速3路排序
void quickSorting3ways(T arr[], int n){
__quickSorting3ways(arr, 0, n-1);
}
//int main(){
// int arr[] = {8,7,6,5,4,3,2,1};
// int n = 8;
// quickSorting3ways(arr, n);
// for(int i = 0; i < n; i++){
// cout<<arr[i]<<" ";
// }
// cout<<endl;
// return 0;
//}
int main()
{
//生成5万个随机元素组成的数组
int n = 500000;
int *arr = generateRandomArray(n, 0, n);
int *arr2 = copyIntArray(arr, n);
int *arr3 = copyIntArray(arr, n);
cout<<"随机数组的排序比较"<<endl;
testSorting("MergeSorting", MergeSorting, arr, n);
testSorting("quickSorting2", quickSorting2, arr2, n);
testSorting("quickSorting3ways", quickSorting3ways, arr3, n);
delete[] arr;//最后删除数组开辟的空间
delete[] arr2;
delete[] arr3;
//生成5万个近乎有序的数组
arr = generateNearlyOrderedArray(n, 100);//生成只有200个无序元素的数组
arr2 = copyIntArray(arr, n);
arr3 = copyIntArray(arr, n);
cout<<"近乎有序数组的排序比较"<<endl;
testSorting("MergeSorting", MergeSorting, arr, n);
testSorting("quickSorting2", quickSorting2, arr2, n);
testSorting("quickSorting3ways", quickSorting3ways, arr3, n);
delete[] arr;//最后删除数组开辟的空间
delete[] arr2;
delete[] arr3;
//生成5万个有大量重复元素的数组
arr = generateRandomArray(n, 0, 10);
arr2 = copyIntArray(arr, n);
arr3 = copyIntArray(arr, n);
cout<<"有大量重复元素数组的排序比较"<<endl;
testSorting("MergeSorting", MergeSorting, arr, n);
testSorting("quickSorting2", quickSorting2, arr2, n);
testSorting("quickSorting3ways", quickSorting3ways, arr3, n);
delete[] arr;//最后删除数组开辟的空间
delete[] arr2;
delete[] arr3;
return 0;
}
输出结果为
可以看出对于随机数组或者近乎有序的数组来说,三路快速排序要慢于快速排序,但是时间复杂度也是在可接受的范围内;对于有大量重复元素的数组来讲,三路快速排序则要快于快速排序,因此三路快速排序的应用范围是很广泛的。