快速排序和归并排序的C语言实现和两者排序在各个量级的数据量下效率对比

 1 #include<stdio.h>
 2 #include<stdlib.h>
 3 #include<unistd.h>
 4 #include<string.h>
 5 #include<errno.h>
 6 
 7 #include"fastsort.h"
 8 
 9 #if 0
10 #define DEBUG(...) printf(__VA_ARGS__)
11 #else
12 #define DEBUG(...)
13 #endif
14 
15 
16 /*-fastsort
17  * @d: a pointer to the array which save the data
18  * @datasize: each data's size in byte
19  * @left,right: the min and max index
20  * @cmp: the callback function used to compare the data
21     an example for cmp, assume they are int data, and order from small to big
22     int cmp(void *a, void *b)
23     {
24         return (*((int *)a) < *((int *)b));
25     }
26  */
27 int fastsort(void *d, const int datasize, const int left, const int right, int (*cmp)(void *, void *))
28 {
29     char *data = d;
30     int hole,l,r,ret;
31     void *tempdata = NULL;
32     
33     if(NULL == d || datasize < 1 || left < 0 || right < 0 || NULL == cmp){
34         return -1;
35     }
36     
37     if(left >= right){  // normal exit
38         return 0;
39     }
40     
41     hole = left;
42     l = left;
43     r = right;
44     
45     tempdata = malloc(datasize);
46     if(NULL == tempdata){
47         perror("malloc()");
48         exit(1);
49     }
50 
51     memcpy(tempdata, &data[datasize * hole], datasize);  // tempdata = data[hole];
52     while(l < r){
53         while(l < r){
54             if(cmp(&data[datasize * r], tempdata)){
55                 memcpy(&data[datasize * hole], &data[datasize * r], datasize);
56                 hole = r;
57                 break;
58             }
59             --r;
60         }
61 
62         while(l < r){
63             if(cmp(tempdata, &data[datasize * l])){
64                 memcpy(&data[datasize * hole], &data[datasize * l], datasize);
65                 hole = l;
66                 break;
67             }
68             ++l;
69         }
70     }
71     
72     memcpy(&data[datasize * hole], tempdata, datasize);
73     free(tempdata);
74 
75     // loop
76     if(left < hole-1){
77         ret = fastsort(d, datasize, left, hole-1, cmp);
78         if(ret < 0){
79             printf("(%d)Error %d, from %d to %d\n", __LINE__, ret, left, hole-1);
80             return ret;
81         }
82     }
83     
84     if(hole+1 < right){
85         ret = fastsort(d, datasize, hole+1, right, cmp);
86         if(ret < 0){
87             printf("(%d)Error %d, from %d to %d\n", __LINE__, ret, hole+1, right);
88             return ret;
89         }
90     }
91     return 0;
92 }
fastsort.c
  1 #include<stdio.h>
  2 #include<stdlib.h>
  3 #include<unistd.h>
  4 #include<string.h>
  5 #include<errno.h>
  6 
  7 #include"mergesort.h"
  8 
  9 #if 0
 10 #define DEBUG(...) printf(__VA_ARGS__)
 11 #else
 12 #define DEBUG(...)
 13 #endif
 14 
 15 
 16 int mergesort(void *d, const int datasize, const int left, const int right, int (*cmp)(void *, void *))
 17 {
 18     char *data = d;
 19     int diff = right - left;
 20     void *tempdata = NULL;
 21     char *temparr = NULL;
 22     int ret = 0;
 23     int l, r;
 24     int i;
 25 
 26     if(NULL == d || datasize < 1 || left < 0 || right < 0 || NULL == cmp){
 27         printf("Error: bad param\n");
 28         return -1;
 29     }
 30 
 31     if(diff == 0){
 32         return 0;
 33     }
 34 
 35     tempdata = malloc(datasize);
 36     if(NULL == tempdata){
 37         perror("malloc()");
 38         return -1;
 39     }
 40 
 41     if(diff > 1){
 42         //DEBUG("before left(%d\t%d) and right(%d\t%d), the arr is\n", left, left + diff/2, left + diff/2 + 1, right); showarr(d, 10);
 43         // sort left and right part
 44         ret = mergesort(d, datasize, left, left + diff/2, cmp);
 45         if(ret < 0){
 46             printf("Error: in left part (%d, %d)\n", left, left + diff/2);
 47             free(tempdata);
 48             return -1;
 49         }
 50         ret = mergesort(d, datasize, left + diff/2 + 1, right, cmp);
 51         if(ret < 0){
 52             printf("Error: in right part (%d, %d)\n", left + diff/2 + 1, right);
 53             free(tempdata);
 54             return -1;
 55         }
 56 
 57         //DEBUG("after left(%d\t%d) and right(%d\t%d), the arr is\n", left, left + diff/2, left + diff/2 + 1, right); showarr(d, 10);printf("\n\n\n");
 58         
 59         // merge
 60         temparr = malloc(datasize * (right - left + 1));  // save data
 61         if(NULL == temparr){
 62             perror("malloc()");
 63             free(tempdata);
 64             return -1;
 65         }
 66 
 67         l = left;
 68         r = left + diff/2 + 1;
 69         for(i=0;i<(right - left + 1);i++){
 70             if(l <= left + diff/2 && r <= right){
 71                 if( cmp(&data[datasize * l], &data[datasize * r]) ){
 72                     memcpy(&temparr[datasize * i], &data[datasize * l], datasize);
 73                     ++l;
 74                 }
 75                 else{
 76                     memcpy(&temparr[datasize * i], &data[datasize * r], datasize);
 77                     ++r;
 78                 }
 79             }
 80             else{
 81                 if(l > left + diff/2){
 82                     memcpy(&temparr[datasize * i], &data[datasize * r], datasize * (right - left + 1 - i));
 83                 }
 84                 else{
 85                     memcpy(&temparr[datasize * i], &data[datasize * l], datasize * (right - left + 1 - i));
 86                 }
 87                 break;  // no matter which part is over, we just need to copy the rest data in one time and finish for loop
 88             }
 89         }
 90         // in temparr, the data has been sorted
 91         memcpy(&data[datasize * left], temparr, datasize * (right - left + 1));
 92         free(temparr);
 93     }
 94     else if(diff == 1){ // only 2 data to compare
 95         if(! cmp(&data[datasize * left], &data[datasize * right])){
 96             memcpy(tempdata, &data[datasize * left], datasize);
 97             memcpy(&data[datasize * left], &data[datasize * right], datasize);
 98             memcpy(&data[datasize * right], tempdata, datasize);
 99         }
100     }
101     else if(diff < 0){  // should not happen
102         printf("Error: wrong diff %d\n", diff);
103         ret = -1;
104     }
105 
106     free(tempdata);
107     return ret;
108 }
mergesort.c
  1 #include<stdio.h>
  2 #include<stdlib.h>
  3 #include<unistd.h>
  4 #include<string.h>
  5 #include<errno.h>
  6 
  7 #include<time.h>
  8 
  9 #include"fastsort.h"
 10 #include"mergesort.h"
 11 
 12 
 13 #if 0
 14 #define DEBUG(...) printf(__VA_ARGS__)
 15 #else
 16 #define DEBUG(...)
 17 #endif
 18 
 19 #define TEST_HOWMANY_DATASIZE (1)
 20 
 21 
 22 /*
 23 struct timespec {
 24     time_t     tv_sec;        // seconds 
 25     long     tv_nsec;        // nanoseconds
 26 };
 27 */
 28 
 29 void showarr(int *arr, int size)
 30 {
 31     for(int i=0;i<size;i++){
 32         printf("%d\t", arr[i]);
 33     }
 34     printf("\n\n\n");
 35     return;
 36 }
 37 
 38 int cmp(void *a, void *b)
 39 {
 40     return (*((int *)a) < *((int *)b));
 41 }
 42 
 43 
 44 #if 0 // basic test
 45 int main(void)
 46 {
 47     int arr1[] = {50   ,   92   ,   67  ,    64  ,    70    ,  79   ,   96  ,    7    ,   6     ,  3};
 48     showarr(arr1, sizeof(arr1)/sizeof(*arr1));
 49     mergesort(arr1, sizeof(*arr1), 0, sizeof(arr1)/sizeof(*arr1) - 1, cmp);
 50     showarr(arr1, sizeof(arr1)/sizeof(*arr1));
 51     return 0;
 52 }
 53 
 54 #else
 55 
 56 #define TEST_DATASIZE (2200)
 57 #define LOOP_TIMES (10000)
 58 
 59 int main(int argc, char *argv[])
 60 {
 61     int arr1[TEST_DATASIZE],arr2[TEST_DATASIZE];
 62     int i,j;
 63     long long int fast_time = 0, merge_time = 0;
 64     struct timespec start_time,end_time;
 65 
 66 #if TEST_HOWMANY_DATASIZE
 67     long int f1, m1;
 68     int fast_win_count = 0;
 69 #endif
 70 
 71     
 72     srand(time(NULL));
 73     for(j=0;j<LOOP_TIMES;j++){
 74         for(i=0;i<TEST_DATASIZE;i++){
 75                 arr1[i] = rand();
 76         }
 77         memcpy(arr2, arr1, sizeof(arr2));
 78         //showarr(arr1, TEST_DATASIZE);
 79         clock_gettime(CLOCK_REALTIME, &start_time);
 80         fastsort(arr1, sizeof(int), 0, sizeof(arr1)/sizeof(*arr1) -1, cmp);
 81         clock_gettime(CLOCK_REALTIME, &end_time);
 82         fast_time += ( 1e9 * (end_time.tv_sec - start_time.tv_sec) + (end_time.tv_nsec - start_time.tv_nsec) );
 83 
 84 #if TEST_HOWMANY_DATASIZE
 85         long int f1, m1;
 86         f1 = ( 1e9 * (end_time.tv_sec - start_time.tv_sec) + (end_time.tv_nsec - start_time.tv_nsec) );
 87         DEBUG("%d\ttime fast  :%ld\n", j+1, f1);
 88 #endif
 89 
 90         clock_gettime(CLOCK_REALTIME, &start_time);
 91         mergesort(arr2, sizeof(int), 0, sizeof(arr1)/sizeof(*arr1) -1, cmp);
 92         clock_gettime(CLOCK_REALTIME, &end_time);
 93         merge_time += ( 1e9 * (end_time.tv_sec - start_time.tv_sec) + (end_time.tv_nsec - start_time.tv_nsec) );
 94 
 95 #if TEST_HOWMANY_DATASIZE
 96         m1 = ( 1e9 * (end_time.tv_sec - start_time.tv_sec) + (end_time.tv_nsec - start_time.tv_nsec) );
 97         DEBUG("%d\ttime merge :%ld\n\n", j+1, m1);
 98         if(f1 < m1){
 99             ++fast_win_count;
100         }
101 #endif
102     }
103 
104     //showarr(arr1, TEST_DATASIZE);
105     //showarr(arr2, TEST_DATASIZE);
106     
107     printf("test data %d loop %d times\n", TEST_DATASIZE, LOOP_TIMES);
108     printf("fast  spend time %lld ns\n", fast_time);
109     printf("merge spend time %lld ns\n", merge_time);
110 #if TEST_HOWMANY_DATASIZE
111     printf("total %d times, fast win %d times(%f%%)\n", LOOP_TIMES, fast_win_count, (100.0*fast_win_count/LOOP_TIMES));
112 #endif
113 
114 
115     return 0;
116 }
117 #endif
main.c
gsp@gsp-VirtualBox:~/share_to_win10/gsp/basic/sort_realize$ ./main
test data 2200 loop 10000 times
fast  spend time 12710266257 ns
merge spend time 15906010158 ns
total 10000 times, fast win 8389 times(83.890000%)
gsp@gsp-VirtualBox:~/share_to_win10/gsp/basic/sort_realize$ ./main
test data 2200 loop 10000 times
fast  spend time 12580529048 ns
merge spend time 14882789401 ns
total 10000 times, fast win 8553 times(85.530000%)
gsp@gsp-VirtualBox:~/share_to_win10/gsp/basic/sort_realize$ 

 

粗略的测了一下:

数据在1000~5000的区间里,快速排序(fast)比归并排序(merge)用时少的概率是80%左右。

数据在100~1000的区间里,快速排序(fast)比归并排序(merge)用时少的概率是90%左右。

如果数据超过5000,数据越大,快速排序的优势好像越不明显了,就是说上述的概论在向50%趋近。

 

PS:上述测试在Ubuntu16.04 x64虚拟机上测的。

PPS:效率的差异和我写的代码质量有没有关系也没有具体分析。和我测试的环境有没有关系也不清楚。

 

posted on 2022-07-02 02:36  寻丶枫  阅读(30)  评论(0编辑  收藏  举报

导航