Subversion Repositories programming

Rev

Rev 101 | Go to most recent revision | Blame | Compare with Previous | Last modification | View Log | RSS feed

/* Written by: Ira Snyder
 * Started on: 05-20-2005
 * Due Date: 06-10-2005
 * CS331 Project #2
 */


/* standard headers */
#include <stdio.h>
#include <stdlib.h>
#include <time.h>

/* broken-out code for common things */
#include "sorts.c"
#include "timing.c"
#include "arrays.c"


/* function prototypes */
void randomfill (int array[], unsigned long size);
int kth_smallest_method1 (int src_array[], unsigned long size, unsigned long position);
int kth_smallest_method2 (int src_array[], unsigned long size, unsigned long position);
int kth_smallest_method3 (int src_array[], unsigned long size, unsigned long position);
int kth_smallest_method4 (int src_array[], unsigned long size, unsigned long position);


int main (void)
{
    /* create new random seed */
    srand((unsigned)time(NULL));

    unsigned long size, kth_pos;
    int *array;
    int stop_looping, i;
    
    size = 10; /* set initial size to 10 */
    stop_looping = 0; /* FALSE */

    while ( !stop_looping )
    {
        /* create and fill an array with random values */
        array = create_array (size);
        randomfill (array, size);

        for (i=0; i<5; i++)
        {
            /* choose the kth position based on the handout */
            if (i==0)
                kth_pos=0;
            else if (i==1)
                kth_pos=size/4;
            else if (i==2)
                kth_pos=size/2;
            else if (i==3)
                kth_pos=3*size/4;
            else
                kth_pos=size-1;

            /* header */
            printf ("Running with size=%lu (%.3fMB) kth_pos=%lu...\n",
                    size, (size*4.0)/(1024*1024), kth_pos);
        
            /* run method1 */
            startclock();
            printf ("%luth smallest (method1): %d -- ", kth_pos, 
                    kth_smallest_method1 (array, size, kth_pos));
            stopclock();
            printtimetaken("Method1");

            /* run method2 */
            startclock();
            printf ("%luth smallest (method2): %d -- ", kth_pos, 
                    kth_smallest_method2 (array, size, kth_pos));
            stopclock();
            printtimetaken("Method2");

            /* run method3 */
            startclock();
            printf ("%luth smallest (method3): %d -- ", kth_pos, 
                    kth_smallest_method3 (array, size, kth_pos));
            stopclock();
            printtimetaken("Method3");
            
            /* run method4 */
            startclock();
            printf ("%luth smallest (method4): %d -- ", kth_pos, 
                    kth_smallest_method4 (array, size, kth_pos));
            stopclock();
            printtimetaken("Method4");
            
            /* some blank lines for spacing */
            printf ("\n\n");
        }
        
        /* free the memory that was allocated for the array */
        array = free_array (array);
        
        /* choose size according to the Project #2 handout */
        if (size < 10)
            size = 10;
        else if (size < 50)
            size = 50;
        else if (size < 100)
            size = 100;
        else if (size < 250)
            size = 250;
        else
            size *= 2;

        /* if we grow above 262.5 million elements (about 1GB), stop looping */
        if (size > 262500000)
            stop_looping = 1; /* TRUE */

    } /* end while loop */

    return 0;
}

/* fill the array with random numbers in
 * the range 0-32767 */
void randomfill (int array[], unsigned long size)
{
    unsigned long i;
        
    for (i=0; i<size; i++)
        array[i] = rand() % 32768;
}

/* Find the kth smallest element in the array (starting from zero)
 *
 * This uses the method of sorting the list, then picking
 * the correct element */
int kth_smallest_method1 (int src_array[], unsigned long size, 
        unsigned long position)
{
    int *array;
    int retval;

    array = create_array (size);
    copyarray (src_array, array, size);
    
    mergesort (array, size);

    retval = array[position];
    array = free_array (array);
    
    return retval;
}

/* Find the kth smallest element in the array (starting from zero)
 *
 * This uses the method of calling partiton() from quicksort, and
 * throwing out data that is unneeded */
int kth_smallest_method2 (int src_array[], unsigned long size, unsigned long position)
{
    int *array;
    int retval;
    unsigned long left = 0;
    unsigned long right = size-1;
    unsigned long pivotpos;
    
    array = create_array (size);
    copyarray (src_array, array, size);

    do
    {
        swap (&array[position], &array[left]);
        pivotpos = partition (array, left, right);

        if (pivotpos < position)
            left = pivotpos + 1;
        else /* pivotpos >= position) */
            right = pivotpos - 1;
    }
    while (pivotpos != position);

    retval = array[position];
    array = free_array (array);
    
    return retval;
}

/* Find the kth smallest element in the array (starting from zero)
 *
 * This uses the method of calling partiton() from quicksort, and
 * throwing out data that is unneeded
 *
 * NOTE: This is a recursive version of the algorithm above (kth_smallest_method2) */
int kth_smallest_method3 (int src_array[], unsigned long size, unsigned long position)
{
    int *array;
    int *temparray;
    int retval;
    unsigned long left = 0;
    unsigned long right = size-1;
    unsigned long pivotpos, newpos;

    array = create_array (size);
    copyarray (src_array, array, size);

    swap (&array[position], &array[left]);
    pivotpos = partition (array, left, right);

    /* base case */
    if (pivotpos == position)
    {
        retval = array[position];
        array = free_array (array);

        return retval;
    }
    
    /* throw away left side */
    if (pivotpos < position)
    {
        left = pivotpos + 1;
        newpos = position - left;
    }
    else /* pivotpos >= position) */ /* throw away right side */
    {
        right = pivotpos - 1;
        newpos = position;
    }

    temparray = create_array (right-left+1);
    copyarray_partial (array, temparray, left, right);

    retval = kth_smallest_method3 (temparray, right-left+1, newpos);

    temparray = free_array (temparray);
    array = free_array (array);
    
    return retval;
}

/* Find the kth smallest element in the array (starting from zero)
 * 
 * This method uses both partition() from quicksort, as well as using
 * the "median of medians" rule to throw away as much data as possible */
int kth_smallest_method4 (int src_array[], unsigned long size, unsigned long position)
{
    int *array;
    int *medianarray;
    int *temparray = NULL;
    int group_size = 11; /* choose any odd number, 11 works well in my tests */
    int i, left=0, right=group_size-1;
    int num_groups = size/group_size;
    int retval;
    int pivotpos;

    array = create_array (size);
    copyarray (src_array, array, size);

    /* base case */
    if (size <= group_size)
    {
        insertsort (array, size);
        retval = array[position];

        array = free_array (array);

        return retval;
    }
    
    /* get the array of medians */
    medianarray = create_array (num_groups);
    temparray = create_array (group_size);
    
    for (i=0; i<num_groups; i++)
    {
        copyarray_partial (array, temparray, left, right);
        insertsort (temparray, group_size);
        medianarray[i] = temparray[group_size/2];
        left = right + 1;
        right = left + group_size - 1;
    }

    temparray = free_array (temparray);
    
    /* find the median of medians */
    retval = kth_smallest_method4 (medianarray, num_groups, num_groups/2);

    /* move the mm to the 0th position in the array (for partition) */
    for (i=0; i<size; i++)
    {
        if (array[i] == retval)
        {
            swap (&array[i], &array[0]);
            break;
        }
    }

    /* find pivotpos using partition() */
    pivotpos = partition (array, 0, size-1);

    if (position == pivotpos)
    { /* no-op */ }
    else if (position < pivotpos)
    {
        temparray = create_array (pivotpos);
        copyarray_partial (array, temparray, 0, pivotpos-1);
        retval = kth_smallest_method4 (temparray, pivotpos, position);
    }
    else
    {
        temparray = create_array (size-(pivotpos+1));
        copyarray_partial (array, temparray, pivotpos+1, size-1);
        retval = kth_smallest_method4 (temparray, size-(pivotpos+1), position-(pivotpos+1));
    }
    
    array = free_array (array);
    medianarray = free_array (medianarray);
    if (temparray != NULL)
    {
        temparray = free_array (temparray);
    }

    return retval;
}