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

来源:互联网 发布:js 360全景图 编辑:程序博客网 时间:2024/06/06 04:49

工作快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以下数据:427500W以下数据:26065000W以下数据:161185000W以上数据:80849data02.in:50W以下数据:4041500W以下数据:256385000W以下数据:1602165000W以上数据:810105data03.in:50W以下数据:20157500W以下数据:1282895000W以下数据:7994295000W以上数据:4052125data04.in:50W以下数据:40933500W以下数据:2559235000W以下数据:15980825000W以上数据:8105062data05.in:50W以下数据:81315500W以下数据:5113075000W以下数据:31933215000W以上数据:16214057data06.in:50W以下数据:121769500W以下数据:7701665000W以下数据:47933585000W以上数据:24314707data07.in:50W以下数据:162871500W以下数据:10236655000W以下数据:63881105000W以上数据:32425354请按任意键继续. . .

使用了OpenMP优化的qsort结果

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


没有使用OpenMP优化的qsort结果

data01.in:总共耗时:33读入数据时间:18排序所用时间:15data02.in:总共耗时:340读入数据时间:159排序所用时间:181data03.in:总共耗时:1781读入数据时间:787排序所用时间:994data04.in:总共耗时:3617读入数据时间:1552排序所用时间:2065data05.in:总共耗时:7361读入数据时间:3118排序所用时间:4243data06.in:总共耗时:11206读入数据时间:4670排序所用时间:6536data07.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
原创粉丝点击