关于快速排序的一些优化思考

工作快2年了,大学搞算法搞得还算可以,可是毕竟工作之后接触的东西,能用上高级算法的地方少之又少

最近复习了一下数据结构和算法,结合最近学的一些知识,我对快速排序这个算法有了一个新的想法

那就是,将数据按一定区域划分,比如按50W以下,50W-500W,500W-5000W,5000W以上划分4个区域

然后再结合OpenMP的优化指令,启动4个线程去排序这4个区域的数据

那么如果数据划分到区域比较均匀的话,每个区域的数据排序时间期望就是 4 * (n/4) * lg(n/4),时间肯定比n*lgn快不少

关于OpenMP学习的,可以参考IBM写的文章:http://www.ibm.com/developerworks/cn/aix/library/au-aix-openmp-framework/

以下是我的一些测试结果,贴给大家看一下:

数据分布结构:

data01.in:
50W以下数据:427
500W以下数据:2606
5000W以下数据:16118
5000W以上数据:80849
data02.in:
50W以下数据:4041
500W以下数据:25638
5000W以下数据:160216
5000W以上数据:810105
data03.in:
50W以下数据:20157
500W以下数据:128289
5000W以下数据:799429
5000W以上数据:4052125
data04.in:
50W以下数据:40933
500W以下数据:255923
5000W以下数据:1598082
5000W以上数据:8105062
data05.in:
50W以下数据:81315
500W以下数据:511307
5000W以下数据:3193321
5000W以上数据:16214057
data06.in:
50W以下数据:121769
500W以下数据:770166
5000W以下数据:4793358
5000W以上数据:24314707
data07.in:
50W以下数据:162871
500W以下数据:1023665
5000W以下数据:6388110
5000W以上数据:32425354
请按任意键继续. . .

使用了OpenMP优化的qsort结果

data01.in:
总共耗时:32
读入数据时间:18
排序所用时间:14
data02.in:
总共耗时:343
读入数据时间:170
排序所用时间:173
data03.in:
总共耗时:1785
读入数据时间:814
排序所用时间:971
data04.in:
总共耗时:3610
读入数据时间:1614
排序所用时间:1996
data05.in:
总共耗时:7343
读入数据时间:3213
排序所用时间:4130
data06.in:
总共耗时:11187
读入数据时间:4851
排序所用时间:6336
data07.in:
总共耗时:14994
读入数据时间:6464
排序所用时间:8530
请按任意键继续. . .


没有使用OpenMP优化的qsort结果

data01.in:
总共耗时:33
读入数据时间:18
排序所用时间:15
data02.in:
总共耗时:340
读入数据时间:159
排序所用时间:181
data03.in:
总共耗时:1781
读入数据时间:787
排序所用时间:994
data04.in:
总共耗时:3617
读入数据时间:1552
排序所用时间:2065
data05.in:
总共耗时:7361
读入数据时间:3118
排序所用时间:4243
data06.in:
总共耗时:11206
读入数据时间:4670
排序所用时间:6536
data07.in:
总共耗时:15086
读入数据时间:6190
排序所用时间:8896
请按任意键继续. . .

从结果来看,好像并没有什么差异,有可能是编译器自动就会做优化,把运算过程自动交到其他线程去处理吧

也有可能是由于数据分布不均匀,导致效果不明显,不过无论如何,OpenMP版快速排序最多也就退化到原本快速排序应有的效率而已

而且编写难度也没有增加太多,这种思路还是值得探究的


最后,附上我写的一些程序,以供大家研究:

OpenMP版快速排序:

#include <stdio.h>
#include <stdlib.h>
#include <omp.h>
#include <time.h>

void   qsort(int lt,int rt,int * number);
int number[100000];
int * range[4];

inline int getRange(int num)
{
    if (num > 50000000) return 3;  // >5000W
    if (num > 5000000) return 2;  // >500W
    if (num > 500000) return 1;  // >50W
    return 0;
}

int main()
{
    for (int i=0;i<4;++i)
    {
        range[i] = new int[50000000];
    }
    int n,num,j,len;
    char file[100];
    FILE * fileIn;
    for (int Case=1;Case<8;++Case) {
        sprintf(file,"data%02d.in",Case);
        //freopen(file,"r",stdin);
        fileIn = fopen(file,"r");
        for (int i=0;i<4;++i)
        {
            range[i][0] = 0;
        }
        clock_t begin_time = clock();
        fscanf(fileIn,"%d",&n);
        for (int i=1;i<=n;++i)
        {
            //读数分类
            fscanf(fileIn,"%d",&num);
            j = getRange(num);
            len = ++range[j][0];
            range[j][len] = num;
        }
        clock_t read_finish = clock();
        //openmp分布处理
        omp_set_num_threads(4);
        #pragma omp parallel for
        for (int i=0;i<4;++i)
        {
            qsort(1,range[i][0],range[i]);
        }
        clock_t sort_finish = clock();
        printf("data%02d.in:\n",Case);
        printf("50W以下数据:%d\n",range[0][0]);
        printf("500W以下数据:%d\n",range[1][0]);
        printf("5000W以下数据:%d\n",range[2][0]);
        printf("5000W以上数据:%d\n",range[3][0]);
        printf("总共耗时:%d\n",sort_finish - begin_time);
        printf("读入数据时间:%d\n",read_finish - begin_time);
        printf("排序所用时间:%d\n",sort_finish - read_finish);
        fclose(fileIn);
    }
    for (int i=0;i<4;++i)
    {
        delete [] range[i];
    }
    system("pause");
    return 0;
}

void   qsort(int lt,int rt,int * number)
{
    if (rt <= lt) return;
    int mid = (lt + rt) >> 1;
    int midVal = number[mid];
    int i = lt,j = rt;
    int tmp;
    do
    {
        while (i < rt && number[i] < midVal) ++i;
        while (j > lt && number[j] > midVal) --j;
        if (i <= j)
        {
            tmp = number[i];
            number[i] = number[j];
            number[j] = tmp;
            ++i;
            --j;
        }
    }while (i <= j);
    if (i < rt) qsort(i,rt,number);
    if (lt < j) qsort(lt,j,number);
}


正常快速排序:

#include <stdio.h>
#include <stdlib.h>
#include <time.h>

void   qsort(int lt,int rt,int * number);
int number[50000000];

int main()
{
    int n,num,j,len;
    char file[100];
    FILE * fileIn;
    for (int Case=1;Case<8;++Case) {
        sprintf(file,"data%02d.in",Case);
        //freopen(file,"r",stdin);
        fileIn = fopen(file,"r");
        clock_t begin_time = clock();
        fscanf(fileIn,"%d",&n);
        for (int i=1;i<=n;++i)
        {
            fscanf(fileIn,"%d",number+i);
        }
        clock_t read_finish = clock();
        qsort(1,n,number);
        clock_t sort_finish = clock();
        printf("data%02d.in:\n",Case);
        printf("总共耗时:%d\n",sort_finish - begin_time);
        printf("读入数据时间:%d\n",read_finish - begin_time);
        printf("排序所用时间:%d\n",sort_finish - read_finish);
        fclose(fileIn);
    }
    system("pause");
    return 0;
}

void   qsort(int lt,int rt,int * number)
{
    if (rt <= lt) return;
    int mid = (lt + rt) >> 1;
    int midVal = number[mid];
    int i = lt,j = rt;
    int tmp;
    do
    {
        while (i < rt && number[i] < midVal) ++i;
        while (j > lt && number[j] > midVal) --j;
        if (i <= j)
        {
            tmp = number[i];
            number[i] = number[j];
            number[j] = tmp;
            ++i;
            --j;
        }
    }while (i <= j);
    if (i < rt) qsort(i,rt,number);
    if (lt < j) qsort(lt,j,number);
}


数据生成器:

#include <stdio.h>
#include <time.h>
#include <stdlib.h>

int main()
{
    int n,total;
    scanf("%d",&n);
    srand(time(0));
    freopen("data.in","w",stdout);
    printf("%d\n",n);
    for (int i=0;i<n;++i)
    {
        printf("%d ",rand() * rand());
    }
    putchar('\n');
    fclose(stdout);
    return 0;
}




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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值