/*************************************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;
}