#include <stdio.h> #include <stdlib.h> #include <time.h> #include <string.h> #define LENGTH (40) #define MIN (-20000) #define MAX (20000) /****************************************************************************************/ /*! * \brief Swaps two integers. *

ote On exit, what was in 'a' will be in 'b', and vice versa. */ void swap ( int * a , int * b ) { int tmp = * a ; * a = * b ; * b = tmp ; } /****************************************************************************************/ /*! * \brief Compare two integers, used to determine sort order. * \return Negative if the _first_ argument should come before the second, 0 or positive * otherwise. */ int compare ( int a , int b ) { return ( a - b ); } /****************************************************************************************/ /*! * \brief Take two ordered arrays of integers and merge them together into a single array * in a way that preserves the original ordering. * \param a The first array. * \param b The second array. * \param a_length The length of the first array. * \param b_length The length of the second array. * \param compare A comparator that returns less than 0 if the first argument should * come before the second; any other value is assumed to mean the second * argument should come first in the returned array. * \return An ordered array that combines the elements of the two argument * arrays. *

ote 'a' _must_ point to a block large enough to contain the combined array. *

ote 'compare' must _not_ be null. */ int * merge_subarrays ( int * a , unsigned a_length , int * b , unsigned b_length , int ( * compare )( int , int )) { unsigned length = a_length + b_length ; int * scratch_buffer = ( int * ) malloc ( length * sizeof ( int )); int a_read_index = 0 , b_read_index = 0 ; int ret_write_index = 0 ; do { /* both arrays still have unused elements remaining? */ if (( a_read_index < a_length ) && ( b_read_index < b_length )) { /* yes - compare the current elements; the one with */ /* the lower index then gets copied into the dest */ if ( compare ( a [ a_read_index ], b [ b_read_index ]) < 0 ) { /* the next element of a should go first */ scratch_buffer [ ret_write_index ] = a [ a_read_index ]; a_read_index ++ ; } else { /* the next element of b should go first */ scratch_buffer [ ret_write_index ] = b [ b_read_index ]; b_read_index ++ ; } } else { /* no - who still has elements we didn't copy yet? */ /* finish copying them... */ if ( a_read_index < a_length ) { scratch_buffer [ ret_write_index ] = a [ a_read_index ]; a_read_index ++ ; } if ( b_read_index < b_length ) { scratch_buffer [ ret_write_index ] = b [ b_read_index ]; b_read_index ++ ; } } ret_write_index ++ ; } while ( ret_write_index < length ); memcpy ( a , scratch_buffer , sizeof ( int ) * length ); free ( scratch_buffer ); return a ; } /****************************************************************************************/ /*! * \brief Recursively sort an array by splitting it in half, sorting the two halves, * and merging the resulting sub-arrays back together. * \param to_be_sorted An array of integers whose contents should have been sorted on * return. * \param length The number of elements in the array we'll be sorting. * \param compare A comparator that tells what order array elements should go in. *

ote The comparator should return less than 0 if the _first_ argument should * come before the second. *

ote 'compare' must _not_ be null. */ int * sort_subarray ( int * to_be_sorted , int length , int ( * compare )( int , int )) { /* Cases that end the recursion */ if ( length <= 2 ) { /* Do we have a pair of elements? Sort them.... */ if ( length == 2 ) { if ( compare ( to_be_sorted [ 0 ], to_be_sorted [ 1 ]) > 0 ) { swap ( & to_be_sorted [ 0 ], & to_be_sorted [ 1 ]); } } /* Otherwise, we only have 1 number, which is inherently */ /* already sorted - nothing to do... */ /* already sorted the trivial/base cases, so send back */ /* up to the caller to merge them... */ return to_be_sorted ; } int * list_a , * list_b ; int a_length , b_length ; /* split it down the centre into subarrays */ list_a = to_be_sorted ; a_length = length >> 1 ; list_b = & to_be_sorted [ a_length ]; b_length = length - a_length ; /* send a sorted array up to the caller (which might be us) */ return ( merge_subarrays ( sort_subarray ( list_a , a_length , compare ), a_length , sort_subarray ( list_b , b_length , compare ), b_length , compare )); } /****************************************************************************************/ int main ( void ) { int i ; int to_sort [ LENGTH ]; srand (( unsigned ) time ( NULL )); for ( i = 0 ; i < LENGTH ; i ++ ) { to_sort [ i ] = ( rand () % ( MAX - MIN )) + MIN ; } printf ( "

------------ \t before sorting:

" ); for ( i = 0 ; i < LENGTH ; i ++ ) { printf ( "%9d

" , to_sort [ i ]); } sort_subarray ( to_sort , LENGTH , compare ); printf ( "

------------ \t after sorting:

" ); for ( i = 0 ; i < LENGTH ; i ++ ) { printf ( "%9d

" , to_sort [ i ]); } return 0 ; }