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 *medianarray;
383
    int *temparray = NULL;
384
    int group_size = 3;
385
    int i, left=0, right=group_size-1;
386
    int num_groups = size/group_size;
387
    int retval;
388
    int pivotpos;
389
 
390
    array = create_array (size);
391
    copyarray (src_array, array, size);
392
 
393
    /* base case */
394
    if (size <= group_size)
82 irasnyd 395
    {
83 irasnyd 396
        mergesort (array, size);
397
        retval = array[position];
398
 
399
        free (array); array = NULL;
400
 
401
        return retval;
82 irasnyd 402
    }
83 irasnyd 403
 
84 irasnyd 404
    /* get the array of medians */
405
    medianarray = create_array (num_groups);
406
    temparray = create_array (group_size);
407
 
83 irasnyd 408
    for (i=0; i<num_groups; i++)
409
    {
84 irasnyd 410
        copyarray_partial (array, temparray, left, right);
411
        mergesort (temparray, group_size);
412
        medianarray[i] = temparray[group_size/2];
83 irasnyd 413
        left = right + 1;
414
        right = left + group_size - 1;
415
    }
82 irasnyd 416
 
84 irasnyd 417
    free (temparray); temparray = NULL;
418
 
83 irasnyd 419
    /* find the median of medians */
420
    retval = kth_smallest_method4 (medianarray, num_groups, num_groups/2);
421
 
422
    /* move the mm to the 0th position in the array (for partition) */
423
    for (i=0; i<size; i++)
424
    {
425
        if (array[i] == retval)
426
        {
427
            swap (&array[i], &array[0]);
428
            break;
429
        }
430
    }
431
 
432
    /* find pivotpos using partition() */
433
    pivotpos = partition (array, 0, size-1);
434
 
435
    if (position == pivotpos)
436
    {
437
        free (array); array = NULL;
438
        free (medianarray); medianarray = NULL;
439
 
440
        return retval;
441
    }
442
    else if (position < pivotpos)
443
    {
444
        temparray = create_array (pivotpos);
445
        copyarray_partial (array, temparray, 0, pivotpos-1);
446
        retval = kth_smallest_method4 (temparray, pivotpos, position);
447
 
448
        free (array); array = NULL;
449
        free (medianarray); medianarray = NULL;
450
        free (temparray); temparray = NULL;
451
 
452
        return retval;
453
    }
454
    else
455
    {
456
        temparray = create_array (size-(pivotpos+1));
457
        copyarray_partial (array, temparray, pivotpos+1, size-1);
458
        retval = kth_smallest_method4 (temparray, size-(pivotpos+1), position-(pivotpos+1));
459
 
460
        free (array); array = NULL;
461
        free (medianarray); medianarray = NULL;
462
        free (temparray); temparray = NULL;
463
 
464
        return retval;
465
    }
82 irasnyd 466
 
83 irasnyd 467
    /* shouldn't need any of this */
468
    free (array); array = NULL;
469
    free (medianarray); medianarray = NULL;
470
    if (temparray != NULL)
471
    {
472
        free (temparray); temparray = NULL;
473
    }
474
 
82 irasnyd 475
    return retval;
476
}
477
 
83 irasnyd 478
int* create_array (unsigned long size)
479
{
480
    int *array;
481
 
482
    if ( (array = (int*) malloc (size*sizeof(int))) == NULL)
483
    {
484
        printf ("Out of memory allocating array of size=%lu\n", size);
485
        printf ("Exiting...");
486
        exit (1);
487
    }
488
 
489
    return array;
490
}
491
 
492
int** create_matrix (unsigned long rows, unsigned long cols)
493
{
494
    int **array;
495
    int i;
496
 
497
    if ( (array = (int**) malloc (rows*sizeof(int*))) == NULL)
498
    {
499
        printf ("Out of memory creating matrix of size=%lux%lu\n", rows, cols);
500
        printf ("Exiting...");
501
        exit (1);
502
    }
503
 
504
    for (i=0; i<rows; i++)
505
    {
506
        if ( (array[i] = (int*) malloc (cols*sizeof(int))) == NULL)
507
        {
508
            printf ("Out of memory creating matrix of size=%lux%lu\n", rows, cols);
509
            printf ("Exiting...");
510
            exit (1);
511
        }
512
    }
513
 
514
    return array;
515
}
516
 
517
void free_matrix (int **matrix, unsigned long rows, unsigned long cols)
518
{
519
    int i;
520
 
521
    for (i=0; i<rows; i++)
522
    {
523
        free (matrix[i]);
524
        matrix[i] = NULL;
525
    }
526
 
527
    free (matrix);
528
    matrix = NULL;
529
}
530