Subversion Repositories programming

Rev

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