Subversion Repositories programming

Rev

Go to most recent revision | Details | Last modification | View Log | RSS feed

Rev Author Line No. Line
77 irasnyd 1
/* Written by: Ira Snyder
2
 * Started on: 05-20-2005
82 irasnyd 3
 * Due Date: 06-10-2005
77 irasnyd 4
 * CS331 Project #2
5
 */
6
 
7
#include <stdio.h>
8
#include <stdlib.h>
9
#include <time.h>
10
 
11
void mergesort (int array[], unsigned long size);
12
void mergesort_rec (int A[], unsigned long min, unsigned long max);
13
void merge (int A[], unsigned long asize, int B[], unsigned long bsize);
14
void swap (int *left, int *right);
15
void printarray (int array[], unsigned long size);
16
void randomfill (int array[], unsigned long size);
17
int partition (int array[], unsigned long left, unsigned long right);
18
void copyarray (int src[], int dst[], unsigned long size);
19
int kth_smallest_method1 (int src_array[], unsigned long size, unsigned long position);
20
int kth_smallest_method2 (int src_array[], unsigned long size, unsigned long position);
21
 
22
void startclock (void);
23
void stopclock (void);
24
void printtimetaken (char *funcname);
25
 
26
 
27
/* global timeval for timing the function calls */
28
struct timeval start_time, end_time, lapsed;
29
 
30
int main (void)
31
{
32
    /* create new random seed */
33
    srand((unsigned)time(NULL));
34
 
35
    unsigned long size, kth_pos;
36
    int* array;
37
    int i;
38
 
39
    for (size=50; size<=3000; size+=50)
40
    {
41
        if ( (array = (int*) malloc (size*sizeof(int))) == NULL)
42
        {
82 irasnyd 43
            printf ("Ran out of memory at size=%lu\n", size);
44
            exit (1);
77 irasnyd 45
        }
46
 
47
        /* fill the array with random values */
48
        randomfill (array, size);
49
 
50
        for (i=0; i<5; i++)
51
        {
52
            if (i==0)
53
                kth_pos=0;
54
            else if (i==1)
55
                kth_pos=size/4;
56
            else if (i==2)
57
                kth_pos=size/2;
58
            else if (i==3)
59
                kth_pos=3*size/4;
60
            else
61
                kth_pos=size-1;
62
            /* header */
82 irasnyd 63
            printf ("Running with size=%lu (%.3fMB) kth_pos=%lu...\n",
77 irasnyd 64
                    size, (size*4.0)/(1024*1024), kth_pos);
65
 
66
            /* run method1 */
67
            startclock();
82 irasnyd 68
            printf ("%luth smallest (method1): %d -- ", kth_pos, 
77 irasnyd 69
                    kth_smallest_method1 (array, size, kth_pos));
70
            stopclock();
71
            printtimetaken("Method1");
72
 
73
            /* run method2 */
74
            startclock();
82 irasnyd 75
            printf ("%luth smallest (method2): %d -- ", kth_pos, 
77 irasnyd 76
                    kth_smallest_method2 (array, size, kth_pos));
77
            stopclock();
78
            printtimetaken("Method2");
79
 
82 irasnyd 80
            /* run method3 */
81
            startclock();
82
            printf ("%luth smallest (method3): %d -- ", kth_pos, 
83
                    kth_smallest_method3 (array, size, kth_pos));
84
            stopclock();
85
            printtimetaken("Method3");
86
 
77 irasnyd 87
            printf ("\n\n");
88
        }
89
 
90
        free (array);
91
        array = NULL;
92
    }
93
 
94
    return 0;
95
}
96
 
97
/* Mergesort an array
98
 * Sets up the correct parameters and hands off the work to
99
 * mergesort_rec()
100
 * 
101
 * Complexity: O(n*lgn)
102
 */
103
void mergesort (int array[], unsigned long size)
104
{
105
    mergesort_rec (array, 0, size-1);
106
}
107
 
108
/* The actual mergesort call */
109
void mergesort_rec (int A[], unsigned long min, unsigned long max)
110
{
111
    unsigned long mid = (min+max)/2;
112
    unsigned long lowerCount = mid - min + 1;
113
    unsigned long upperCount = max - mid;
114
 
115
    if (max == min)
116
        return;
117
 
118
    mergesort_rec (A, min, mid);
119
    mergesort_rec (A, mid+1, max);
120
    merge (A+min, lowerCount, A+mid+1, upperCount);
121
}
122
 
123
/* merge two arrays together
124
 *
125
 * Complexity: O(n)
126
 */
127
void merge(int A[], unsigned long asize, int B[], unsigned long bsize)
128
{
129
    unsigned long ai, bi, ci, i;
130
    int *C;
131
    unsigned long csize = asize+bsize;
132
 
82 irasnyd 133
    if ( (C = (int*) malloc (csize * sizeof(int))) == NULL)
77 irasnyd 134
    {
82 irasnyd 135
        printf ("Out of memory... Exiting\n");
136
        exit (1);
77 irasnyd 137
    }
138
 
139
    ai = 0;
140
    bi = 0;
141
    ci = 0;
142
 
143
    while ((ai < asize) && (bi < bsize)) 
144
    {
145
        if (A[ai] <= B[bi])
146
        {
147
            C[ci] = A[ai];
148
            ci++; ai++;
149
        }
150
        else
151
        {
152
            C[ci] = B[bi];
153
            ci++; bi++;
154
        }
155
    }
156
 
157
    if (ai >= asize)
158
        for (i = ci; i < csize; i++, bi++)
159
            C[i] = B[bi];
160
        else if (bi >= bsize)
161
            for (i = ci; i < csize; i++, ai++)
162
                C[i] = A[ai];
163
 
164
        for (i = 0; i < csize; i++)
165
            A[i] = C[i];
166
 
167
    free (C);
168
}
169
 
170
/* swap two values */
171
void swap (int *left, int *right)
172
{
173
    int temp;
174
    temp = *left;
175
    *left = *right;
176
    *right = temp;
177
}
178
 
179
/* print out the contents of the array
180
 * used for debugging mainly
181
 */
182
void printarray (int array[], unsigned long size)
183
{
184
    unsigned long i;
185
 
82 irasnyd 186
    printf("Printing %lu elements\n", size);
77 irasnyd 187
 
188
    for (i=0; i<size; i++)
189
        printf("%d ", array[i]);
190
 
191
    printf("\n");
192
}
193
 
194
/* fill the array with random numbers in
195
 * the range 0-32767
196
 */
197
void randomfill (int array[], unsigned long size)
198
{
199
    unsigned long i;
200
 
201
    for (i=0; i<size; i++)
202
        array[i] = rand() % 32768;
203
}
204
 
205
/* partition from quicksort
206
 * this partitions an array around the pivot value,
207
 * which is found in array[left].
208
 *
209
 * All values less than the pivot are on the left
210
 * All values more than the pivot are on the right
211
 *
212
 * Complexity: O(n)
213
 */
214
int partition (int array[], unsigned long left, unsigned long right)
215
{
216
    unsigned long i, last, pivot;
217
 
218
    pivot = array[left];
219
    last = left;
220
 
221
    for (i=left+1; i<=right; i++)
222
        if (array[i] < pivot)
223
        {
224
           last++;
225
           swap (&array[last], &array[i]);
226
        }
227
 
228
    swap (&array[left], &array[last]);
229
    return last;
230
}
231
 
232
/* start the clock (for timing) */
233
void startclock (void)
234
{
235
    gettimeofday(&start_time, NULL);
236
}
237
 
238
/* stop the clock (for timing) */
239
void stopclock (void)
240
{
241
    gettimeofday(&end_time, NULL);
242
}
243
 
244
/* print the time taken, in milliseconds = seconds / 1000 */
245
void printtimetaken (char *funcname)
246
{
247
    double total_usecs = (end_time.tv_sec-start_time.tv_sec) * 1000000.0
248
                       + (end_time.tv_usec-start_time.tv_usec);
249
 
250
    printf("%s : %.3lf milliseconds\n", funcname, total_usecs/1000.0);
251
}
252
 
253
/* copy the src[] to dst[] */
254
void copyarray (int src[], int dst[], unsigned long size)
255
{
256
    unsigned long i;
257
 
258
    for (i=0; i<size; i++)
259
        dst[i] = src[i];
260
}
261
 
82 irasnyd 262
void copyarray_partial (int src[], int dst[], unsigned long src_left, 
263
        unsigned long src_right)
264
{
265
    unsigned long i, j;
266
 
267
    for (i=src_left, j=0; i<=src_right; i++, j++)
268
        dst[j] = src[i];
269
}
270
 
77 irasnyd 271
/* Find the kth smallest element in the array (starting from zero)
272
 *
273
 * This uses the method of sorting the list, then picking
274
 * the correct element
275
 */
82 irasnyd 276
int kth_smallest_method1 (int src_array[], unsigned long size, 
277
        unsigned long position)
77 irasnyd 278
{
279
    int *array;
280
    int retval;
281
 
282
    if ( (array = (int*) malloc (size*sizeof(int))) == NULL)
283
    {
82 irasnyd 284
        printf ("Out of memory at size=%lu\n", size);
77 irasnyd 285
        exit(1);
286
    }
287
 
288
    copyarray (src_array, array, size);
289
 
290
    mergesort (array, size);
291
 
292
    retval = array[position];
293
    free (array);
294
    array = NULL;
295
    return retval;
296
}
297
 
298
/* Find the kth smallest element in the array (starting from zero)
299
 *
300
 * This uses the method of calling partiton() from quicksort, and
301
 * throwing out data that is unneeded
302
 */
303
int kth_smallest_method2 (int src_array[], unsigned long size, unsigned long position)
304
{
305
    int *array;
306
    int retval;
307
    unsigned long left = 0;
308
    unsigned long right = size-1;
309
    unsigned long pivotpos;
310
 
311
    if ( (array = (int*) malloc (size*sizeof(int))) == NULL)
312
    {
82 irasnyd 313
        printf ("Out of memory at size=%lu\n", size);
314
        exit (1);
77 irasnyd 315
    }
316
 
317
    copyarray (src_array, array, size);
318
 
319
    do
320
    {
321
        swap (&array[position], &array[left]);
322
        pivotpos = partition (array, left, right);
323
 
324
        if (pivotpos < position)
325
            left = pivotpos + 1;
326
        else /* pivotpos >= position) */
82 irasnyd 327
            right = pivotpos - 1;
77 irasnyd 328
    }
329
    while (pivotpos != position);
330
 
331
    retval = array[position];
332
    free (array);
333
    array = NULL;
334
    return retval;
335
}
336
 
82 irasnyd 337
int kth_smallest_method3 (int src_array[], unsigned long size, unsigned long position)
338
{
339
    int *array;
340
    int *temparray;
341
    int retval;
342
    unsigned long left = 0;
343
    unsigned long right = size-1;
344
    unsigned long pivotpos, newpos;
345
 
346
    if ( (array = (int*) malloc (size*sizeof(int))) == NULL)
347
    {
348
        printf ("Out of memory at size=%lu\n", size);
349
        exit (1);
350
    }
351
 
352
    copyarray (src_array, array, size);
353
 
354
    swap (&array[position], &array[left]);
355
    pivotpos = partition (array, left, right);
356
 
357
    /* base case */
358
    if (pivotpos == position)
359
    {
360
        retval = array[position];
361
        free (array);
362
        array = NULL;
363
        return retval;
364
    }
365
 
366
    /* throw away left side */
367
    if (pivotpos < position)
368
    {
369
        left = pivotpos + 1;
370
        newpos = position - left;
371
    }
372
    else /* pivotpos >= position) */ /* throw away right side */
373
    {
374
        right = pivotpos - 1;
375
        newpos = position;
376
    }
377
 
378
    if ( (temparray = (int*) malloc (size*sizeof(int))) == NULL)
379
    {
380
        printf ("Out of memory at size=%lu\n", size);
381
        exit (1);
382
    }
383
 
384
    copyarray_partial (array, temparray, left, right);
385
 
386
    retval = kth_smallest_method3 (temparray, right-left+1, newpos);
387
 
388
    free (temparray);
389
    temparray = NULL;
390
    free (array);
391
    array = NULL;
392
 
393
    return retval;
394
}
395