/*************************************sort.h****************************/ #ifndef SORT_H #define SORT_H #include "type.h" #ifdef __cplusplus extern "C"{ #endif /*basic---complex:O(n*n)*/ Ret bubble_sort(void** array, size_t nr, DataCompareFunc cmp); Ret select_sort(void** array, size_t nr, DataCompareFunc cmp); Ret insert_sort(void** array, size_t nr, DataCompareFunc cmp); /*shell---complex:<O(n*n)*/ Ret shell_sort(void** array, size_t nr, DataCompareFunc cmp); /*quick---complex:O(nlogn)*/ Ret quick_sort(void** array, size_t nr, DataCompareFunc cmp); /*merge*/ Ret merge_sort(void** array, size_t nr, DataCompareFunc cmp); /*heap*/ Ret heap_sort(void** array, size_t nr, DataCompareFunc cmp); #ifdef __cplusplus } #endif #endif
/***************************************sort.c*****************************************/ #include "sort.h" Ret bubble_sort(void** array, size_t nr, DataCompareFunc cmp) { size_t i = 0; size_t j = 0; void* data = 0; return_val_if_fail(array != NULL && cmp != NULL, RET_INVALID_PARAMETER); for(i = 0; i < nr -1; i++) { for(j = 0; j < (nr-1-i); j++) { if(cmp(array[j], array[j+1]) > 0) { data = array[j]; array[j] = array[j+1]; array[j+1] = data; } } } return RET_OK; } Ret select_sort(void** array, size_t nr, DataCompareFunc cmp) { size_t i = 0; size_t j = 0; size_t min = 0; void* data = 0; return_val_if_fail(array != NULL && cmp != NULL, RET_INVALID_PARAMETER); for(i = 0; i < nr; i++) { min = i; for(j = i+1; j < nr; j++) { if(cmp(array[j], array[min]) < 0) { min = j; } } if(min != i) { data = array[i]; array[i] = array[min]; array[min] = data; } } return RET_OK; } Ret insert_sort(void** array, size_t nr, DataCompareFunc cmp) { size_t i = 0; size_t j = 0; void* data = 0; return_val_if_fail(array != NULL && cmp != NULL, RET_INVALID_PARAMETER); //choose the smallest elemnt as sentinel key and store into array[0] for(i = nr - 1; i > 0; i--) { if(cmp(array[i], array[i-1]) < 0) { data = array[i-1]; array[i-1] = array[i]; array[i] = data; } } for(i = 2; i < nr; i++) { j = i; data = array[i]; while(cmp(data, array[j-1]) < 0) { array[j] = array[j-1]; j--; } array[j] = data; } return RET_OK; } Ret shell_sort(void** array, size_t nr, DataCompareFunc cmp) { size_t i = 0; size_t j = 0; size_t h = 0; void *data = 0; return_val_if_fail(array != NULL && cmp != NULL, RET_INVALID_PARAMETER); //generate max grap h value for(h = 1; h < (nr-1)/9; h = 3*h+1); //append a cycle on the base of basic insert sort for(; h > 0; h /= 3) { for(i = h; i < nr; i++) { j = i; data = array[i]; while(j >= h && cmp(data, array[j-h]) < 0) { array[j] = array[j-h]; j -= h; } array[j] = data; } } return RET_OK; } static void quick_sort_implement(void** array, size_t low, size_t high, DataCompareFunc cmp) { size_t save_low = low; size_t save_high = high; void *data = array[low]; /*move item that less than data to left, otherwise to right*/ while(low < high) { while(cmp(array[high], data) >= 0 && (low < high)) high--; if(low != high) { array[low] = array[high]; low++; } while(cmp(array[low], data) <= 0 && (low < high)) low++; if(low != high) { array[high] = array[low]; high--; } } array[low] = data; /*left partion sort*/ if(save_low < low) { quick_sort_implement(array, save_low, low-1, cmp); } /*right partion sort*/ if(save_high > high) { quick_sort_implement(array, low+1, save_high, cmp); } return; } Ret quick_sort(void** array, size_t nr, DataCompareFunc cmp) { return_val_if_fail(array != NULL && cmp != NULL, RET_INVALID_PARAMETER); if(nr > 1) { quick_sort_implement(array, 0, nr-1, cmp); } return RET_OK; } static Ret merge_sort_implement(void** storage, void** array, size_t low, size_t mid, size_t high, DataCompareFunc cmp) { size_t i = low; //all part size_t j = low; //left part size_t k = mid; //right part /*merge left part*/ if((low+1) < mid) { size_t x = low + ((mid-low)>>1); merge_sort_implement(storage, array, low, x, mid, cmp); } /*merge right part*/ if((mid+1) < high) { size_t x = mid + ((high-mid)>>1); merge_sort_implement(storage, array, mid, x, high, cmp); } /*merge two sequece part*/ while(j < mid && k < high) { if(cmp(array[j], array[k]) <= 0) { storage[i++] = array[j++]; } else { storage[i++] = array[k++]; } } while(j < mid) { storage[i++] = array[j++]; } while(k < high) { storage[i++] = array[k++]; } for(i = low; i < high; i++) { array[i] = storage[i]; } return RET_OK; } Ret merge_sort(void** array, size_t nr, DataCompareFunc cmp) { Ret ret = RET_FAIL; void** storage = NULL; return_val_if_fail(array != NULL && cmp != NULL, RET_INVALID_PARAMETER); if(nr > 1) { storage = (void**)malloc(sizeof(void *) * nr); if(storage == NULL) { ret = RET_OOM; } else { ret = merge_sort_implement(storage, array, 0, nr>>1, nr, cmp); free(storage); storage = NULL; } } return ret; } static void heap_adjust(void** array, size_t index, size_t nr, DataCompareFunc cmp) { size_t j = 0; void* data = array[index]; for(j = 2 * index; j <= nr; j *= 2) { if(j < nr && cmp(array[j], array[j+1]) < 0) { j++; } /*max heap*/ if(cmp(data, array[j]) > 0) { break; } array[index] = array[j]; index = j; } array[index] = data; return; } Ret heap_sort(void** array, size_t nr, DataCompareFunc cmp) { size_t i; void* data; void** parray; Ret ret = RET_OK; return_val_if_fail( array != NULL && cmp != NULL, RET_INVALID_PARAMETER); if(nr > 1) { /* *adapt array like this way a[1]..a[n] *in order to use the adjust algrith */ parray = array - 1;//parray[1] == array[0] /*create max top heap and start to adjust from array[n/2]*/ for( i = (nr >> 1); i > 0; i--) { heap_adjust(parray, i, nr, cmp); } /* *exchange heap top value and tail value, and *adjust the left in cycle until heap is null. */ for(i = nr; i > 1; --i) { data = parray[1]; //max value == top value parray[1] = parray[i]; parray[i] = data; heap_adjust(parray, 1, i-1, cmp); } } return ret; }
/*****************************sort_test.c*******************************************/ #include "darray.h" #include "sort.h" #include "test_helper.c" //#define BUBBLE_SORT //#define INSERT_SORT //#define SHELL_SORT //#define QUICK_SORT //#define MERGE_SORT #define HEAP_SORT static void sort_test() { int i = 0; int data[] = {2, 4, 1, 6, 3, 3, 4, 5, 7, 8, 9, 0,12,13,11}; //int data[] = {49, 38, 65, 97 ,76, 13, 27, 49}; int num = sizeof(data) / sizeof(*data); DArray* this = NULL; this = darray_create(NULL, NULL); if(NULL == this) { return; } for(i = 0; i < num; i++) { assert(darray_append(this, (void* )data[i]) == RET_OK); } assert(darray_length(this) == num); assert(darray_foreach(this, print_int, NULL) == RET_OK); printf("\n"); #if defined (BUBBLE_SORT) assert(darray_sort(this, (DataSortFunc)bubble_sort, int_cmp) == RET_OK); #elif defined(INSERT_SORT) assert(darray_sort(this, (DataSortFunc)insert_sort, int_cmp) == RET_OK); #elif defined(SHELL_SORT) assert(darray_sort(this, (DataSortFunc)shell_sort, int_cmp) == RET_OK); #elif defined(QUICK_SORT) assert(darray_sort(this, (DataSortFunc)quick_sort, int_cmp) == RET_OK); #elif defined(MERGE_SORT) assert(darray_sort(this, (DataSortFunc)merge_sort, int_cmp) == RET_OK); #elif defined(HEAP_SORT) assert(darray_sort(this, (DataSortFunc)heap_sort, int_cmp) == RET_OK); #endif assert(darray_foreach(this, print_int, NULL) == RET_OK); printf("\n"); darray_destroy(this); } int main() { sort_test(); return 0; }