00001 #include <ctype.h>
00002
00003 #include <debug.h>
00004 #include <random.h>
00005 #include <stdlib.h>
00006 #include <stdbool.h>
00007
00008
00009
00010 int
00011 atoi (const char *s)
00012 {
00013 bool negative;
00014 int value;
00015
00016 ASSERT (s != NULL);
00017
00018
00019 while (isspace ((unsigned char) *s))
00020 s++;
00021
00022
00023 negative = false;
00024 if (*s == '+')
00025 s++;
00026 else if (*s == '-')
00027 {
00028 negative = true;
00029 s++;
00030 }
00031
00032
00033
00034
00035
00036 for (value = 0; isdigit (*s); s++)
00037 value = value * 10 - (*s - '0');
00038 if (!negative)
00039 value = -value;
00040
00041 return value;
00042 }
00043
00044
00045 static int
00046 compare_thunk (const void *a, const void *b, void *aux)
00047 {
00048 int (**compare) (const void *, const void *) = aux;
00049 return (*compare) (a, b);
00050 }
00051
00052
00053
00054
00055
00056
00057
00058 void
00059 qsort (void *array, size_t cnt, size_t size,
00060 int (*compare) (const void *, const void *))
00061 {
00062 sort (array, cnt, size, compare_thunk, &compare);
00063 }
00064
00065
00066
00067 static void
00068 do_swap (unsigned char *array, size_t a_idx, size_t b_idx, size_t size)
00069 {
00070 unsigned char *a = array + (a_idx - 1) * size;
00071 unsigned char *b = array + (b_idx - 1) * size;
00072 size_t i;
00073
00074 for (i = 0; i < size; i++)
00075 {
00076 unsigned char t = a[i];
00077 a[i] = b[i];
00078 b[i] = t;
00079 }
00080 }
00081
00082
00083
00084
00085
00086 static int
00087 do_compare (unsigned char *array, size_t a_idx, size_t b_idx, size_t size,
00088 int (*compare) (const void *, const void *, void *aux),
00089 void *aux)
00090 {
00091 return compare (array + (a_idx - 1) * size, array + (b_idx - 1) * size, aux);
00092 }
00093
00094
00095
00096
00097 static void
00098 heapify (unsigned char *array, size_t i, size_t cnt, size_t size,
00099 int (*compare) (const void *, const void *, void *aux),
00100 void *aux)
00101 {
00102 for (;;)
00103 {
00104
00105
00106 size_t left = 2 * i;
00107 size_t right = 2 * i + 1;
00108 size_t max = i;
00109 if (left <= cnt && do_compare (array, left, max, size, compare, aux) > 0)
00110 max = left;
00111 if (right <= cnt
00112 && do_compare (array, right, max, size, compare, aux) > 0)
00113 max = right;
00114
00115
00116
00117 if (max == i)
00118 break;
00119
00120
00121 do_swap (array, i, max, size);
00122 i = max;
00123 }
00124 }
00125
00126
00127
00128
00129
00130
00131
00132 void
00133 sort (void *array, size_t cnt, size_t size,
00134 int (*compare) (const void *, const void *, void *aux),
00135 void *aux)
00136 {
00137 size_t i;
00138
00139 ASSERT (array != NULL || cnt == 0);
00140 ASSERT (compare != NULL);
00141 ASSERT (size > 0);
00142
00143
00144 for (i = cnt / 2; i > 0; i--)
00145 heapify (array, i, cnt, size, compare, aux);
00146
00147
00148 for (i = cnt; i > 1; i--)
00149 {
00150 do_swap (array, 1, i, size);
00151 heapify (array, 1, i - 1, size, compare, aux);
00152 }
00153 }
00154
00155
00156
00157
00158
00159
00160
00161
00162
00163
00164
00165
00166 void *
00167 bsearch (const void *key, const void *array, size_t cnt,
00168 size_t size, int (*compare) (const void *, const void *))
00169 {
00170 return binary_search (key, array, cnt, size, compare_thunk, &compare);
00171 }
00172
00173
00174
00175
00176
00177
00178
00179
00180
00181
00182
00183
00184
00185 void *
00186 binary_search (const void *key, const void *array, size_t cnt, size_t size,
00187 int (*compare) (const void *, const void *, void *aux),
00188 void *aux)
00189 {
00190 const unsigned char *first = array;
00191 const unsigned char *last = array + size * cnt;
00192
00193 while (first < last)
00194 {
00195 size_t range = (last - first) / size;
00196 const unsigned char *middle = first + (range / 2) * size;
00197 int cmp = compare (key, middle, aux);
00198
00199 if (cmp < 0)
00200 last = middle;
00201 else if (cmp > 0)
00202 first = middle + size;
00203 else
00204 return (void *) middle;
00205 }
00206
00207 return NULL;
00208 }
00209