双路快速排序

背景

目录

背景

思路

完整实现


解决单路快速排序所存在的问题,即:在基准值存在大量重复值时,(>=v)部分和(<v)部分分配及其不均衡,算法会退步称为 0(n2) 级别的算法。

为了解决这个问题,衍生出双路快速排序:

思路

其他部分和普通快速排序相同,主要更改主过程Partition部分。

 

从数组中随机选择一点将其作为基准点,并与数组第一个元素交换位置,称其为V点。

在数组中设置4个索引:

l:数组最左侧元素

r:数组最右侧元素

i:比较当前元素是否<v,起始点为(l+1)

j:比较当前元素是否>v,起始点为r

 Partition开始

i点比较当前元素是否<V,若小于V,向后移动一位,i++;若>=V,循环停止。(附加停止条件:整个数组遍历完毕,i=r)

j点比较当前元素是否>V,若大于V,向前移动一位,j--;若<=V,循环停止。(附加停止条件:整个数组遍历完毕,j=l+1)

两循环停止后,将索引 i, j 所指向的元素交换位置。

中间部分继续重复进行以上操作,直到 i,j 重合,l与 i/j 交换,此次Partiton结束。

 Partition代码实现

int _Partition_2(T arr[] , int l , int r){
    //初始化:从数组中随机选择一点将其作为基准点,并与数组第一个元素交换位置,称其为V点。
    T x = (l + rand()%(r-l+1));
    swap(arr[l],arr[x]);
    T v = arr[l];
    cout<<endl;
    int i = l+1;
    int j = r;

    //将arr[l]后的元素排序,i前为<v,i后为>v,排序后交换arr[l]和arr[i],返回i
    while (true) {
        //i点比较当前元素是否<V,若小于V,向后移动一位,i++;若>=V,循环停止。(附加停止条件:整个数组遍历完毕,i=r)
        while (arr[i] < v && i <= r) {i++;}
        //j点比较当前元素是否>V,若大于V,向前移动一位,j--;若<=V,循环停止。(附加停止条件:整个数组遍历完毕,j=l+1
        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;
}

完整实现

#include <iostream>
#include <algorithm>
#include "../SortTestHelper.h"
using namespace std;

template <typename T>
int _Partition_2(T arr[] , int l , int r){
    //初始化:从数组中随机选择一点将其作为基准点,并与数组第一个元素交换位置,称其为V点。
    T x = (l + rand()%(r-l+1));
    swap(arr[l],arr[x]);
    T v = arr[l];
    int i = l+1;
    int j = r;

    //将arr[l]后的元素排序,i前为<v,i后为>v,排序后交换arr[l]和arr[i],返回i
    while (true) {
        //i点比较当前元素是否<V,若小于V,向后移动一位,i++;若>=V,循环停止。(附加停止条件:整个数组遍历完毕,i=r)
        while (arr[i] < v && i <= r) {i++;}
        //j点比较当前元素是否>V,若大于V,向前移动一位,j--;若<=V,循环停止。(附加停止条件:整个数组遍历完毕,j=l+1
        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;
}

template <typename T>
void _quickSort2(T arr[] ,int l ,int r){
    if(l>=r){return;}
    else{
        int p = _Partition_2(arr,l,r);
        _quickSort2(arr,l,p);
        _quickSort2(arr,p+1,r);
    }
}

template <typename T>
void quickSort2(T arr[] , int n){
    srand((int)(time((NULL))));
    _quickSort2(arr,0,n-1);

}

int main(){
//测试
   int *arr = SortTestHelper::generateRandomArray(10,0,10);
    for(int i = 0;i<10;i++){
        cout<<arr[i];
    }
    cout<<endl;
   quickSort2(arr,10);
    for(int i = 0;i<10;i++){
        cout<<arr[i];
    }
    cout<<endl;
    return 0;
}

随机数产生:

srand():用于随机种子的产生,常用语法 ->srand((int)(time(NULL))),time使用前需要先导入<ctime>

产生一定范围随机数的通用表示公式 -> a + rand() % n

a: 随机数起始位置

n: 整数的范围

#include<iostream>
#include<ctime>

int main() {

    srand((int)time(NULL));
    int a = 5;
    int b = 10;

    //[a,b]  (a+rand()%(b-a+1)) ;
    //(a,b]  (a+1 + rand()%(b-a));
    //[a,b)  (a + rand()%(b-a));
    //(a,b)  (a+1 + rand()%(b-a-1));
    for (int i =0 ; i<50; i++){
        cout<<(a+1 + rand()%(b-a-1))<<"-";
    }
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值