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