数据结构与算法C++之三路快速排序

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/majinlei121/article/details/83902497

前两篇博客介绍了快速排序算法以及对快速排序算法的两种改进
下面开始介绍三路快速排序算法,之所以称为三路快速排序算法,是因为其考虑了三个部分(如下图),分别为大于 v v 的部分, 小于 v v 的部分, 等于 v v 的部分。
在这里插入图片描述
如上图所示,随机选择一个元素 v v 作为参考元素,并与最左边元素交换位置,交换后参考元素 v v 的索引为 l l . 然后定义小于 v v 的元素中最后一个元素索引为 l t lt ,大于 v v 的元素中第一个元素索引为 g t gt ,当前处理元素索引为 i i ,三路排序就是使
a r r [ l + 1... l t ] < v arr[l+1...lt]<v , a r r [ g t . . . r ] > v arr[gt...r]>v , a r r [ l t + 1... i 1 ] = = v arr[lt+1...i-1]==v
(1)当前元素 i i 大于 v v 时, s w a p ( a r r [ i ] , a r r [ g t 1 ] ) swap(arr[i], arr[gt-1]) g t gt--
(2)当前元素 i i 小于 v v 时, s w a p ( a r r [ i ] , a r r [ l t + 1 ] ) swap(arr[i], arr[lt+1]) l t + + lt++ i + + i++
(3)当前元素 i i 等于 v v 时, i + + i++
(4)最后排序的结果是 g t = i gt=i ,如下图所示

在这里插入图片描述
(5)最后一步,将参考元素 v v 交换到合适的位置, s w a p ( a r r [ l ] , a r r [ l t ] ) swap(arr[l], arr[lt])

下面是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;
}

输出结果为
在这里插入图片描述
可以看出对于随机数组或者近乎有序的数组来说,三路快速排序要慢于快速排序,但是时间复杂度也是在可接受的范围内;对于有大量重复元素的数组来讲,三路快速排序则要快于快速排序,因此三路快速排序的应用范围是很广泛的。

猜你喜欢

转载自blog.csdn.net/majinlei121/article/details/83902497
今日推荐