aboutsummaryrefslogtreecommitdiff
path: root/arraylist.c
diff options
context:
space:
mode:
Diffstat (limited to 'arraylist.c')
-rw-r--r--arraylist.c295
1 files changed, 295 insertions, 0 deletions
diff --git a/arraylist.c b/arraylist.c
new file mode 100644
index 0000000..21b8229
--- /dev/null
+++ b/arraylist.c
@@ -0,0 +1,295 @@
1/* arraylist */
2#include <assert.h>
3#include <stdbool.h>
4#include <stdio.h>
5#include <stdlib.h>
6#include <string.h>
7#include <time.h>
8
9typedef int T;
10
11struct ArrayList {
12 T ** array;
13 size_t size;
14 size_t capacity;
15};
16
17// Utils...
18static void
19ERROR(const char *msg)
20{
21 fprintf(stderr, "Error: %s\n", msg);
22 exit(EXIT_FAILURE);
23}
24
25static T **
26ArrayList_allocate(void *ptr, size_t nelem)
27{
28 T **new_ptr = reallocarray(ptr, nelem, sizeof *new_ptr);
29
30 if ( new_ptr == NULL ) {
31 ERROR("out of memory");
32 }
33
34 return new_ptr;
35}
36
37void
38ArrayList_init(struct ArrayList *arrayList)
39{
40 assert(arrayList != NULL);
41
42 arrayList->array = NULL;
43 arrayList->size = 0;
44 arrayList->capacity = 0;
45}
46
47struct ArrayList *
48ArrayList_new(void)
49{
50 struct ArrayList *arrayList = malloc(sizeof *arrayList);
51 if ( arrayList != NULL ) {
52 ArrayList_init(arrayList);
53 }
54 return arrayList;
55}
56
57void
58ArrayList_free(struct ArrayList *arrayList)
59{
60 assert(arrayList != NULL);
61
62 free(arrayList->array);
63 ArrayList_init(arrayList);
64}
65
66void
67ArrayList_delete(struct ArrayList *arrayList)
68{
69 assert(arrayList != NULL);
70
71 ArrayList_free(arrayList);
72 free(arrayList);
73}
74
75static void
76ArrayList_growIfNeeded(struct ArrayList *arrayList)
77{
78 assert(arrayList != NULL);
79
80 if ( arrayList->size == arrayList->capacity ) {
81 if ( arrayList->array == NULL ) { // leere Liste
82 assert(arrayList->size == 0);
83 assert(arrayList->capacity == 0);
84
85 static const size_t DEFAULT_CAPACITY = 10;
86
87 arrayList->capacity = DEFAULT_CAPACITY;
88 arrayList->array = ArrayList_allocate(NULL, DEFAULT_CAPACITY);
89 }
90 else {
91 size_t new_capacity = (arrayList->capacity * 3) / 2; // *= 1.5
92 T ** new_arrayList = ArrayList_allocate(arrayList->array, new_capacity);
93
94 arrayList->capacity = new_capacity;
95 arrayList->array = new_arrayList;
96 }
97
98 assert(arrayList->array != NULL);
99 }
100}
101
102void
103ArrayList_append(struct ArrayList *arrayList, T *ptr)
104{
105 assert(arrayList != NULL);
106
107 ArrayList_growIfNeeded(arrayList);
108
109 arrayList->array[arrayList->size++] = ptr;
110}
111
112void
113ArrayList_insertAt(struct ArrayList *arrayList, size_t idx, T *ptr)
114{
115 assert(arrayList != NULL);
116 assert(idx <= arrayList->size); // allow last position
117
118 ArrayList_growIfNeeded(arrayList);
119
120 memmove(&arrayList->array[idx + 1], &arrayList->array[idx], (arrayList->size - idx) * sizeof(arrayList->array[0]));
121 arrayList->array[idx] = ptr;
122 ++arrayList->size;
123}
124
125T *
126ArrayList_getAt(struct ArrayList *arrayList, size_t idx)
127{
128 assert(arrayList != NULL);
129 assert(idx < arrayList->size);
130
131 return arrayList->array[idx];
132}
133
134size_t
135ArrayList_size(struct ArrayList *arrayList)
136{
137 assert(arrayList != NULL);
138
139 return arrayList->size;
140}
141
142bool
143ArrayList_empty(struct ArrayList *arrayList)
144{
145 assert(arrayList != NULL);
146
147 return arrayList->size == 0;
148}
149
150void
151ArrayList_removeAt(struct ArrayList *arrayList, size_t idx, void clear_func(T *, void *), void *args)
152{
153 assert(arrayList != NULL);
154 assert(idx < arrayList->size);
155
156 if ( clear_func != NULL ) {
157 clear_func(arrayList->array[idx], args);
158 }
159
160#if defined(ARRAYLIST_KEEP_ORDER)
161 memmove(&arrayList->arrayList[idx], &arrayList->arrayList[idx + 1], (arrayList->size - (idx + 1)) * sizeof(arrayList->arrayList[0]));
162#else
163 arrayList->array[idx] = arrayList->array[arrayList->size - 1];
164#endif
165
166 --arrayList->size;
167}
168
169struct ArrayList_sort_ctx {
170 int (*cmp)(const T *, const T *, void *);
171 void *args;
172};
173
174typedef const T *const_ptr;
175
176static int
177ArrayList_compareAdapter(void *ctx, const void *a, const void *b)
178{
179 const const_ptr *aa = a;
180 const const_ptr *bb = b;
181
182 const struct ArrayList_sort_ctx *sort_ctx = ctx;
183
184 return sort_ctx->cmp(*aa, *bb, sort_ctx->args);
185}
186
187void
188ArrayList_sort(struct ArrayList *arrayList, int cmp(const T *, const T *, void *), void *args)
189{
190 assert(arrayList != NULL);
191 assert(cmp != NULL);
192
193 struct ArrayList_sort_ctx sort_ctx = {
194 .cmp = cmp,
195 .args = args
196 };
197
198 qsort_r(arrayList->array, arrayList->size, sizeof(arrayList->array[0]), &sort_ctx, ArrayList_compareAdapter);
199}
200
201void
202ArrayList_shuffle(struct ArrayList *arrayList, size_t rng(size_t, void *), void *args)
203{
204 assert(arrayList != NULL);
205 assert(rng != NULL);
206
207 if ( arrayList->size > 1 ) {
208 for ( size_t i = arrayList->size - 1; i > 0; --i ) {
209 size_t j = rng(i + 1, args);
210
211 // swap
212 T *t = arrayList->array[j];
213 arrayList->array[j] = arrayList->array[i];
214 arrayList->array[i] = t;
215 }
216 }
217}
218
219static void
220ArrayList_debugPrint(struct ArrayList *arrayList)
221{
222 for ( size_t idx = 0; idx != ArrayList_size(arrayList); ++idx ) {
223 T *ptr = ArrayList_getAt(arrayList, idx);
224 printf("%d, ", *ptr);
225 }
226 putchar('\n');
227}
228
229static int
230my_compare(const T *a, const T *b, void *args)
231{
232 (void) args;
233
234 if ( *a > *b ) {
235 return 1;
236 }
237 else if ( *a < *b ) {
238 return -1;
239 }
240 else {
241 return 0;
242 }
243}
244
245static size_t
246my_rng(size_t max, void *args)
247{
248 (void) args;
249 return (size_t) rand() % max;
250}
251
252static void
253ArrayList_testSort(struct ArrayList *arrayList)
254{
255 for ( size_t i = 1; i < arrayList->size; ++i ) {
256 if ( *arrayList->array[i - 1] > *arrayList->array[i] ) {
257 fprintf(stderr, "Fehler: %zu (%d, %d)\n", i, *arrayList->array[i - 1], *arrayList->array[i]);
258 exit(EXIT_FAILURE);
259 }
260 }
261}
262
263int
264main(void)
265{
266 srand(time(NULL));
267
268 int a = 11, b = 22, c = 33, d = 44;
269
270 struct ArrayList *arrayList = ArrayList_new();
271
272 ArrayList_append(arrayList, &a);
273 ArrayList_append(arrayList, &b);
274 ArrayList_append(arrayList, &c);
275 ArrayList_append(arrayList, &d);
276 ArrayList_debugPrint(arrayList); // 11, 22, 33, 44
277
278 ArrayList_removeAt(arrayList, 0, NULL, NULL);
279 ArrayList_debugPrint(arrayList); // 44, 22, 33
280
281 ArrayList_insertAt(arrayList, 3, &a);
282 ArrayList_debugPrint(arrayList); // 44, 22, 33, 11
283
284 ArrayList_sort(arrayList, my_compare, NULL);
285 ArrayList_testSort(arrayList);
286
287 ArrayList_debugPrint(arrayList); // 11, 22, 33, 44
288
289 ArrayList_shuffle(arrayList, my_rng, NULL);
290 ArrayList_debugPrint(arrayList); // ??
291
292 ArrayList_delete(arrayList);
293
294 return EXIT_SUCCESS;
295}