Blame | Last modification | View Log | RSS feed
/* Written by: Ira Snyder
* Started on: 05-20-2005
* Due Date: 06-01-2005
* CS331 Project #2
*
* Changelog Follows:
*
*/
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
void mergesort (int array[], unsigned long size);
void mergesort_rec (int A[], unsigned long min, unsigned long max);
void merge (int A[], unsigned long asize, int B[], unsigned long bsize);
void swap (int *left, int *right);
void printarray (int array[], unsigned long size);
void randomfill (int array[], unsigned long size);
int partition (int array[], unsigned long left, unsigned long right);
void copyarray (int src[], int dst[], 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);
void startclock (void);
void stopclock (void);
void printtimetaken (char *funcname);
/* global timeval for timing the function calls */
struct timeval start_time, end_time, lapsed;
int main (void)
{
/* create new random seed */
srand((unsigned)time(NULL));
unsigned long size, kth_pos;
int* array;
int i;
for (size=50; size<=3000; size+=50)
{
if ( (array = (int*) malloc (size*sizeof(int))) == NULL)
{
printf ("Ran out of memory at size=%d\n", size);
exit(1);
}
/* fill the array with random values */
randomfill (array, size);
for (i=0; i<5; i++)
{
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=%d (%.3fMB) kth_pos=%d...\n",
size, (size*4.0)/(1024*1024), kth_pos);
/* run method1 */
startclock();
printf ("%dth smallest (method1): %d -- ", kth_pos,
kth_smallest_method1 (array, size, kth_pos));
stopclock();
printtimetaken("Method1");
/* run method2 */
startclock();
printf ("%dth smallest (method2): %d -- ", kth_pos,
kth_smallest_method2 (array, size, kth_pos));
stopclock();
printtimetaken("Method2");
printf ("\n\n");
}
free (array);
array = NULL;
}
return 0;
}
/* Mergesort an array
* Sets up the correct parameters and hands off the work to
* mergesort_rec()
*
* Complexity: O(n*lgn)
*/
void mergesort (int array[], unsigned long size)
{
mergesort_rec (array, 0, size-1);
}
/* The actual mergesort call */
void mergesort_rec (int A[], unsigned long min, unsigned long max)
{
unsigned long mid = (min+max)/2;
unsigned long lowerCount = mid - min + 1;
unsigned long upperCount = max - mid;
if (max == min)
return;
mergesort_rec (A, min, mid);
mergesort_rec (A, mid+1, max);
merge (A+min, lowerCount, A+mid+1, upperCount);
}
/* merge two arrays together
*
* Complexity: O(n)
*/
void merge(int A[], unsigned long asize, int B[], unsigned long bsize)
{
unsigned long ai, bi, ci, i;
int *C;
unsigned long csize = asize+bsize;
C = (int*) malloc (csize * sizeof(int));
if (C == NULL)
{
printf("Out of memory... Exiting\n");
exit(1);
}
ai = 0;
bi = 0;
ci = 0;
while ((ai < asize) && (bi < bsize))
{
if (A[ai] <= B[bi])
{
C[ci] = A[ai];
ci++; ai++;
}
else
{
C[ci] = B[bi];
ci++; bi++;
}
}
if (ai >= asize)
for (i = ci; i < csize; i++, bi++)
C[i] = B[bi];
else if (bi >= bsize)
for (i = ci; i < csize; i++, ai++)
C[i] = A[ai];
for (i = 0; i < csize; i++)
A[i] = C[i];
free (C);
}
/* swap two values */
void swap (int *left, int *right)
{
int temp;
temp = *left;
*left = *right;
*right = temp;
}
/* print out the contents of the array
* used for debugging mainly
*/
void printarray (int array[], unsigned long size)
{
unsigned long i;
printf("Printing %d elements\n", size);
for (i=0; i<size; i++)
printf("%d ", array[i]);
printf("\n");
}
/* 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;
}
/* partition from quicksort
* this partitions an array around the pivot value,
* which is found in array[left].
*
* All values less than the pivot are on the left
* All values more than the pivot are on the right
*
* Complexity: O(n)
*/
int partition (int array[], unsigned long left, unsigned long right)
{
unsigned long i, last, pivot;
pivot = array[left];
last = left;
for (i=left+1; i<=right; i++)
if (array[i] < pivot)
{
last++;
swap (&array[last], &array[i]);
}
swap (&array[left], &array[last]);
return last;
}
/* start the clock (for timing) */
void startclock (void)
{
gettimeofday(&start_time, NULL);
}
/* stop the clock (for timing) */
void stopclock (void)
{
gettimeofday(&end_time, NULL);
}
/* print the time taken, in milliseconds = seconds / 1000 */
void printtimetaken (char *funcname)
{
double total_usecs = (end_time.tv_sec-start_time.tv_sec) * 1000000.0
+ (end_time.tv_usec-start_time.tv_usec);
printf("%s : %.3lf milliseconds\n", funcname, total_usecs/1000.0);
}
/* copy the src[] to dst[] */
void copyarray (int src[], int dst[], unsigned long size)
{
unsigned long i;
for (i=0; i<size; i++)
dst[i] = src[i];
}
/* 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[size];
int *array;
int retval;
if ( (array = (int*) malloc (size*sizeof(int))) == NULL)
{
printf ("Out of memory at size=%d\n", size);
exit(1);
}
copyarray (src_array, array, size);
mergesort (array, size);
retval = array[position];
free (array);
array = NULL;
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[size];
int *array;
int retval;
unsigned long left = 0;
unsigned long right = size-1;
unsigned long pivotpos;
if ( (array = (int*) malloc (size*sizeof(int))) == NULL)
{
printf ("Out of memory at size=%d\n", size);
exit(1);
}
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];
free (array);
array = NULL;
return retval;
}