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