快速排序和归并排序的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 #endifmain.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:效率的差异和我写的代码质量有没有关系也没有具体分析。和我测试的环境有没有关系也不清楚。
标签:排序,int,C语言,include,right,数据量,datasize,data,left 来源: https://www.cnblogs.com/gsp1004/p/16436370.html