5.2.5 三数取中划分快速排序算法

前言

每次选三个数(第一个、最后一个、倒二个),以到二个作为中位数进行分治排序


#include <bits/stdc++.h>
using namespace std;
#define ElemType int
#define M 10

ElemType arr[1000005], arr2[1000005];
int vis[1000005];

void SelectSort(ElemType arr[], int len) {
    int i, j, minidx;
    for(i = 0; i < len - 1; i++) {
        minidx = i;
        for (j = i+1; j < len; j++)
            if(arr[j]<arr[minidx])
                minidx = j;
        if(minidx^i) {
            ElemType tmp = arr[i];
            arr[i] = arr[minidx];
            arr[minidx] = tmp;
        }
    }
}

int partition(ElemType arr[], int l, int r) {
    int tag = arr[r];
    while(l < r) {
        while(l < r && arr[l] <= tag) l++;
        while(l < r && arr[r]>=tag) r--;
        if(l < r)
            swap(arr[l], arr[r]);
    }
    return l;
}

void QuickSort(ElemType arr[], int l, int r) {
    if(r-l <= M) { //小规模改用非递归算法
        SelectSort(arr+l, r-l+1);
        return ;
    }

    //取三个的中位数放到r-1的位置上,并且让其余两个分别置于中位数的两侧
    swap(arr[l+(r-l>>1)], arr[r-1]);
    if(arr[l] > arr[r-1]) swap(arr[l], arr[r-1]);
    if(arr[l] > arr[r]) swap(arr[l], arr[r]);
    if(arr[r-1] > arr[r]) swap(arr[r], arr[r-1]);
    
    int idx=partition(arr, l+1, r-1);
	swap(arr[idx], arr[r-1]);
	
    QuickSort(arr, l, idx-1);
    QuickSort(arr, idx+1, r);

    return ;
}


//

// 排序时间性能测试
void SortFunctionPerformance(const char* name, ElemType arr[], int len, void(*fun_ptr)(ElemType arr[], int l, int r))
{
    double dur;
    clock_t start,end;
    printf("%s 时间性能测试, 待排数组长度 : %d\n", name, len);
    start = clock();
    fun_ptr(arr, 0, len-1); //测试的函数
    end = clock();
    dur = (double)(end - start);
    printf("Use Time:%f\n",(dur/CLOCKS_PER_SEC));
}

// 生成一个随机序列
void MakeRandSquence(ElemType arr[], int len) {
    srand(time(NULL));
    for(int i=0; i<len; i++)
        arr[i]=rand();
}

// 生成一个基本有序序列, 即逆序对很少
void MakeBasicOrderSquence(ElemType arr[], int len) {
    srand(time(NULL));
    for(int i=0; i<len; i++)
        arr[i]=i+1;
    int n = len / 10; //随机修改10%
    n = !n ? 1 : n;   //保证至少会打乱2个位置
    int k, s, sz = 0;     //保证不会产生交换环
    for(int i=0; i<n; i++) {
R1:     k=rand()%len;
        for(int j=0; j<sz; j++) if(k==vis[j]) goto R1;
R2:     s=rand()%len;
        if(s==k) goto R2;
        for(int j=0; j<sz; j++) if(s==vis[j]) goto R2;
        //以上产生两个未有的序列
        ElemType tmp = arr[k];
        arr[k] = arr[s];
        arr[s] = tmp;
        vis[sz++] = k;
        vis[sz++] = s;
    }
}

//

int main() {
    MakeRandSquence(arr, 100000);
    for(int i=0; i<10; i++) cout << arr[i] << ' '; cout << endl;
    SortFunctionPerformance("三数取中快速排序", arr, 100000, QuickSort);
    for(int i=0; i<10; i++) cout << arr[i] << ' '; cout << endl;
    MakeBasicOrderSquence(arr, 100000);
    for(int i=0; i<10; i++) cout << arr[i] << ' '; cout << endl;
    SortFunctionPerformance("三数取中快速排序", arr, 100000, QuickSort);
    for(int i=0; i<10; i++) cout << arr[i] << ' '; cout << endl;
    return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

小胡同的诗

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值