Subversion Repositories programming

Rev

Rev 103 | Details | Compare with Previous | 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
108 ira 5
 * License: Public Domain
77 irasnyd 6
 */
7
 
86 irasnyd 8
 
9
/* standard headers */
77 irasnyd 10
#include <stdio.h>
11
#include <stdlib.h>
12
#include <time.h>
13
 
86 irasnyd 14
/* broken-out code for common things */
15
#include "sorts.c"
16
#include "timing.c"
17
#include "arrays.c"
18
 
19
 
20
/* function prototypes */
77 irasnyd 21
void randomfill (int array[], unsigned long size);
22
int kth_smallest_method1 (int src_array[], unsigned long size, unsigned long position);
23
int kth_smallest_method2 (int src_array[], unsigned long size, unsigned long position);
83 irasnyd 24
int kth_smallest_method3 (int src_array[], unsigned long size, unsigned long position);
25
int kth_smallest_method4 (int src_array[], unsigned long size, unsigned long position);
77 irasnyd 26
 
27
 
28
int main (void)
29
{
30
    /* create new random seed */
31
    srand((unsigned)time(NULL));
32
 
33
    unsigned long size, kth_pos;
86 irasnyd 34
    int *array;
88 irasnyd 35
    int stop_looping, i;
77 irasnyd 36
 
88 irasnyd 37
    size = 10; /* set initial size to 10 */
38
    stop_looping = 0; /* FALSE */
39
 
40
    while ( !stop_looping )
77 irasnyd 41
    {
88 irasnyd 42
        /* create and fill an array with random values */
83 irasnyd 43
        array = create_array (size);
77 irasnyd 44
        randomfill (array, size);
45
 
46
        for (i=0; i<5; i++)
47
        {
88 irasnyd 48
            /* choose the kth position based on the handout */
77 irasnyd 49
            if (i==0)
50
                kth_pos=0;
51
            else if (i==1)
52
                kth_pos=size/4;
53
            else if (i==2)
54
                kth_pos=size/2;
55
            else if (i==3)
56
                kth_pos=3*size/4;
57
            else
58
                kth_pos=size-1;
86 irasnyd 59
 
77 irasnyd 60
            /* header */
82 irasnyd 61
            printf ("Running with size=%lu (%.3fMB) kth_pos=%lu...\n",
77 irasnyd 62
                    size, (size*4.0)/(1024*1024), kth_pos);
63
 
64
            /* run method1 */
65
            startclock();
82 irasnyd 66
            printf ("%luth smallest (method1): %d -- ", kth_pos, 
77 irasnyd 67
                    kth_smallest_method1 (array, size, kth_pos));
68
            stopclock();
69
            printtimetaken("Method1");
70
 
71
            /* run method2 */
72
            startclock();
82 irasnyd 73
            printf ("%luth smallest (method2): %d -- ", kth_pos, 
77 irasnyd 74
                    kth_smallest_method2 (array, size, kth_pos));
75
            stopclock();
76
            printtimetaken("Method2");
77
 
82 irasnyd 78
            /* run method3 */
79
            startclock();
80
            printf ("%luth smallest (method3): %d -- ", kth_pos, 
81
                    kth_smallest_method3 (array, size, kth_pos));
82
            stopclock();
83
            printtimetaken("Method3");
83 irasnyd 84
 
85
            /* run method4 */
86
            startclock();
87
            printf ("%luth smallest (method4): %d -- ", kth_pos, 
88
                    kth_smallest_method4 (array, size, kth_pos));
89
            stopclock();
90
            printtimetaken("Method4");
91
 
87 irasnyd 92
            /* some blank lines for spacing */
77 irasnyd 93
            printf ("\n\n");
94
        }
95
 
88 irasnyd 96
        /* free the memory that was allocated for the array */
86 irasnyd 97
        array = free_array (array);
88 irasnyd 98
 
99
        /* choose size according to the Project #2 handout */
100
        if (size < 10)
101
            size = 10;
102
        else if (size < 50)
103
            size = 50;
104
        else if (size < 100)
105
            size = 100;
106
        else if (size < 250)
107
            size = 250;
108
        else
109
            size *= 2;
77 irasnyd 110
 
103 irasnyd 111
        /* if we grow above 262.5 million elements (about 1GB), stop looping */
112
        if (size > 262500000)
88 irasnyd 113
            stop_looping = 1; /* TRUE */
114
 
115
    } /* end while loop */
116
 
77 irasnyd 117
    return 0;
118
}
119
 
120
/* fill the array with random numbers in
87 irasnyd 121
 * the range 0-32767 */
77 irasnyd 122
void randomfill (int array[], unsigned long size)
123
{
124
    unsigned long i;
125
 
126
    for (i=0; i<size; i++)
127
        array[i] = rand() % 32768;
128
}
129
 
130
/* Find the kth smallest element in the array (starting from zero)
131
 *
132
 * This uses the method of sorting the list, then picking
87 irasnyd 133
 * the correct element */
82 irasnyd 134
int kth_smallest_method1 (int src_array[], unsigned long size, 
135
        unsigned long position)
77 irasnyd 136
{
137
    int *array;
138
    int retval;
139
 
83 irasnyd 140
    array = create_array (size);
77 irasnyd 141
    copyarray (src_array, array, size);
142
 
143
    mergesort (array, size);
144
 
145
    retval = array[position];
86 irasnyd 146
    array = free_array (array);
83 irasnyd 147
 
77 irasnyd 148
    return retval;
149
}
150
 
151
/* Find the kth smallest element in the array (starting from zero)
152
 *
153
 * This uses the method of calling partiton() from quicksort, and
87 irasnyd 154
 * throwing out data that is unneeded */
77 irasnyd 155
int kth_smallest_method2 (int src_array[], unsigned long size, unsigned long position)
156
{
157
    int *array;
158
    int retval;
159
    unsigned long left = 0;
160
    unsigned long right = size-1;
161
    unsigned long pivotpos;
162
 
83 irasnyd 163
    array = create_array (size);
77 irasnyd 164
    copyarray (src_array, array, size);
165
 
166
    do
167
    {
168
        swap (&array[position], &array[left]);
169
        pivotpos = partition (array, left, right);
170
 
171
        if (pivotpos < position)
172
            left = pivotpos + 1;
173
        else /* pivotpos >= position) */
82 irasnyd 174
            right = pivotpos - 1;
77 irasnyd 175
    }
176
    while (pivotpos != position);
177
 
178
    retval = array[position];
86 irasnyd 179
    array = free_array (array);
83 irasnyd 180
 
77 irasnyd 181
    return retval;
182
}
183
 
87 irasnyd 184
/* Find the kth smallest element in the array (starting from zero)
185
 *
186
 * This uses the method of calling partiton() from quicksort, and
187
 * throwing out data that is unneeded
188
 *
189
 * NOTE: This is a recursive version of the algorithm above (kth_smallest_method2) */
82 irasnyd 190
int kth_smallest_method3 (int src_array[], unsigned long size, unsigned long position)
191
{
192
    int *array;
193
    int *temparray;
194
    int retval;
195
    unsigned long left = 0;
196
    unsigned long right = size-1;
197
    unsigned long pivotpos, newpos;
198
 
83 irasnyd 199
    array = create_array (size);
82 irasnyd 200
    copyarray (src_array, array, size);
201
 
202
    swap (&array[position], &array[left]);
203
    pivotpos = partition (array, left, right);
204
 
205
    /* base case */
206
    if (pivotpos == position)
207
    {
208
        retval = array[position];
86 irasnyd 209
        array = free_array (array);
83 irasnyd 210
 
82 irasnyd 211
        return retval;
212
    }
213
 
214
    /* throw away left side */
215
    if (pivotpos < position)
216
    {
217
        left = pivotpos + 1;
218
        newpos = position - left;
219
    }
220
    else /* pivotpos >= position) */ /* throw away right side */
221
    {
222
        right = pivotpos - 1;
223
        newpos = position;
224
    }
225
 
83 irasnyd 226
    temparray = create_array (right-left+1);
227
    copyarray_partial (array, temparray, left, right);
228
 
229
    retval = kth_smallest_method3 (temparray, right-left+1, newpos);
230
 
86 irasnyd 231
    temparray = free_array (temparray);
232
    array = free_array (array);
83 irasnyd 233
 
234
    return retval;
235
}
236
 
87 irasnyd 237
/* Find the kth smallest element in the array (starting from zero)
238
 * 
239
 * This method uses both partition() from quicksort, as well as using
240
 * the "median of medians" rule to throw away as much data as possible */
83 irasnyd 241
int kth_smallest_method4 (int src_array[], unsigned long size, unsigned long position)
242
{
243
    int *array;
244
    int *medianarray;
245
    int *temparray = NULL;
87 irasnyd 246
    int group_size = 11; /* choose any odd number, 11 works well in my tests */
83 irasnyd 247
    int i, left=0, right=group_size-1;
248
    int num_groups = size/group_size;
249
    int retval;
250
    int pivotpos;
251
 
252
    array = create_array (size);
253
    copyarray (src_array, array, size);
254
 
255
    /* base case */
256
    if (size <= group_size)
82 irasnyd 257
    {
86 irasnyd 258
        insertsort (array, size);
83 irasnyd 259
        retval = array[position];
260
 
86 irasnyd 261
        array = free_array (array);
83 irasnyd 262
 
263
        return retval;
82 irasnyd 264
    }
83 irasnyd 265
 
84 irasnyd 266
    /* get the array of medians */
267
    medianarray = create_array (num_groups);
268
    temparray = create_array (group_size);
269
 
83 irasnyd 270
    for (i=0; i<num_groups; i++)
271
    {
84 irasnyd 272
        copyarray_partial (array, temparray, left, right);
86 irasnyd 273
        insertsort (temparray, group_size);
84 irasnyd 274
        medianarray[i] = temparray[group_size/2];
83 irasnyd 275
        left = right + 1;
276
        right = left + group_size - 1;
277
    }
82 irasnyd 278
 
86 irasnyd 279
    temparray = free_array (temparray);
84 irasnyd 280
 
83 irasnyd 281
    /* find the median of medians */
282
    retval = kth_smallest_method4 (medianarray, num_groups, num_groups/2);
283
 
284
    /* move the mm to the 0th position in the array (for partition) */
285
    for (i=0; i<size; i++)
286
    {
287
        if (array[i] == retval)
288
        {
289
            swap (&array[i], &array[0]);
290
            break;
291
        }
292
    }
293
 
294
    /* find pivotpos using partition() */
295
    pivotpos = partition (array, 0, size-1);
296
 
297
    if (position == pivotpos)
85 irasnyd 298
    { /* no-op */ }
83 irasnyd 299
    else if (position < pivotpos)
300
    {
301
        temparray = create_array (pivotpos);
302
        copyarray_partial (array, temparray, 0, pivotpos-1);
303
        retval = kth_smallest_method4 (temparray, pivotpos, position);
304
    }
305
    else
306
    {
307
        temparray = create_array (size-(pivotpos+1));
308
        copyarray_partial (array, temparray, pivotpos+1, size-1);
309
        retval = kth_smallest_method4 (temparray, size-(pivotpos+1), position-(pivotpos+1));
310
    }
82 irasnyd 311
 
86 irasnyd 312
    array = free_array (array);
313
    medianarray = free_array (medianarray);
83 irasnyd 314
    if (temparray != NULL)
315
    {
86 irasnyd 316
        temparray = free_array (temparray);
83 irasnyd 317
    }
318
 
82 irasnyd 319
    return retval;
320
}
321