通用动态数组(三)——算法排序

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


你可能感兴趣的:(数据结构、动态数组、排序算法)