aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorThomas Schmucker <ts@its1.de>2022-04-09 09:46:17 +0200
committerThomas Schmucker <ts@its1.de>2022-04-09 09:46:17 +0200
commit38f5e364f73967c01f9ed442fe6646e70cb1dde0 (patch)
tree274817eb2793584b0e3d856de5504a614f2b4e89 /src
parent2863f4f1d2a6a6a8704454824d6c291d2e0d4b5c (diff)
parent154874afda4a8df885e51c01f7681f04fb0b8e61 (diff)
downloaddata-structures-38f5e364f73967c01f9ed442fe6646e70cb1dde0.tar.gz
data-structures-38f5e364f73967c01f9ed442fe6646e70cb1dde0.tar.bz2
data-structures-38f5e364f73967c01f9ed442fe6646e70cb1dde0.zip
Merge branch 'rework-directory-structure'
Diffstat (limited to 'src')
-rw-r--r--src/allocator.c79
-rw-r--r--src/allocator.h30
-rw-r--r--src/arraylist.c368
-rw-r--r--src/avl.c471
-rw-r--r--src/deque.c485
-rw-r--r--src/dlist.c504
-rw-r--r--src/hashtab.c220
-rw-r--r--src/heap.c291
-rw-r--r--src/insertsort.c38
-rw-r--r--src/list-tail-node.c197
-rw-r--r--src/list.c264
-rw-r--r--src/queue.c115
-rw-r--r--src/quicksort.c684
-rw-r--r--src/random.h47
-rw-r--r--src/rb.c614
-rw-r--r--src/rc4.c156
-rw-r--r--src/ringbuff.c156
-rw-r--r--src/shellsort.c63
-rw-r--r--src/stack.c110
-rw-r--r--src/stack2.c115
-rw-r--r--src/tree.c806
-rw-r--r--src/treeutil.h51
-rw-r--r--src/util.h24
23 files changed, 5888 insertions, 0 deletions
diff --git a/src/allocator.c b/src/allocator.c
new file mode 100644
index 0000000..98fa69f
--- /dev/null
+++ b/src/allocator.c
@@ -0,0 +1,79 @@
1#include "allocator.h"
2
3#include <stdlib.h> /* malloc */
4
5/* Interface Code */
6static void *
7default_allocate(struct allocator *allocator, size_t n)
8{
9 (void) allocator;
10 return malloc(n);
11}
12
13static void
14default_deallocate(struct allocator *allocator, void *ptr)
15{
16 (void) allocator;
17 free(ptr);
18}
19
20struct allocator allocator_default_allocator = {
21 .allocate = &default_allocate,
22 .deallocate = &default_deallocate
23};
24
25/* Libary Code */
26#include <string.h>
27
28void *
29allocator_malloc(struct allocator *allocator, size_t n)
30{
31 if ( !allocator ) {
32 allocator = &allocator_default_allocator;
33 }
34
35 return allocator->allocate(allocator, n);
36}
37
38void
39allocator_free(struct allocator *allocator, void *ptr)
40{
41 if ( !allocator ) {
42 allocator = &allocator_default_allocator;
43 }
44
45 allocator->deallocate(allocator, ptr);
46}
47
48char *
49allocator_strdup(struct allocator *allocator, const char *str)
50{
51 size_t n;
52 char * dest;
53
54 n = strlen(str) + 1;
55 dest = allocator_malloc(allocator, n);
56 if ( dest ) {
57 memcpy(dest, str, n);
58 }
59
60 return dest;
61}
62
63void *
64allocator_malloc_zero(struct allocator *allocator, size_t n)
65{
66 void *ptr;
67
68 ptr = allocator_malloc(allocator, n);
69 if ( ptr ) {
70 memset(ptr, 0, n);
71 }
72
73 return ptr;
74}
75
76int
77main()
78{
79}
diff --git a/src/allocator.h b/src/allocator.h
new file mode 100644
index 0000000..dd9bb16
--- /dev/null
+++ b/src/allocator.h
@@ -0,0 +1,30 @@
1#pragma once
2
3#include <stddef.h> /* size_t */
4
5struct allocator {
6 void *(*allocate)(struct allocator *allocator, size_t n);
7 void (*deallocate)(struct allocator *allocator, void *ptr);
8};
9
10extern struct allocator default_allocator;
11
12/* allocator interface */
13void *allocator_malloc(struct allocator *allocator, size_t n);
14void allocator_free(struct allocator *allocator, void *ptr);
15
16/* helper functions */
17char *allocator_strdup(struct allocator *allocator, const char *str);
18void *allocator_malloc_zero(struct allocator *allocator, size_t n);
19
20#define ALLOCATE(n) \
21 allocator_malloc(&allocator_default_allocator, (n))
22
23#define ALLOCATE_ZERO(n) \
24 allocator_malloc_zero(&allocator_default_allocator, (n))
25
26#define FREE(ptr) \
27 (allocator_free(&allocator_default_allocator, (ptr)), (ptr) = NULL)
28
29#define NEW(ptr) ((ptr) = ALLOCATE(sizeof *(ptr)))
30#define NEW0(ptr) ((ptr) = ALLOCATE_ZERO(sizeof *(ptr)))
diff --git a/src/arraylist.c b/src/arraylist.c
new file mode 100644
index 0000000..f010d07
--- /dev/null
+++ b/src/arraylist.c
@@ -0,0 +1,368 @@
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
9#include "util.h"
10
11typedef int T;
12
13struct ArrayList {
14 T ** array;
15 size_t size;
16 size_t capacity;
17};
18
19static T **
20ArrayList_allocateArray(void *ptr, size_t nelem)
21{
22 T **new_ptr = reallocarray(ptr, nelem, sizeof *new_ptr);
23
24 if ( new_ptr == NULL ) {
25 ERROR("out of memory");
26 }
27
28 return new_ptr;
29}
30
31void
32ArrayList_init(struct ArrayList *arrayList)
33{
34 assert(arrayList);
35
36 arrayList->array = NULL;
37 arrayList->size = 0;
38 arrayList->capacity = 0;
39}
40
41struct ArrayList *
42ArrayList_new(void)
43{
44 struct ArrayList *arrayList = malloc(sizeof *arrayList);
45 if ( arrayList ) {
46 ArrayList_init(arrayList);
47 }
48 return arrayList;
49}
50
51void
52ArrayList_free(struct ArrayList *arrayList)
53{
54 assert(arrayList);
55
56 free(arrayList->array);
57 ArrayList_init(arrayList);
58}
59
60void
61ArrayList_delete(struct ArrayList *arrayList)
62{
63 assert(arrayList);
64
65 ArrayList_free(arrayList);
66 free(arrayList);
67}
68
69static void
70ArrayList_growIfNeeded(struct ArrayList *arrayList)
71{
72 assert(arrayList);
73
74 if ( arrayList->size == arrayList->capacity ) {
75 if ( arrayList->array == NULL ) { // leere Liste
76 assert(arrayList->size == 0);
77 assert(arrayList->capacity == 0);
78
79 static const size_t DEFAULT_CAPACITY = 10;
80
81 arrayList->capacity = DEFAULT_CAPACITY;
82 arrayList->array = ArrayList_allocateArray(NULL, DEFAULT_CAPACITY);
83 }
84 else {
85 size_t new_capacity = (arrayList->capacity * 3) / 2; // *= 1.5
86 T ** new_arrayList = ArrayList_allocateArray(arrayList->array, new_capacity);
87
88 arrayList->capacity = new_capacity;
89 arrayList->array = new_arrayList;
90 }
91
92 assert(arrayList->array);
93 }
94
95 assert(arrayList->capacity > arrayList->size);
96}
97
98void
99ArrayList_append(struct ArrayList *arrayList, T *ptr)
100{
101 assert(arrayList);
102
103 ArrayList_growIfNeeded(arrayList);
104
105 arrayList->array[arrayList->size++] = ptr;
106}
107
108void
109ArrayList_insertAt(struct ArrayList *arrayList, size_t idx, T *ptr)
110{
111 assert(arrayList);
112 assert(idx <= arrayList->size); // allow last position
113
114 ArrayList_growIfNeeded(arrayList);
115
116 memmove(&arrayList->array[idx + 1],
117 &arrayList->array[idx],
118 (arrayList->size - idx) * sizeof arrayList->array[0]);
119 arrayList->array[idx] = ptr;
120 ++arrayList->size;
121}
122
123T *
124ArrayList_getAt(struct ArrayList *arrayList, size_t idx)
125{
126 assert(arrayList);
127 assert(idx < arrayList->size);
128
129 return arrayList->array[idx];
130}
131
132size_t
133ArrayList_size(struct ArrayList *arrayList)
134{
135 assert(arrayList);
136
137 return arrayList->size;
138}
139
140bool
141ArrayList_empty(struct ArrayList *arrayList)
142{
143 assert(arrayList);
144
145 return arrayList->size == 0;
146}
147
148void
149ArrayList_removeAt(struct ArrayList *arrayList, size_t idx, void clear_func(T *, void *), void *args)
150{
151 assert(arrayList);
152 assert(idx < arrayList->size);
153
154 if ( clear_func ) {
155 clear_func(arrayList->array[idx], args);
156 }
157
158#if defined(ARRAYLIST_KEEP_ORDER)
159 memmove(&arrayList->arrayList[idx],
160 &arrayList->arrayList[idx + 1],
161 (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 qsortHelper_context {
170 int (*cmp)(const T *, const T *, void *);
171 void *args;
172};
173
174typedef const T *const_T_ptr;
175
176static int
177ArrayList_qsortHelper(void *ctx, const void *a, const void *b)
178{
179 const const_T_ptr *aa = a;
180 const const_T_ptr *bb = b;
181
182 const struct qsortHelper_context *context = ctx;
183
184 return context->cmp(*aa, *bb, context->args);
185}
186
187void
188ArrayList_sort(struct ArrayList *arrayList, int cmp(const T *, const T *, void *), void *args)
189{
190 assert(arrayList);
191 assert(cmp);
192
193 struct qsortHelper_context context = {
194 .cmp = cmp,
195 .args = args
196 };
197
198 // Das vollständige qsort_x()-Drama: https://stackoverflow.com/a/46042467
199 qsort_r(arrayList->array, arrayList->size, sizeof arrayList->array[0], &context, ArrayList_qsortHelper);
200}
201
202bool
203ArrayList_linearSearch(struct ArrayList *arrayList, void *key, int cmp(void *, const T *, void *), void *args, size_t *loc)
204{
205 assert(arrayList);
206 assert(cmp);
207 assert(loc);
208
209 for ( size_t idx = 0; idx != arrayList->size; ++idx ) {
210 if ( cmp(key, arrayList->array[idx], args) == 0 ) {
211 *loc = idx;
212 return true;
213 }
214 }
215 return false;
216}
217
218struct bsearchHelper_context {
219 void *key;
220 int (*cmp)(void *, const T *, void *);
221 void *args;
222};
223
224static int
225ArrayList_bsearchHelper(const void *ctx, const void *el)
226{
227 const struct bsearchHelper_context *context = ctx;
228 const const_T_ptr * element = el;
229
230 return context->cmp(context->key, *element, context->args);
231}
232
233bool
234ArrayList_binarySearch(struct ArrayList *arrayList, void *key, int cmp(void *, const T *, void *), void *args, size_t *loc)
235{
236 assert(arrayList);
237 assert(cmp);
238 assert(loc);
239
240 struct bsearchHelper_context context = {
241 .key = key,
242 .cmp = cmp,
243 .args = args
244 };
245
246 T **pos = bsearch(&context, arrayList->array, arrayList->size, sizeof arrayList->array[0], ArrayList_bsearchHelper);
247 if ( pos ) {
248 *loc = (size_t)(pos - arrayList->array);
249 return true;
250 }
251 else {
252 return false;
253 }
254}
255
256void
257ArrayList_shuffle(struct ArrayList *arrayList, size_t rng(size_t, void *), void *args)
258{
259 assert(arrayList);
260 assert(rng);
261
262 if ( arrayList->size > 1 ) {
263 for ( size_t i = arrayList->size - 1; i > 0; --i ) {
264 size_t j = rng(i + 1, args);
265
266 // swap
267 T *t = arrayList->array[j];
268 arrayList->array[j] = arrayList->array[i];
269 arrayList->array[i] = t;
270 }
271 }
272}
273
274static void
275ArrayList_debugPrint(struct ArrayList *arrayList)
276{
277 for ( size_t idx = 0; idx != ArrayList_size(arrayList); ++idx ) {
278 T *ptr = ArrayList_getAt(arrayList, idx);
279 printf("%d, ", *ptr);
280 }
281 putchar('\n');
282}
283
284static int
285my_compare(const T *a, const T *b, void *args)
286{
287 (void) args;
288
289 if ( *a > *b )
290 return 1;
291 else if ( *a < *b )
292 return -1;
293 else
294 return 0;
295}
296
297static int
298my_search_compare(void *key, const T *element, void *args)
299{
300 (void) args;
301
302 int *a = key;
303
304 if ( *a < *element )
305 return -1;
306 else if ( *a > *element )
307 return 1;
308 else
309 return 0;
310}
311
312static size_t
313my_rng(size_t max, void *args)
314{
315 (void) args;
316 return (size_t) rand() % max;
317}
318
319static void
320ArrayList_testSort(struct ArrayList *arrayList)
321{
322 for ( size_t i = 1; i < arrayList->size; ++i ) {
323 if ( *arrayList->array[i - 1] > *arrayList->array[i] ) {
324 fprintf(stderr, "Fehler: %zu (%d, %d)\n", i, *arrayList->array[i - 1], *arrayList->array[i]);
325 exit(EXIT_FAILURE);
326 }
327 }
328}
329
330int
331main(void)
332{
333 srand(time(NULL));
334
335 int a = 11, b = 22, c = 33, d = 44;
336
337 struct ArrayList *arrayList = ArrayList_new();
338
339 ArrayList_append(arrayList, &a);
340 ArrayList_append(arrayList, &b);
341 ArrayList_append(arrayList, &c);
342 ArrayList_append(arrayList, &d);
343 ArrayList_debugPrint(arrayList); // 11, 22, 33, 44
344
345 ArrayList_removeAt(arrayList, 0, NULL, NULL);
346 ArrayList_debugPrint(arrayList); // 44, 22, 33
347
348 ArrayList_insertAt(arrayList, 3, &a);
349 ArrayList_debugPrint(arrayList); // 44, 22, 33, 11
350
351 ArrayList_sort(arrayList, my_compare, NULL);
352 ArrayList_testSort(arrayList);
353
354 ArrayList_debugPrint(arrayList); // 11, 22, 33, 44
355
356 size_t loc;
357 int dummy = 44;
358 if ( ArrayList_binarySearch(arrayList, &dummy, my_search_compare, NULL, &loc) ) {
359 printf("Gefunden: %zu\n", loc);
360 }
361
362 ArrayList_shuffle(arrayList, my_rng, NULL);
363 ArrayList_debugPrint(arrayList); // ??
364
365 ArrayList_delete(arrayList);
366
367 return EXIT_SUCCESS;
368}
diff --git a/src/avl.c b/src/avl.c
new file mode 100644
index 0000000..874cc6c
--- /dev/null
+++ b/src/avl.c
@@ -0,0 +1,471 @@
1// AVL Tree
2#include <assert.h>
3#include <stdbool.h>
4#include <stdio.h>
5#include <stdlib.h>
6#include <time.h>
7
8/* utils */
9#include "util.h"
10
11// clang-format off
12
13// Review: http://www.inr.ac.ru/~info21/ADen/
14// Tests: https://stackoverflow.com/q/3955680
15
16/* --8<-- avl_type */
17typedef int T;
18
19struct tree_node {
20 struct tree_node *left, *right;
21 int bal;
22 T key;
23 int count; /* collision counter */
24 /* ggf. weitere Felder... */
25};
26/* -->8-- */
27
28/* --8<-- avl_insert_r */
29static struct tree_node *
30insert_r(T x, struct tree_node *p, bool *h)
31{
32 struct tree_node *p1, *p2;
33
34 if ( p == NULL ) {
35 *h = true;
36
37 p = malloc(sizeof *p);
38 if ( p ) {
39 p->left = NULL;
40 p->right = NULL;
41 p->bal = 0;
42
43 p->key = x;
44 p->count = 1; /* hit counter */
45 }
46 else
47 ERROR("out of memory");
48 }
49 else if ( x < p->key ) {
50 p->left = insert_r(x, p->left, h);
51
52 if ( *h ) {
53 if ( p->bal == +1 ) {
54 p->bal = 0;
55 *h = false;
56 }
57 else if ( p->bal == 0 ) {
58 p->bal = -1;
59 }
60 else /* if ( p->bal == -1 ) */ {
61 p1 = p->left;
62 if ( p1->bal == -1 ) { /* single LL rotation */
63 p->left = p1->right; p1->right = p;
64 p->bal = 0; p = p1;
65 }
66 else { /* double LR rotation */
67 p2 = p1->right;
68 p1->right = p2->left; p2->left = p1;
69 p->left = p2->right; p2->right = p;
70 p->bal = ( p2->bal == -1 ) ? +1 : 0;
71 p1->bal = ( p2->bal == +1 ) ? -1 : 0;
72 p = p2;
73 }
74 p->bal = 0;
75 *h = false;
76 }
77 }
78 }
79 else if ( x > p->key ) {
80 p->right = insert_r(x, p->right, h);
81
82 if ( *h ) {
83 if ( p->bal == -1 ) {
84 p->bal = 0;
85 *h = false;
86 }
87 else if ( p->bal == 0 ) {
88 p->bal = +1;
89 }
90 else /* if ( p->bal == +1 ) */ {
91 p1 = p->right;
92 if ( p1->bal == +1 ) { /* single RR rotation */
93 p->right = p1->left; p1->left = p;
94 p->bal = 0; p = p1;
95 }
96 else { /* double RL rotation */
97 p2 = p1->left;
98 p1->left = p2->right; p2->right = p1;
99 p->right = p2->left; p2->left = p;
100 p->bal = ( p2->bal == +1 ) ? -1 : 0;
101 p1->bal = ( p2->bal == -1 ) ? +1 : 0;
102 p = p2;
103 }
104 p->bal = 0;
105 *h = false;
106 }
107 }
108 }
109 else {
110 /* handle collision! */
111 p->count++; /* hit counter */
112 *h = false;
113 }
114 assert(p != NULL);
115
116 return p;
117}
118/* -->8-- */
119
120/* --8<-- avl_insert */
121struct tree_node *
122insert(struct tree_node *tree, T data)
123{
124 bool h = false;
125 return insert_r(data, tree, &h);
126}
127/* -->8-- */
128
129/* --8<-- avl_balanceL */
130static struct tree_node *
131balanceL(struct tree_node *p, bool *h)
132{
133 if ( p->bal == -1 ) {
134 p->bal = 0;
135 }
136 else if ( p->bal == 0 ) {
137 p->bal = +1;
138 *h = false;
139 }
140 else /* if ( p->bal == +1 ) */ { /* rebalance */
141 struct tree_node *p1 = p->right;
142 if ( p1->bal >= 0 ) { /* singla RR rotation */
143 p->right = p1->left;
144 p1->left = p;
145 if ( p1->bal == 0 ) {
146 p->bal = +1;
147 p1->bal = -1;
148 *h = false;
149 }
150 else {
151 p->bal = 0;
152 p1->bal = 0;
153 }
154 p = p1;
155 }
156 else { /* double RL rotation */
157 struct tree_node *p2 = p1->left;
158 p1->left = p2->right;
159 p2->right = p1;
160 p->right = p2->left;
161 p2->left = p;
162 p->bal = ( p2->bal == +1 ) ? -1 : 0;
163 p1->bal = ( p2->bal == -1 ) ? +1 : 0;
164 p = p2;
165 p2->bal = 0;
166 }
167 }
168 return p;
169}
170/* -->8-- */
171
172/* --8<-- avl_balanceR */
173static struct tree_node *
174balanceR(struct tree_node *p, bool *h)
175{
176 if ( p->bal == +1 ) {
177 p->bal = 0;
178 }
179 else if ( p->bal == 0 ) {
180 p->bal = -1;
181 *h = false;
182 }
183 else /* p->bal == -1 */ { /* rebalance */
184 struct tree_node *p1 = p->left;
185 if ( p1->bal <= 0 ) { /* single LL rotation */
186 p->left = p1->right;
187 p1->right = p;
188 if ( p1->bal == 0 ) {
189 p->bal = -1;
190 p1->bal = +1;
191 *h = false;
192 }
193 else {
194 p->bal = 0;
195 p1->bal = 0;
196 }
197 p = p1;
198 }
199 else { /* double LR rotation */
200 struct tree_node *p2 = p1->right;
201 p1->right = p2->left;
202 p2->left = p1;
203 p->left = p2->right;
204 p2->right = p;
205 p->bal = ( p2->bal == -1 ) ? +1 : 0;
206 p1->bal = ( p2->bal == +1 ) ? -1 : 0;
207 p = p2;
208 p2->bal = 0;
209 }
210 }
211 return p;
212}
213/* -->8-- */
214
215/* --8<-- avl_del */
216static void
217del(struct tree_node **q, struct tree_node **r, bool *h)
218{
219 if ( (*r)->right ) {
220 del(q, &(*r)->right, h);
221 if ( *h )
222 *r = balanceR(*r, h);
223 }
224 else {
225 /* copy data */
226 (*q)->key = (*r)->key;
227 (*q)->count = (*r)->count;
228
229 *q = *r;
230 *r = (*r)->left;
231 *h = true;
232 }
233}
234/* -->8-- */
235
236/* --8<-- avl_delete_r */
237static struct tree_node *
238delete_r(T x, struct tree_node *p, bool *h)
239{
240 if ( p == NULL ) {
241 ERROR("key not found");
242 }
243 else if ( x < p->key ) {
244 p->left = delete_r(x, p->left, h);
245 if ( *h )
246 p = balanceL(p, h);
247 }
248 else if ( x > p->key ) {
249 p->right = delete_r(x, p->right, h);
250 if ( *h )
251 p = balanceR(p, h);
252 }
253 else /* if ( x == p->key ) */ {
254 struct tree_node *q = p;
255 if ( q->right == NULL ) {
256 p = q->left;
257 *h = true;
258 }
259 else if ( q->left == NULL ) {
260 p = q->right;
261 *h = true;
262 }
263 else {
264 del(&q, &q->left, h);
265 if ( *h )
266 p = balanceL(p, h);
267 }
268 free(q);
269 }
270 return p;
271}
272/* -->8-- */
273
274/* --8<-- avl_delete */
275struct tree_node *
276delete(struct tree_node *tree, T data)
277{
278 bool h = false;
279 return delete_r(data, tree, &h);
280}
281/* -->8-- */
282
283// aux display and verification routines, helpful but not essential
284struct trunk {
285 struct trunk *prev;
286 char * str;
287};
288
289void show_trunks(struct trunk *p)
290{
291 if (!p) return;
292 show_trunks(p->prev);
293 printf("%s", p->str);
294}
295
296// this is very haphazzard
297void show_tree(struct tree_node *root, struct trunk *prev, int is_left)
298{
299 if (root == NULL) return;
300
301 struct trunk this_disp = { prev, " " };
302 char *prev_str = this_disp.str;
303 show_tree(root->right, &this_disp, 1);
304
305 if (!prev)
306 this_disp.str = "---";
307 else if (is_left) {
308 this_disp.str = ".--";
309 prev_str = " |";
310 } else {
311 this_disp.str = "`--";
312 prev->str = prev_str;
313 }
314
315 show_trunks(&this_disp);
316 if ( root->key >= 'A' && root->key <= 'Z' )
317 printf("%c\n", root->key);
318 else
319 printf("%d\n", root->key);
320
321 if (prev) prev->str = prev_str;
322 this_disp.str = " |";
323
324 show_tree(root->left, &this_disp, 0);
325 if (!prev) puts("");
326}
327
328void
329print(struct tree_node *tree)
330{
331 if ( tree ) {
332 print(tree->left);
333 printf("%d (%d)\n", tree->key, tree->bal);
334 print(tree->right);
335 }
336}
337
338int
339main()
340{
341
342
343#if 0 /* 1a/b */
344 tree = insert(tree, 20);
345 tree = insert(tree, 4);
346 show_tree(tree, 0, 0);
347
348 //tree = insert(tree, 15);
349 tree = insert(tree, 8);
350 show_tree(tree, 0, 0);
351#endif
352
353#if 0 /* 2a/b */
354 tree = insert(tree, 20);
355 tree = insert(tree, 4);
356 tree = insert(tree, 26);
357 tree = insert(tree, 3);
358 tree = insert(tree, 9);
359 show_tree(tree, 0, 0);
360
361 //tree = insert(tree, 15);
362 tree = insert(tree, 8);
363 show_tree(tree, 0, 0);
364#endif
365
366#if 0 /* 3a/b */
367 tree = insert(tree, 20);
368 tree = insert(tree, 4);
369 tree = insert(tree, 26);
370 tree = insert(tree, 3);
371 tree = insert(tree, 9);
372 tree = insert(tree, 21);
373 tree = insert(tree, 30);
374 tree = insert(tree, 2);
375 tree = insert(tree, 7);
376 tree = insert(tree, 11);
377 show_tree(tree, 0, 0);
378
379 //tree = insert(tree, 15);
380 tree = insert(tree, 8);
381 show_tree(tree, 0, 0);
382#endif
383
384#if 0
385 tree = insert(tree, 2);
386 tree = insert(tree, 1);
387 tree = insert(tree, 4);
388 tree = insert(tree, 3);
389 tree = insert(tree, 5);
390 show_tree(tree, 0, 0);
391
392 tree = delete(tree, 1);
393 show_tree(tree, 0, 0);
394#endif
395
396#if 0
397 tree = insert(tree, 6);
398 tree = insert(tree, 2);
399 tree = insert(tree, 9);
400 tree = insert(tree, 1);
401 tree = insert(tree, 4);
402 tree = insert(tree, 8);
403 tree = insert(tree, 'B');
404 tree = insert(tree, 3);
405 tree = insert(tree, 5);
406 tree = insert(tree, 7);
407 tree = insert(tree, 'A');
408 tree = insert(tree, 'C');
409 tree = insert(tree, 'D');
410 show_tree(tree, 0, 0);
411
412 tree = delete(tree, 1);
413 show_tree(tree, 0, 0);
414#endif
415
416
417#if 0
418 tree = insert(tree, 5);
419 tree = insert(tree, 2);
420 tree = insert(tree, 8);
421 tree = insert(tree, 1);
422 tree = insert(tree, 3);
423 tree = insert(tree, 7);
424 tree = insert(tree, 'A');
425 tree = insert(tree, 4);
426 tree = insert(tree, 6);
427 tree = insert(tree, 9);
428 tree = insert(tree, 'B');
429 tree = insert(tree, 'C');
430 show_tree(tree, 0, 0);
431
432 tree = delete(tree, 1);
433 show_tree(tree, 0, 0);
434#endif
435
436
437#if 0
438 tree = insert(tree, 5);
439 tree = insert(tree, 3);
440 tree = insert(tree, 8);
441 tree = insert(tree, 2);
442 tree = insert(tree, 4);
443 tree = insert(tree, 7);
444 tree = insert(tree, 10);
445 tree = insert(tree, 1);
446 tree = insert(tree, 6);
447 tree = insert(tree, 9);
448 tree = insert(tree, 11);
449
450 tree = delete(tree, 4);
451 tree = delete(tree, 8);
452 tree = delete(tree, 6);
453 tree = delete(tree, 5);
454 tree = delete(tree, 2);
455 tree = delete(tree, 1);
456 tree = delete(tree, 7);
457
458 show_tree(tree, 0, 0);
459#endif
460
461 struct tree_node *tree = NULL;
462
463 srand(time(NULL));
464 for ( int i = 0; i != 300000; ++i )
465 tree = insert(tree, rand());
466
467 //show_tree(tree, 0, 0);
468
469 return EXIT_SUCCESS;
470}
471
diff --git a/src/deque.c b/src/deque.c
new file mode 100644
index 0000000..881d1d3
--- /dev/null
+++ b/src/deque.c
@@ -0,0 +1,485 @@
1#include <assert.h>
2#include <stdbool.h>
3#include <stdio.h>
4#include <stdlib.h>
5
6#include "util.h"
7
8#define START_MAP_CAPACITY 4
9#define CHUNK_CAPACITY 17
10
11/* --8<-- deque_type */
12typedef int T;
13
14struct deque {
15 T **map;
16
17 size_t map_begin;
18 size_t map_end;
19 size_t map_capacity;
20
21 size_t offset;
22 size_t size;
23};
24/* -->8-- */
25
26/* --8<-- deque_allocate */
27static void *
28allocate(size_t n, size_t sz)
29{
30 void *ptr = calloc(n, sz);
31 if ( ptr == NULL ) {
32 ERROR("out of memory!");
33 }
34 return ptr;
35}
36/* -->8-- */
37
38/* --8<-- deque_init */
39void
40deque_init(struct deque *d)
41{
42 assert(d);
43
44 d->map_begin = 0;
45 d->map_end = 0;
46 d->offset = 0;
47 d->size = 0;
48
49 // TODO: Error handling
50 d->map = allocate(START_MAP_CAPACITY, sizeof *d->map);
51 if ( d->map ) {
52 d->map_capacity = START_MAP_CAPACITY;
53
54 for ( size_t i = 0; i != d->map_capacity; ++i ) {
55 d->map[i] = NULL;
56 }
57 }
58}
59/* -->8-- */
60
61/* --8<-- deque_free */
62void
63deque_free(struct deque *d)
64{
65 assert(d);
66
67 // free all chunks
68 for ( size_t i = 0; i != d->map_capacity; ++i ) {
69 free(d->map[i]);
70 }
71
72 // free the map itself
73 free(d->map);
74 d->map = NULL;
75}
76/* -->8-- */
77
78/* --8<-- deque_size */
79size_t
80deque_size(struct deque *d)
81{
82 assert(d);
83
84 return d->size;
85}
86/* -->8-- */
87
88/* --8<-- deque_is_empty */
89bool
90deque_is_empty(struct deque *d)
91{
92 assert(d);
93
94 return d->map_begin == d->map_end;
95}
96/* -->8-- */
97
98/* --8<-- deque_grow_map */
99static void
100grow_map(struct deque *d)
101{
102 assert(d);
103
104 const size_t capacity = d->map_capacity + d->map_capacity / 2;
105 T ** map = allocate(capacity, sizeof *map);
106
107 // copy elements
108 size_t i, j;
109 for ( i = 0, j = d->map_begin; i != d->map_capacity; ++i, ++j ) {
110 if ( j == d->map_capacity ) {
111 j = 0;
112 }
113 map[i] = d->map[j];
114 }
115
116 // initialize the rest (new) elements with NULL
117 for ( ; i != capacity; ++i ) {
118 map[i] = NULL;
119 }
120
121 // free old & assign new map
122 free(d->map);
123 d->map = map;
124
125 // adjust pointers
126 d->map_begin = 0;
127 d->map_end = d->map_capacity - 1;
128
129 // set new map_capacity
130 d->map_capacity = capacity;
131}
132/* -->8-- */
133
134/* --8<-- deque_map_append_chunk */
135static void
136map_append_chunk(struct deque *d)
137{
138 assert(d);
139
140 size_t next = (d->map_end + 1) % d->map_capacity;
141
142 if ( next == d->map_begin ) { // Resize the map
143 grow_map(d);
144
145 next = d->map_end + 1;
146 }
147
148 d->map[d->map_end] = allocate(CHUNK_CAPACITY, sizeof **d->map);
149 d->map_end = next;
150}
151/* -->8-- */
152
153/* --8<-- deque_map_prepend_chunk */
154static void
155map_prepend_chunk(struct deque *d)
156{
157 assert(d);
158
159 size_t prev = (d->map_begin + d->map_capacity - 1) % d->map_capacity;
160
161 if ( prev == d->map_end ) {
162 grow_map(d);
163
164 prev = d->map_capacity - 1;
165 }
166
167 d->map[prev] = allocate(CHUNK_CAPACITY, sizeof **d->map);
168 d->map_begin = prev;
169}
170/* -->8-- */
171
172/* --8<-- deque_map_remove_front_chunk */
173static void
174map_remove_front_chunk(struct deque *d)
175{
176 assert(d);
177
178 if ( d->map_begin == d->map_end ) {
179 return;
180 }
181
182 const size_t next = (d->map_begin + 1) % d->map_capacity;
183
184 free(d->map[d->map_begin]);
185 d->map[d->map_begin] = NULL;
186
187 d->map_begin = next;
188}
189/* -->8-- */
190
191/* --8<-- deque_remove_tail_chunk */
192static void
193map_remove_tail_chunk(struct deque *d)
194{
195 assert(d);
196
197 if ( d->map_begin == d->map_end ) {
198 return;
199 }
200
201 const size_t prev = (d->map_end + d->map_capacity - 1) % d->map_capacity;
202
203 free(d->map[prev]);
204 d->map[prev] = NULL;
205
206 d->map_end = prev;
207}
208/* -->8-- */
209
210/* --8<-- deque_get_at */
211bool
212deque_get_at(struct deque *d, size_t idx, T *data)
213{
214 assert(d);
215 assert(idx < d->size);
216 assert(data);
217
218 if ( idx >= d->size ) {
219 return false;
220 }
221
222 const size_t pos = d->offset + idx;
223 const size_t chunk_off = pos % CHUNK_CAPACITY;
224 const size_t chunk_num = (pos / CHUNK_CAPACITY + d->map_begin) % d->map_capacity;
225
226 *data = d->map[chunk_num][chunk_off];
227
228 return true;
229}
230/* -->8-- */
231
232/* --8<-- deque_set_at */
233bool
234deque_set_at(struct deque *d, size_t idx, T data)
235{
236 assert(d);
237 assert(idx < d->size);
238
239 if ( idx >= d->size ) {
240 return false;
241 }
242
243 const size_t pos = d->offset + idx;
244 const size_t chunk_off = pos % CHUNK_CAPACITY;
245 const size_t chunk_num = (pos / CHUNK_CAPACITY + d->map_begin) % d->map_capacity;
246
247 d->map[chunk_num][chunk_off] = data;
248
249 return true;
250}
251/* -->8-- */
252
253/* --8<-- deque_push_back */
254void
255deque_push_back(struct deque *d, T data)
256{
257 assert(d);
258
259 const size_t pos = d->offset + d->size;
260 const size_t chunk_off = pos % CHUNK_CAPACITY;
261 size_t chunk_num = (pos / CHUNK_CAPACITY + d->map_begin) % d->map_capacity;
262
263 if ( chunk_num == d->map_end ) {
264 map_append_chunk(d);
265 chunk_num = (pos / CHUNK_CAPACITY + d->map_begin) % d->map_capacity;
266 }
267
268 d->map[chunk_num][chunk_off] = data;
269 ++d->size;
270}
271/* -->8-- */
272
273/* --8<-- deque_push_front */
274void
275deque_push_front(struct deque *d, T data)
276{
277 assert(d);
278
279 if ( d->offset == 0 ) { // Im ersten Element ist kein Platz mehr frei!
280 map_prepend_chunk(d);
281 d->offset = CHUNK_CAPACITY;
282 }
283
284 --d->offset;
285
286 const size_t chunk_num = (d->offset / CHUNK_CAPACITY + d->map_begin) % d->map_capacity;
287
288 d->map[chunk_num][d->offset] = data;
289 ++d->size;
290}
291/* -->8-- */
292
293/* --8<-- deque_pop_back */
294bool
295deque_pop_back(struct deque *d, T *data)
296{
297 assert(d);
298 assert(data);
299
300 if ( d->size == 0 ) {
301 return false;
302 }
303
304 --d->size;
305
306 const size_t pos = d->offset + d->size;
307 const size_t chunk_off = pos % CHUNK_CAPACITY;
308 const size_t chunk_num = (pos / CHUNK_CAPACITY + d->map_begin) % d->map_capacity;
309
310 *data = d->map[chunk_num][chunk_off];
311
312 if ( d->size == 0 || chunk_off == 0 ) {
313 map_remove_tail_chunk(d);
314 }
315
316 return true;
317}
318/* -->8-- */
319
320/* --8<-- deque_pop_front */
321bool
322deque_pop_front(struct deque *d, T *data)
323{
324 assert(d);
325 assert(data);
326
327 if ( d->size == 0 ) {
328 return false;
329 }
330
331 --d->size;
332
333 const size_t chunk_num = (d->offset / CHUNK_CAPACITY + d->map_begin) % d->map_capacity;
334
335 *data = d->map[chunk_num][d->offset];
336
337 ++d->offset;
338
339 if ( d->size == 0 || d->offset == CHUNK_CAPACITY ) {
340 map_remove_front_chunk(d);
341 d->offset = 0;
342 }
343
344 return true;
345}
346/* -->8-- */
347
348static void
349deque_show(struct deque *d)
350{
351 assert(d);
352
353 printf("first: %zu -- last: %zu -- size: %zu -- map_capacity: %zu -- offset: %zu\n",
354 d->map_begin, d->map_end, d->size, d->map_capacity, d->offset);
355 for ( size_t i = 0; i != d->map_capacity; ++i ) {
356 printf("%zu(%p) ", i, (void *) d->map[i]);
357 }
358 putchar('\n');
359}
360
361void
362test_deque(void)
363{
364#ifndef NDEBUG
365 struct deque d[1];
366
367 deque_init(d);
368
369 const int N = 100000;
370
371 for ( int i = 0; i != N; ++i ) {
372 deque_push_front(d, i);
373 }
374
375 for ( int i = 0; i != N; ++i ) {
376 int data;
377 assert(deque_pop_back(d, &data) == true);
378 assert(data == i);
379 }
380 assert(deque_is_empty(d) == true);
381 assert(deque_size(d) == 0);
382
383 deque_free(d);
384
385 deque_init(d);
386
387 for ( int i = 0; i != N; ++i ) {
388 deque_push_back(d, i);
389 }
390
391 for ( int i = 0; i != N; ++i ) {
392 int data;
393 assert(deque_pop_front(d, &data) == true);
394 assert(data == i);
395 }
396 assert(deque_is_empty(d) == true);
397 assert(deque_size(d) == 0);
398
399 deque_free(d);
400
401 deque_init(d);
402
403 for ( int i = 0; i != N; ++i ) {
404 deque_push_back(d, i);
405 }
406
407 for ( int i = N - 1; i >= 0; --i ) {
408 int data;
409 assert(deque_pop_back(d, &data) == true);
410 assert(data == i);
411 }
412 assert(deque_is_empty(d) == true);
413 assert(deque_size(d) == 0);
414
415 deque_free(d);
416
417 deque_init(d);
418
419 for ( int i = 0; i != N; ++i ) {
420 if ( i & 1 ) {
421 deque_push_front(d, i);
422 }
423 else {
424 deque_push_back(d, i);
425 }
426 }
427
428 for ( int i = N - 1; i >= 0; --i ) {
429 int data;
430 if ( i & 1 ) {
431 assert(deque_pop_front(d, &data) == true);
432 }
433 else {
434 assert(deque_pop_back(d, &data) == true);
435 }
436 if ( data != i ) {
437 printf("i: %d - data: %d\n", i, data);
438 }
439 assert(data == i);
440 }
441 assert(deque_is_empty(d) == true);
442 assert(deque_size(d) == 0);
443
444 deque_free(d);
445
446 deque_init(d);
447
448 for ( int i = 0; i != N; ++i ) {
449 deque_push_front(d, i);
450 }
451
452 for ( int i = N - 1; i >= 0; --i ) {
453 int data;
454 assert(deque_pop_front(d, &data) == true);
455 assert(data == i);
456 }
457 assert(deque_is_empty(d) == true);
458 assert(deque_size(d) == 0);
459
460 deque_free(d);
461
462 puts("all tests passed.");
463#endif
464}
465
466int
467main(void)
468{
469 test_deque();
470
471 struct deque c;
472
473 deque_init(&c);
474
475 T data;
476 while ( deque_pop_front(&c, &data) ) {
477 printf("%u, ", data);
478 }
479 putchar('\n');
480 deque_show(&c);
481
482 deque_free(&c);
483
484 return 0;
485}
diff --git a/src/dlist.c b/src/dlist.c
new file mode 100644
index 0000000..55e42d7
--- /dev/null
+++ b/src/dlist.c
@@ -0,0 +1,504 @@
1/* dlist -- double linked list */
2
3/* Standard C */
4#include <assert.h>
5#include <stdbool.h>
6#include <stdio.h>
7#include <stdlib.h>
8#include <time.h>
9
10/* Project */
11#include "util.h"
12
13/* --8<-- dlist_type */
14typedef int T;
15
16struct dlist {
17 struct dlist_element *head, *tail;
18};
19
20struct dlist_element {
21 struct dlist_element *prev, *next;
22 T data;
23};
24/* -->8-- */
25
26/* --8<-- dlist_init */
27void
28dlist_init(struct dlist *dlist)
29{
30 dlist->head = NULL;
31 dlist->tail = NULL;
32}
33/* -->8-- */
34
35/* --8<-- dlist_empty */
36bool
37dlist_empty(struct dlist *dlist)
38{
39 return dlist->head == NULL;
40}
41/* -->8-- */
42
43/* --8<-- dlist_create_element */
44static struct dlist_element *
45create_element(T data)
46{
47 struct dlist_element *element;
48
49 element = malloc(sizeof *element);
50 if ( element ) {
51 element->data = data;
52 }
53
54 return element;
55}
56/* -->8-- */
57
58/* --8<-- dlist_push_front */
59struct dlist_element *
60dlist_push_front(struct dlist *dlist, T data)
61{
62 struct dlist_element *element;
63
64 element = create_element(data);
65 if ( element ) {
66 element->prev = NULL; /* Vorgänger ist in jedem Fall NULL */
67
68 if ( dlist_empty(dlist) ) {
69 element->next = NULL;
70 dlist->tail = element;
71 }
72 else {
73 element->next = dlist->head;
74 element->next->prev = element;
75 }
76
77 dlist->head = element; /* Neues Element ist in jedem Fall der neue Anfang! */
78 }
79 else
80 ERROR("out of memory");
81
82 return element;
83}
84/* -->8-- */
85
86/* --8<-- dlist_push_back */
87struct dlist_element *
88dlist_push_back(struct dlist *dlist, T data)
89{
90 struct dlist_element *element;
91
92 element = create_element(data);
93 if ( element ) {
94 element->next = NULL; /* Nachfolger ist in jedem Fall NULL */
95
96 if ( dlist_empty(dlist) ) {
97 element->prev = NULL;
98 dlist->head = element;
99 }
100 else {
101 element->prev = dlist->tail;
102 element->prev->next = element;
103 }
104
105 dlist->tail = element; /* Neues Element ist in jedem Fall das neue Ende! */
106 }
107 else
108 ERROR("out of memory");
109
110 return element;
111}
112/* -->8-- */
113
114/* --8<-- dlist_pop_front */
115bool
116dlist_pop_front(struct dlist *dlist, T *data)
117{
118 if ( dlist->head ) {
119 struct dlist_element *element = dlist->head;
120
121 dlist->head = element->next;
122
123 if ( dlist->head == NULL )
124 dlist->tail = NULL;
125 else
126 element->next->prev = NULL;
127
128 if ( data ) {
129 *data = element->data;
130 }
131 free(element);
132
133 return true;
134 }
135 else
136 return false;
137}
138/* -->8-- */
139
140/* --8<-- dlist_pop_back */
141bool
142dlist_pop_back(struct dlist *dlist, T *data)
143{
144 if ( dlist->head ) {
145 struct dlist_element *element = dlist->tail;
146
147 dlist->tail = element->prev;
148
149 if ( dlist->tail == NULL )
150 dlist->head = NULL;
151 else
152 element->prev->next = NULL;
153
154 if ( data ) {
155 *data = element->data;
156 }
157 free(element);
158
159 return true;
160 }
161 else
162 return false;
163}
164/* -->8-- */
165
166/* --8<-- dlist_insert_next */
167struct dlist_element *
168dlist_insert_next(struct dlist *dlist, struct dlist_element *element, T data)
169{
170 struct dlist_element *new_element;
171
172 new_element = create_element(data);
173 if ( new_element ) {
174 if ( dlist->head == NULL ) {
175 dlist->head = new_element;
176 dlist->head->prev = NULL;
177 dlist->head->next = NULL;
178 dlist->tail = new_element;
179 }
180 else {
181 new_element->next = element->next;
182 new_element->prev = element;
183
184 if ( element->next == NULL )
185 dlist->tail = new_element;
186 else
187 element->next->prev = new_element;
188
189 element->next = new_element;
190 }
191 }
192 else
193 ERROR("out of memory");
194
195 return new_element;
196}
197/* -->8-- */
198
199/* --8<-- dlist_insert_prev */
200struct dlist_element *
201dlist_insert_prev(struct dlist *dlist, struct dlist_element *element, T data)
202{
203 struct dlist_element *new_element;
204
205 new_element = create_element(data);
206 if ( new_element ) {
207 if ( dlist->head == NULL ) {
208 dlist->head = new_element;
209 dlist->head->prev = NULL;
210 dlist->head->next = NULL;
211 dlist->tail = new_element;
212 }
213 else {
214 new_element->next = element;
215 new_element->prev = element->prev;
216
217 if ( element->prev == NULL )
218 dlist->head = new_element;
219 else
220 element->prev->next = new_element;
221
222 element->prev = new_element;
223 }
224 }
225 else
226 ERROR("out of memory");
227
228 return new_element;
229}
230/* -->8-- */
231
232/* --8<-- dlist_remove */
233void
234dlist_remove(struct dlist *dlist, struct dlist_element *element)
235{
236 if ( element == dlist->head ) {
237 dlist->head = element->next;
238
239 if ( dlist->head == NULL )
240 dlist->tail = NULL;
241 else
242 element->next->prev = NULL;
243 }
244 else {
245 element->prev->next = element->next;
246
247 if ( element->next == NULL )
248 dlist->tail = element->prev;
249 else
250 element->next->prev = element->prev;
251 }
252
253 free(element);
254}
255/* -->8-- */
256
257/* --8<-- dlist_free */
258void
259dlist_free(struct dlist *dlist)
260{
261 struct dlist_element *elem, *next;
262
263 for ( elem = dlist->head; elem; elem = next ) {
264 next = elem->next;
265 free(elem);
266 }
267
268 dlist_init(dlist);
269}
270/* -->8-- */
271
272void
273dlist_apply_rev(struct dlist *dlist, void (*visit)(T data, void *cl), void *cl)
274{
275 for ( struct dlist_element *elem = dlist->tail; elem; elem = elem->prev ) {
276 visit(elem->data, cl);
277 }
278}
279
280void
281print_list(const char *msg, struct dlist *dlist)
282{
283 printf("%s:", msg);
284
285 for ( struct dlist_element *elem = dlist->head; elem; elem = elem->next )
286 printf(" %d", elem->data);
287
288 putchar('\n');
289}
290
291void
292print_list_rev(const char *msg, struct dlist *dlist)
293{
294 printf("%s:", msg);
295
296 for ( struct dlist_element *elem = dlist->tail; elem; elem = elem->prev )
297 printf(" %d", elem->data);
298
299 putchar('\n');
300}
301
302void
303remove_if(struct dlist *list)
304{
305 struct dlist_element *elem, *next;
306
307 for ( elem = list->head; elem; elem = next ) {
308 next = elem->next;
309
310 if ( (elem->data & 1) == 1 ) {
311 dlist_remove(list, elem);
312 }
313 }
314}
315
316/* --8<-- dlist_merge */
317struct dlist *
318dlist_merge(struct dlist *list1, struct dlist *list2)
319{
320 struct dlist_element *head = NULL,
321 *cur = NULL,
322 *e1 = list1->head,
323 *e2 = list2->head;
324
325 while ( e1 && e2 ) // Solange in e1 UND e2 Elemente sind...
326 {
327 if ( e1->data < e2->data ) {
328 e1->prev = cur;
329 if ( cur )
330 cur->next = e1;
331 else
332 head = e1;
333 cur = e1;
334 e1 = e1->next;
335 }
336 else {
337 e2->prev = cur;
338 if ( cur )
339 cur->next = e2;
340 else
341 head = e2;
342 cur = e2;
343 e2 = e2->next;
344 }
345 }
346
347 if ( e1 ) // in e1 sind noch Elemente vorhanden!
348 {
349 assert(e2 == NULL);
350
351 e1->prev = cur;
352 if ( cur )
353 cur->next = e1;
354 else
355 head = e1;
356
357 // list1->tail zeigt bereits auf das letzte Element in list1
358 }
359 else /* if ( e2 ) */
360 {
361 assert(e1 == NULL);
362 assert(e2);
363
364 e2->prev = cur;
365 if ( cur )
366 cur->next = e2;
367 else
368 head = e2;
369
370 list1->tail = list2->tail; // list2->tail ist das Ende der Liste
371 }
372
373 // Kopf neu setzen...
374 list1->head = head;
375
376 // Liste2 ist leer
377 list2->head = NULL;
378 list2->tail = NULL;
379
380 // Zeiger auf Liste1 zurückliefern
381 return list1;
382}
383/* -->8-- */
384
385/* --8<-- dlist_sort */
386struct dlist *
387dlist_sort(struct dlist *list)
388{
389 if ( list->head == NULL || list->head->next == NULL ) // Leer oder nur ein Element? => Fertig
390 return list;
391
392 struct dlist_element *slow = list->head,
393 *fast = list->head->next;
394
395 while ( fast && fast->next )
396 slow = slow->next, fast = fast->next->next;
397
398 struct dlist list1 = { .head = list->head, .tail = slow },
399 list2 = { .head = slow->next, .tail = list->tail };
400
401 list1.tail->next = list2.head->prev = NULL;
402
403 dlist_merge(dlist_sort(&list1), dlist_sort(&list2));
404
405 list->head = list1.head;
406 list->tail = list1.tail;
407
408 return list;
409}
410/* -->8-- */
411
412void
413merge_test(void)
414{
415 struct dlist l1, l2;
416
417 dlist_init(&l1);
418 dlist_init(&l2);
419
420 dlist_push_back(&l1, 7);
421 dlist_push_back(&l1, 10);
422 dlist_push_back(&l1, 11);
423 dlist_push_back(&l1, 19);
424 dlist_push_back(&l1, 23);
425
426 dlist_push_back(&l2, 4);
427 dlist_push_back(&l2, 14);
428 dlist_push_back(&l2, 15);
429
430 struct dlist *ptr;
431 ptr = dlist_merge(&l1, &l2);
432
433 struct dlist_element *cur;
434 for ( cur = ptr->head; cur; cur = cur->next ) {
435 if ( cur->prev )
436 printf("%4d", cur->prev->data);
437 else
438 printf("xxx ");
439 printf("%4d", cur->data);
440 if ( cur->next )
441 printf("%4d", cur->next->data);
442 else
443 printf(" xxx");
444
445 puts("");
446 }
447
448 dlist_free(&l1);
449 dlist_free(&l2);
450}
451
452void
453ls()
454{
455 struct dlist list;
456
457 dlist_init(&list);
458
459 for ( int i = 0; i != 30000000; ++i )
460 dlist_insert_prev(&list, list.tail, rand() % 9999);
461
462 //print_list("Unsortiert:", &list);
463 printf("start\n");
464 clock_t start = clock();
465 dlist_sort(&list);
466 clock_t ende = clock();
467
468 printf("Dauer: %.3fsec\n", ((double) ende - start) / CLOCKS_PER_SEC);
469 //print_list("Sortiert:", &list);
470 //print_list_rev("Sortiert:", &list);
471
472 dlist_free(&list);
473}
474
475int
476main(void)
477{
478 ls();
479
480#if 0
481 merge_test();
482#endif
483
484#if 0
485 struct dlist list;
486
487 dlist_init(&list);
488
489 for ( int i = 0; i != 10; ++i )
490 dlist_insert_prev(&list, list.tail, i);
491
492 print_list("Ausgabe: ", &list);
493
494 remove_if(&list);
495
496 print_list("Ausgabe: ", &list);
497
498 dlist_free(&list);
499
500 ls();
501
502 return EXIT_SUCCESS;
503#endif
504}
diff --git a/src/hashtab.c b/src/hashtab.c
new file mode 100644
index 0000000..256fac9
--- /dev/null
+++ b/src/hashtab.c
@@ -0,0 +1,220 @@
1#include <ctype.h>
2#include <stdbool.h>
3#include <stdio.h>
4#include <stdlib.h>
5#include <string.h>
6
7#include "util.h"
8
9/* --8<-- hash_type */
10typedef int T;
11
12struct hash_item {
13 struct hash_item *next;
14 char * key;
15 T data;
16};
17
18struct hash_tab {
19 struct hash_item *table[251]; // fit for your needs...
20};
21/* -->8-- */
22
23/* --8<-- hash_key */
24static unsigned long
25hash_key(const unsigned char *str)
26{
27 unsigned long hash = 5381;
28 unsigned int c;
29
30 while ( (c = *str++) != '\0' )
31 hash = ((hash << 5) + hash) + c; /* hash * 33 + c */
32
33 return hash;
34}
35/* -->8-- */
36
37/* --8<-- hash_init */
38void
39hash_init(struct hash_tab *ht)
40{
41 for ( size_t i = 0; i != NELEM(ht->table); ++i )
42 ht->table[i] = NULL;
43}
44/* -->8-- */
45
46/* --8<-- hash_add */
47static struct hash_item *
48hash_add(struct hash_item *next, const char *key, T data)
49{
50 struct hash_item *new_item;
51 char * new_key;
52
53 new_key = strdup(key); // strdup: not standard but commonly used...
54 new_item = malloc(sizeof *new_item);
55
56 if ( new_key == NULL || new_item == NULL ) {
57 free(new_key);
58 free(new_item);
59 ERROR("out of memory");
60 return NULL;
61 }
62
63 new_item->next = next;
64 new_item->key = new_key;
65 new_item->data = data;
66
67 return new_item;
68}
69/* -->8-- */
70
71/* --8<-- hash_lookup */
72T *
73hash_lookup(struct hash_tab *ht, const char *key, T data, int create)
74{
75 unsigned long h;
76 struct hash_item *item;
77
78 h = hash_key((const unsigned char *) key) % NELEM(ht->table);
79 for ( item = ht->table[h]; item; item = item->next )
80 if ( strcmp(key, item->key) == 0 )
81 return &item->data;
82
83 // not found! create?
84 if ( create ) {
85 item = hash_add(ht->table[h], key, data);
86 if ( item )
87 ht->table[h] = item;
88 else
89 ERROR("can't create item");
90 }
91
92 return item ? &item->data : NULL;
93}
94/* -->8-- */
95
96/* --8<-- hash_delete */
97bool
98hash_delete(struct hash_tab *ht, const char *key)
99{
100 unsigned long h;
101 struct hash_item *prev, *p;
102
103 h = hash_key((const unsigned char *) key) % NELEM(ht->table);
104 prev = NULL;
105 for ( p = ht->table[h]; p; p = p->next ) {
106 if ( strcmp(key, p->key) == 0 ) {
107 if ( prev == NULL )
108 ht->table[h] = p->next;
109 else
110 prev->next = p->next;
111
112 free(p->key);
113 free(p);
114
115 return true; // successfully removed!
116 }
117 prev = p;
118 }
119
120 return false;
121}
122/* -->8-- */
123
124/* --8<-- hash_apply */
125void
126hash_apply(struct hash_tab *ht, void (*visit)(const char *key, T data, void *cl), void *cl)
127{
128 struct hash_item *item;
129
130 for ( size_t i = 0; i != NELEM(ht->table); ++i )
131 for ( item = ht->table[i]; item; item = item->next )
132 visit(item->key, item->data, cl);
133}
134/* -->8-- */
135
136/* --8<-- hash_free */
137void
138hash_free(struct hash_tab *ht)
139{
140 struct hash_item *p, *next;
141
142 for ( size_t i = 0; i != NELEM(ht->table); ++i ) {
143 for ( p = ht->table[i]; p; p = next ) {
144 next = p->next;
145 free(p->key);
146 free(p);
147 }
148 ht->table[i] = NULL;
149 }
150}
151/* -->8-- */
152
153static int
154getword(FILE *fp, char *buf, size_t size, int first(int), int rest(int))
155{
156 size_t i = 0;
157 int c;
158
159 c = getc(fp);
160 for ( ; c != EOF; c = getc(fp) )
161 if ( first(c) ) {
162 if ( i < size - 1 )
163 buf[i++] = c;
164 c = getc(fp);
165 break;
166 }
167
168 for ( ; c != EOF && rest(c); c = getc(fp) )
169 if ( i < size - 1 )
170 buf[i++] = c;
171
172 if ( i < size )
173 buf[i] = 0;
174 else
175 buf[size - 1] = 0;
176
177 if ( c != EOF )
178 ungetc(c, fp);
179
180 return c > 0;
181}
182
183static int
184first(int c)
185{
186 return isalpha(c);
187}
188
189static int
190rest(int c)
191{
192 return isalpha(c) || c == '_';
193}
194
195static void
196print(const char *key, T data, void *cl)
197{
198 fprintf(cl, "%s: %d\n", key, data);
199}
200
201int
202main()
203{
204 struct hash_tab ht[1];
205 char word[100];
206
207 hash_init(ht);
208
209 while ( getword(stdin, word, sizeof word, first, rest) ) {
210 T *p = hash_lookup(ht, word, 0, 1);
211 if ( p )
212 ++(*p);
213 }
214
215 hash_delete(ht, "new_item");
216
217 hash_apply(ht, print, stdout);
218
219 hash_free(ht);
220}
diff --git a/src/heap.c b/src/heap.c
new file mode 100644
index 0000000..091e761
--- /dev/null
+++ b/src/heap.c
@@ -0,0 +1,291 @@
1#include <assert.h>
2#include <stdbool.h>
3#include <stdio.h>
4#include <stdlib.h>
5#include <time.h>
6
7#include "util.h"
8
9typedef int T;
10
11// https://stackoverflow.com/a/22900767
12
13#define LEFT(idx) (idx * 2 + 1)
14#define RIGHT(idx) (idx * 2 + 2)
15#define PARENT(idx) ((idx - 1) / 2)
16
17static void
18swap(T heap[], size_t i, size_t j)
19{
20 T temp = heap[i];
21 heap[i] = heap[j];
22 heap[j] = temp;
23}
24
25#define MAX_HEAP 1
26
27#if defined(MAX_HEAP)
28// MAX-HEAP Implementation
29static void
30fixup(T heap[], size_t i)
31{
32 size_t p = PARENT(i);
33
34 while ( i > 0 && heap[p] < heap[i] ) {
35 swap(heap, p, i);
36
37 i = p;
38 p = PARENT(i);
39 }
40}
41
42static void
43fixdown(T heap[], size_t i, size_t n)
44{
45 for ( ;; ) {
46 const size_t l = LEFT(i);
47 const size_t r = RIGHT(i);
48 size_t m = i;
49
50 if ( l < n && heap[m] < heap[l] ) {
51 m = l;
52 }
53
54 if ( r < n && heap[m] < heap[r] ) {
55 m = r;
56 }
57
58 if ( m == i ) {
59 break;
60 }
61
62 swap(heap, m, i);
63
64 i = m;
65 }
66}
67
68static bool
69is_heap(T heap[], size_t n)
70{
71 for ( size_t i = 0; i < n / 2; ++i ) {
72 const size_t l = LEFT(i);
73 const size_t r = RIGHT(i);
74
75 if ( l < n && heap[i] < heap[l] ) {
76 return false;
77 }
78 if ( r < n && heap[i] < heap[r] ) {
79 return false;
80 }
81 }
82 return true;
83}
84
85#else
86// MIN-HEAP Implementation
87static void
88fixup(T heap[], size_t i)
89{
90 size_t p = PARENT(i);
91
92 while ( i > 0 && heap[i] < heap[p] ) {
93 swap(heap, i, p);
94
95 i = p;
96 p = PARENT(i);
97 }
98}
99
100static void
101fixdown(T heap[], size_t i, size_t n)
102{
103 for ( ;; ) {
104 const size_t l = LEFT(i);
105 const size_t r = RIGHT(i);
106 size_t m = i;
107
108 if ( l < n && heap[l] < heap[m] ) {
109 m = l;
110 }
111
112 if ( r < n && heap[r] < heap[m] ) {
113 m = r;
114 }
115
116 if ( m == i ) {
117 break;
118 }
119
120 swap(heap, m, i);
121
122 i = m;
123 }
124}
125
126static bool
127is_heap(T heap[], size_t n)
128{
129 for ( size_t i = 0; i < n / 2; ++i ) {
130 const size_t l = LEFT(i);
131 const size_t r = RIGHT(i);
132
133 if ( l < n && heap[i] > heap[l] ) {
134 return false;
135 }
136 if ( r < n && heap[i] > heap[r] ) {
137 return false;
138 }
139 }
140 return true;
141}
142#endif
143
144static void
145heapify(T heap[], size_t n)
146{
147 for ( size_t i = n / 2; i-- > 0; ) {
148 fixdown(heap, i, n);
149 }
150
151 assert(is_heap(heap, n));
152}
153
154static void
155my_heapsort(T a[], size_t n)
156{
157 heapify(a, n);
158
159 while ( n-- ) {
160 swap(a, 0, n);
161 fixdown(a, 0, n);
162 }
163}
164
165// -------------------------------------------
166
167struct pq { // Priority Queue
168 T heap[251];
169 size_t sz;
170};
171
172void
173pq_init(struct pq *pq)
174{
175 pq->sz = 0;
176}
177
178bool
179pq_push(struct pq *pq, T data)
180{
181 if ( pq->sz == NELEM(pq->heap) ) {
182 return false;
183 }
184
185 pq->heap[pq->sz] = data;
186 fixup(pq->heap, pq->sz);
187 ++pq->sz;
188 return true;
189}
190
191bool
192pq_pop(struct pq *pq, T *data)
193{
194 if ( pq->sz == 0 ) {
195 return false;
196 }
197
198 *data = pq->heap[0];
199 --pq->sz;
200 pq->heap[0] = pq->heap[pq->sz];
201 fixdown(pq->heap, 0, pq->sz);
202 return true;
203}
204
205// -------------------------------------------
206
207void
208print_heap(T heap[], size_t n)
209{
210 if ( n ) {
211 printf("%d", heap[0]);
212 for ( size_t i = 1; i != n; ++i ) {
213 printf(", %d", heap[i]);
214 }
215 putchar('\n');
216 }
217}
218
219void
220test_heapsort(void)
221{
222 static const size_t N = 1000000;
223 T array[N];
224
225 puts("fülle....");
226 srand(time(NULL));
227 for ( size_t idx = 0; idx != NELEM(array); ++idx ) {
228 array[idx] = rand();
229 }
230
231 puts("sortiere....");
232 clock_t start = clock();
233 my_heapsort(array, NELEM(array));
234 clock_t end = clock();
235
236 puts("teste...");
237 for ( size_t idx = 1; idx != NELEM(array); ++idx ) {
238#if defined(MAX_HEAP)
239 if ( array[idx - 1] > array[idx] ) {
240 fprintf(stderr, "Fehler an Pos: %zu\n", idx);
241 exit(EXIT_FAILURE);
242 }
243#else
244 if ( array[idx - 1] < array[idx] ) {
245 fprintf(stderr, "Fehler an Pos: %zu\n", idx);
246 exit(EXIT_FAILURE);
247 }
248#endif
249 }
250 printf("ok! (%.3lf sec)\n", ((double) end - start) / CLOCKS_PER_SEC);
251}
252
253void
254test_pq(void)
255{
256 struct pq pq[1];
257
258 pq_init(pq);
259
260 for ( int i = 0; i != 10; ++i ) {
261 pq_push(pq, rand());
262 }
263
264 T data;
265 while ( pq_pop(pq, &data) ) {
266 printf("%d\n", data);
267 }
268}
269
270int
271main(void)
272{
273 test_heapsort();
274 test_pq();
275#if 1 // Heap-Testprogramm
276 // Beispiel aus "Informatik - Datenstrukturen und Konzepte der Abstraktion"
277 // Kapitel 5.10, Seite 372 ff.
278 T heap[20] = { 18, 18, 16, 9, 7, 1, 9, 3, 7, 5 };
279
280 //heapify(heap, 10);
281 assert(is_heap(heap, 10));
282 print_heap(heap, 10);
283
284 //heap[10] = 13; fixup(heap, 10);
285 swap(heap, 0, 9);
286 fixdown(heap, 0, 9);
287
288 assert(is_heap(heap, 9));
289 print_heap(heap, 9);
290#endif
291}
diff --git a/src/insertsort.c b/src/insertsort.c
new file mode 100644
index 0000000..1a30a1a
--- /dev/null
+++ b/src/insertsort.c
@@ -0,0 +1,38 @@
1#include <stdio.h>
2#include <stdlib.h>
3#include <time.h>
4
5#include "util.h"
6
7typedef int T;
8
9void
10insertsort(T a[], size_t n)
11{
12 for ( size_t i = 1; i < n; ++i ) {
13 size_t j = i;
14 const T value = a[i];
15
16 for ( ; j > 0 && a[j - 1] > value; --j )
17 a[j] = a[j - 1];
18
19 a[j] = value;
20 }
21}
22
23int
24main(void)
25{
26 T a[10];
27
28 srand(time(NULL));
29 for ( size_t i = 0; i != NELEM(a); ++i )
30 a[i] = rand() % 100;
31
32 insertsort(a, NELEM(a));
33
34 for ( size_t i = 0; i != NELEM(a); ++i )
35 printf("%d ", a[i]);
36 putchar('\n');
37 return EXIT_SUCCESS;
38}
diff --git a/src/list-tail-node.c b/src/list-tail-node.c
new file mode 100644
index 0000000..edfcf31
--- /dev/null
+++ b/src/list-tail-node.c
@@ -0,0 +1,197 @@
1/* Standard C */
2#include <stdbool.h>
3#include <stdio.h>
4#include <stdlib.h>
5
6/* Project */
7#include "util.h"
8
9/* --8<-- list_tail_type */
10typedef int T;
11
12struct list_node {
13 struct list_node *next;
14 T data;
15};
16
17struct list {
18 struct list_node *head, *tail;
19};
20/* -->8-- */
21
22/* --8<-- list_tail_init */
23void
24list_init(struct list *list)
25{
26 list->head = NULL;
27}
28/* -->8-- */
29
30/* --8<-- list_tail_create_node */
31static struct list_node *
32create_node(struct list_node *next, T data)
33{
34 struct list_node *node = malloc(sizeof *node);
35
36 if ( node ) {
37 node->next = next;
38 node->data = data;
39 }
40 return node;
41}
42/* -->8-- */
43
44/* --8<-- list_tail_push_back */
45void
46list_push_back(struct list *list, T data)
47{
48 struct list_node *node = create_node(NULL, data);
49
50 if ( node ) {
51 if ( list->head == NULL ) {
52 list->head = node;
53 }
54 else {
55 list->tail->next = node;
56 }
57 list->tail = node;
58 }
59 else {
60 ERROR("out of memory");
61 }
62}
63/* -->8-- */
64
65/* --8<-- list_tail_front */
66void
67list_push_front(struct list *list, T data)
68{
69 struct list_node *node = create_node(list->head, data);
70
71 if ( node ) {
72 if ( list->head == NULL ) { // Einfügen in eine leere Liste?
73 list->tail = node;
74 }
75 list->head = node;
76 }
77 else {
78 ERROR("out of memory");
79 }
80}
81/* -->8-- */
82
83/* --8<-- list_tail_pop_front */
84bool
85list_pop_front(struct list *list, T *data)
86{
87 if ( list->head ) {
88 struct list_node *next = list->head->next;
89
90 if ( data ) {
91 *data = list->head->data;
92 }
93 free(list->head);
94 list->head = next;
95
96 return true;
97 }
98 else {
99 return false;
100 }
101}
102/* -->8-- */
103
104/* --8<-- list_tail_insert_next */
105void
106list_insert_next(struct list *list, struct list_node *node, T data)
107{
108 if ( node == NULL ) { // Am Anfang einfügen
109 list_push_front(list, data);
110 }
111 else {
112 struct list_node *new_node = create_node(node->next, data);
113
114 if ( new_node ) {
115 if ( node->next == NULL ) { // Am Ende einfügen
116 list->tail = new_node;
117 }
118 node->next = new_node;
119 }
120 else {
121 ERROR("out of memory");
122 }
123 }
124}
125/* -->8-- */
126
127/* --8<-- list_tail_delete_next */
128void
129list_delete_next(struct list *list, struct list_node *node, T *data)
130{
131 if ( node == NULL ) { // Am Anfang entfernen
132 list_pop_front(list, data);
133 }
134 else {
135 if ( node->next ) {
136 struct list_node *old_node = node->next;
137 node->next = node->next->next;
138
139 if ( node->next == NULL ) {
140 list->tail = node;
141 }
142
143 if ( data ) {
144 *data = old_node->data;
145 }
146 free(old_node);
147 }
148 }
149}
150/* -->8-- */
151
152/* --8<-- list_tail_empty */
153bool
154list_empty(struct list *list)
155{
156 return list->head == NULL;
157}
158/* -->8-- */
159
160/* --8<-- list_tail_free */
161void
162list_free(struct list *list)
163{
164 struct list_node *item, *next;
165
166 for ( item = list->head; item; item = next ) {
167 next = item->next;
168 free(item);
169 }
170}
171/* -->8-- */
172
173int
174main()
175{
176 struct list list[1];
177
178 list_init(list);
179
180 for ( int i = 0; i != 10; ++i )
181 list_push_front(list, -i);
182
183 for ( int i = 0; i != 10; ++i )
184 list_push_back(list, i);
185
186 while ( !list_empty(list) ) {
187 int i;
188 if ( list_pop_front(list, &i) )
189 printf("%d\n", i);
190 else
191 ERROR("this shouldn't happen!");
192 }
193
194 list_free(list);
195
196 return EXIT_SUCCESS;
197}
diff --git a/src/list.c b/src/list.c
new file mode 100644
index 0000000..d18dae4
--- /dev/null
+++ b/src/list.c
@@ -0,0 +1,264 @@
1/* simple Implementation of single linked lists */
2/* written and placed in the public domain by Thomas Schmucker */
3
4/* Standard C */
5#include <stdio.h>
6#include <stdlib.h>
7#include <time.h>
8
9/* Project */
10#include "util.h"
11
12/* --8<-- list_type */
13typedef int T;
14
15struct list_item {
16 struct list_item *next;
17 T data;
18};
19/* -->8-- */
20
21/* --8<-- list_add */
22struct list_item *
23list_add(struct list_item *next, T data)
24{
25 struct list_item *new_item;
26
27 new_item = malloc(sizeof *new_item);
28 if ( new_item ) {
29 new_item->data = data;
30 new_item->next = next;
31 }
32 else {
33 ERROR("out of memory");
34 }
35
36 return new_item;
37}
38/* -->8-- */
39
40/* --8<-- list_insert_next */
41void
42list_insert_next(struct list_item *list, T data)
43{
44 struct list_item *new_item;
45
46 new_item = list_add(list->next, data);
47 if ( new_item ) {
48 list->next = new_item;
49 }
50 else {
51 ERROR("out of memory");
52 }
53}
54/* -->8-- */
55
56/* --8<-- list_delete */
57struct list_item *
58list_delete(struct list_item *list, T data)
59{
60 struct list_item *prev = NULL;
61
62 for ( struct list_item *p = list; p; p = p->next ) {
63 if ( p->data == data ) {
64 if ( prev == NULL ) { /* first element in list? */
65 list = p->next;
66 }
67 else {
68 prev->next = p->next;
69 }
70
71 free(p);
72
73 return list;
74 }
75 prev = p;
76 }
77#ifdef LIST_REPORT_ERROR
78 ERROR("data not found");
79#endif
80 return list;
81}
82/* -->8-- */
83
84/* --8<-- list_delete_next */
85void
86list_delete_next(struct list_item *list)
87{
88 if ( list->next ) {
89 struct list_item *temp = list->next;
90
91 list->next = list->next->next;
92
93 free(temp);
94 }
95}
96/* -->8-- */
97
98/* --8<-- list_length */
99size_t
100list_length(struct list_item *list)
101{
102 size_t len = 0;
103
104 for ( ; list; list = list->next ) {
105 ++len;
106 }
107
108 return len;
109}
110/* -->8-- */
111
112/* --8<-- list_copy */
113struct list_item *
114list_copy(struct list_item *list)
115{
116 struct list_item *head = NULL, **p = &head;
117
118 for ( ; list; list = list->next ) {
119 *p = malloc(sizeof **p);
120 if ( *p ) {
121 (*p)->data = list->data; // copy elements
122 p = &(*p)->next;
123 }
124 else {
125 ERROR("out of memory");
126 }
127 }
128 *p = NULL;
129 return head;
130}
131/* -->8-- */
132
133/* --8<-- list_reverse */
134struct list_item *
135list_reverse(struct list_item *list)
136{
137 struct list_item *head = NULL, *next;
138
139 for ( ; list; list = next ) {
140 next = list->next;
141 list->next = head;
142 head = list;
143 }
144 return head;
145}
146/* -->8-- */
147
148/* --8<-- list_apply */
149void
150list_apply(struct list_item *list, void (*visit)(T data, void *cl), void *cl)
151{
152 for ( ; list; list = list->next ) {
153 visit(list->data, cl);
154 }
155}
156/* -->8-- */
157
158/* --8<-- list_merge */
159struct list_item *
160list_merge(struct list_item *a, struct list_item *b)
161{
162 struct list_item dummy = { .next = NULL };
163 struct list_item *head = &dummy, *c = head;
164
165 while ( a && b )
166 if ( a->data < b->data ) {
167 c->next = a, c = a, a = a->next;
168 }
169 else {
170 c->next = b, c = b, b = b->next;
171 }
172
173 c->next = a ? a : b;
174
175 return head->next;
176}
177/* -->8-- */
178
179/* --8<-- list_sort */
180struct list_item *
181list_sort(struct list_item *c)
182{
183 if ( c == NULL || c->next == NULL )
184 return c;
185
186 struct list_item *a = c,
187 *b = c->next;
188
189 while ( b && b->next ) {
190 c = c->next, b = b->next->next;
191 }
192
193 b = c->next, c->next = NULL;
194
195 return list_merge(list_sort(a), list_sort(b));
196}
197/* -->8-- */
198
199/* --8<-- list_free */
200void
201list_free(struct list_item *list)
202{
203 struct list_item *next;
204
205 for ( ; list; list = next ) {
206 next = list->next;
207 free(list);
208 }
209}
210/* -->8-- */
211
212/* --8<-- list_apply_sample */
213static void
214print_data(T data, void *cl)
215{
216 fprintf(cl, "%d\n", data);
217}
218/* -->8-- */
219
220int
221main()
222{
223 clock_t start;
224
225 /*
226 struct list_item *mylist = NULL;
227
228 mylist = list_add(mylist, 42);
229 mylist = list_add(mylist, 43);
230 mylist = list_add(mylist, 44);
231
232 mylist = list_delete(mylist, 45);
233
234 list_apply(mylist, print_data, stdout);
235
236 struct list_item *mylist2 = list_reverse(list_copy(mylist));
237
238 list_free(mylist);
239 list_apply(mylist2, print_data);
240 list_free(mylist2);
241 */
242
243 srand(time(NULL));
244
245 static const int COUNT = 10000000;
246
247 struct list_item *x = NULL;
248 for ( int i = 0; i != COUNT; ++i ) {
249 int r = rand();
250 x = list_add(x, r);
251 }
252
253 puts("start");
254 start = clock();
255 x = list_sort(x);
256 printf("Fertig: %.3lf sec\n", (double) (clock() - start) / CLOCKS_PER_SEC);
257
258 //list_apply(x, print_data);
259 printf("Len: %zu\n", list_length(x));
260
261 list_free(x);
262
263 return EXIT_SUCCESS;
264}
diff --git a/src/queue.c b/src/queue.c
new file mode 100644
index 0000000..6a472ee
--- /dev/null
+++ b/src/queue.c
@@ -0,0 +1,115 @@
1/* Standard C */
2#include <stdbool.h>
3#include <stdio.h>
4#include <stdlib.h>
5
6/* Project */
7#include "util.h"
8
9/* --8<-- queue_type */
10typedef int T;
11
12struct queue_item {
13 struct queue_item *next;
14 T data;
15};
16
17struct queue {
18 struct queue_item *head, *tail;
19};
20/* -->8-- */
21
22/* --8<-- queue_init */
23void
24queue_init(struct queue *queue)
25{
26 queue->head = NULL;
27}
28/* -->8-- */
29
30/* --8<-- queue_put */
31void
32queue_put(struct queue *queue, T data)
33{
34 struct queue_item *new_item;
35
36 if ( (new_item = malloc(sizeof *new_item)) != NULL ) {
37 struct queue_item *tmp = queue->tail;
38 new_item->data = data;
39 new_item->next = NULL;
40 queue->tail = new_item;
41 if ( queue->head == NULL )
42 queue->head = queue->tail;
43 else
44 tmp->next = queue->tail;
45 }
46 else {
47 ERROR("out of memory");
48 }
49}
50/* -->8-- */
51
52/* --8<-- queue_get */
53bool
54queue_get(struct queue *queue, T *data)
55{
56 if ( queue->head ) {
57 struct queue_item *next = queue->head->next;
58
59 if ( data ) {
60 *data = queue->head->data;
61 }
62 free(queue->head);
63 queue->head = next;
64
65 return true;
66 }
67 else
68 return false;
69}
70/* -->8-- */
71
72/* --8<-- queue_empty */
73bool
74queue_empty(struct queue *queue)
75{
76 return queue->head == NULL;
77}
78/* -->8-- */
79
80/* --8<-- queue_free */
81void
82queue_free(struct queue *queue)
83{
84 struct queue_item *item, *next;
85
86 for ( item = queue->head; item; item = next ) {
87 next = item->next;
88 free(item);
89 }
90}
91/* -->8-- */
92
93int
94main()
95{
96 struct queue queue[1];
97
98 queue_init(queue);
99
100 for ( int i = 0; i != 10; ++i ) {
101 queue_put(queue, i);
102 }
103
104 while ( !queue_empty(queue) ) {
105 int i;
106 if ( queue_get(queue, &i) )
107 printf("%d\n", i);
108 else
109 ERROR("this shouldn't happen!");
110 }
111
112 queue_free(queue);
113
114 return EXIT_SUCCESS;
115}
diff --git a/src/quicksort.c b/src/quicksort.c
new file mode 100644
index 0000000..4657dcd
--- /dev/null
+++ b/src/quicksort.c
@@ -0,0 +1,684 @@
1#include <assert.h>
2#include <stdio.h>
3#include <stdlib.h>
4#include <time.h>
5
6#include "util.h"
7
8static int
9bigrand(void)
10{
11 int x = (rand() << 24) | (rand() << 16) | (rand() << 8) | rand();
12 if ( x < 0 )
13 return -x;
14 return x;
15}
16
17static int
18randint(int l, int u)
19{
20 return l + bigrand() % (u - l + 1);
21}
22
23typedef int T;
24
25static const int CUTOFF = 128;
26
27static inline void
28swap(T a[], int i, int j)
29{
30 T t = a[i];
31 a[i] = a[j];
32 a[j] = t;
33}
34
35static void
36insertsort(T a[], int n)
37{
38 int i, j;
39 for ( i = 1; i < n; ++i ) {
40 T t = a[i];
41 for ( j = i; j > 0 && a[j - 1] > t; --j )
42 a[j] = a[j - 1];
43 a[j] = t;
44 }
45}
46
47static void
48quicksort(T a[], int n)
49{
50 int i, last;
51
52 if ( n <= CUTOFF )
53 return;
54
55 swap(a, 0, bigrand() % n);
56
57 last = 0;
58 for ( i = 1; i < n; ++i )
59 if ( a[i] < a[0] )
60 swap(a, ++last, i);
61
62 swap(a, 0, last);
63
64 quicksort(a, last);
65 quicksort(a + last + 1, n - last - 1);
66}
67
68void
69my_quicksort(T a[], int n)
70{
71 quicksort(a, n);
72 insertsort(a, n);
73}
74
75static int
76cmp(const void *a, const void *b)
77{
78 const int *pa = (const T *) a;
79 const int *pb = (const T *) b;
80
81 if ( *pa < *pb )
82 return -1;
83 if ( *pa > *pb )
84 return 1;
85 return 0;
86}
87
88void
89c_quicksort(T a[], int n)
90{
91 assert(n >= 0);
92 qsort(a, (size_t) n, sizeof(T), cmp);
93}
94
95/* This function takes last element as pivot, places
96 the pivot element at its correct position in sorted
97 array, and places all smaller (smaller than pivot)
98 to left of pivot and all greater elements to right
99 of pivot */
100int
101partition(int arr[], int low, int high)
102{
103 int pivot = arr[high]; // pivot
104 int i = (low - 1); // Index of smaller element
105
106 for ( int j = low; j <= high - 1; j++ ) {
107 // If current element is smaller than or
108 // equal to pivot
109 if ( arr[j] <= pivot ) {
110 i++; // increment index of smaller element
111 swap(arr, i, j);
112 }
113 }
114 swap(arr, i + 1, high);
115 return (i + 1);
116}
117
118/* The main function that implements QuickSort
119 arr[] --> Array to be sorted,
120 low --> Starting index,
121 high --> Ending index */
122void
123quickSort(int arr[], int low, int high)
124{
125 while ( low < high ) {
126 /* pi is partitioning index, arr[p] is now
127 at right place */
128 int pi = partition(arr, low, high);
129
130 if ( pi - low < high - pi ) {
131 quickSort(arr, low, pi - 1);
132 low = pi + 1;
133 }
134 else {
135 quickSort(arr, pi + 1, high);
136 high = pi - 1;
137 }
138 }
139}
140
141void
142g4g_quicksort(T a[], int n)
143{
144 quickSort(a, 0, n - 1);
145}
146
147static void
148three_way_quicksort(int a[], int l, int r)
149{
150 int k;
151 T v = a[r];
152
153 if ( r <= l )
154 return;
155
156 int i = l - 1, j = r, p = l - 1, q = r;
157
158 for ( ;; ) {
159 while ( a[++i] < v )
160 ;
161 while ( v < a[--j] )
162 if ( j == l )
163 break;
164 if ( i >= j )
165 break;
166
167 swap(a, i, j);
168
169 if ( a[i] == v )
170 swap(a, ++p, i);
171 if ( v == a[j] )
172 swap(a, --q, j);
173 }
174 swap(a, i, r);
175 j = i - 1;
176 i = i + 1;
177
178 for ( k = l; k <= p; ++k, --j )
179 swap(a, k, j);
180 for ( k = r - 1; k >= q; --k, ++i )
181 swap(a, k, i);
182
183 three_way_quicksort(a, l, j);
184 three_way_quicksort(a, i, r);
185}
186
187void
188sed_quicksort(int a[], int n)
189{
190 three_way_quicksort(a, 0, n - 1);
191}
192
193/* ====================== HEAPSORT ======================= */
194
195#define LEFT(idx) (idx * 2 + 1)
196#define RIGHT(idx) (idx * 2 + 2)
197#define PARENT(idx) ((idx - 1) / 2)
198
199static void
200fixdown(T heap[], int i, int n)
201{
202 for ( ;; ) {
203 const int l = LEFT(i);
204 const int r = RIGHT(i);
205 int m = i;
206
207 if ( l < n && heap[m] < heap[l] )
208 m = l;
209
210 if ( r < n && heap[m] < heap[r] )
211 m = r;
212
213 if ( m == i )
214 break;
215
216 swap(heap, m, i);
217
218 i = m;
219 }
220}
221
222static void
223heapify(T heap[], int n)
224{
225 for ( int i = n / 2 - 1; i >= 0; --i )
226 fixdown(heap, i, n);
227}
228
229void
230my_heapsort(T a[], int n)
231{
232 heapify(a, n);
233
234 for ( int i = n - 1; i >= 0; --i ) {
235 swap(a, 0, i);
236 fixdown(a, 0, i);
237 }
238}
239
240void
241heapsort_bu(T *data, int n) // zu sortierendes Feld und seine Länge
242{
243 T val;
244 int parent, child;
245 int root = n >> 1; // erstes Blatt im Baum
246 int count = 0; // Zähler für Anzahl der Vergleiche
247
248 for ( ;; ) {
249 if ( root ) { // Teil 1: Konstruktion des Heaps
250 parent = --root;
251 val = data[root]; // zu versickernder Wert
252 }
253 else if ( --n ) { // Teil 2: eigentliche Sortierung
254 val = data[n]; // zu versickernder Wert vom Heap-Ende
255 data[n] = data[0]; // Spitze des Heaps hinter den Heap in
256 parent = 0; // den sortierten Bereich verschieben
257 }
258 else // Heap ist leer; Sortierung beendet
259 break;
260
261 while ( (child = (parent + 1) << 1) < n ) // zweites (!) Kind;
262 { // Abbruch am Ende des Heaps
263 if ( ++count, data[child - 1] > data[child] ) // größeres Kind wählen
264 --child;
265
266 data[parent] = data[child]; // größeres Kind nach oben rücken
267 parent = child; // in der Ebene darunter weitersuchen
268 }
269
270 if ( child == n ) // ein einzelnes Kind am Heap-Ende
271 { // ist übersprungen worden
272 if ( ++count, data[--child] >= val ) { // größer als der zu versick-
273 data[parent] = data[child]; // ernde Wert, also noch nach oben
274 data[child] = val; // versickerten Wert eintragen
275 continue;
276 }
277
278 child = parent; // 1 Ebene nach oben zurück
279 }
280 else {
281 if ( ++count, data[parent] >= val ) { // das Blatt ist größer als der
282 data[parent] = val; // zu versickernde Wert, der damit
283 continue; // direkt eingetragen werden kann
284 }
285
286 child = (parent - 1) >> 1; // 2 Ebenen nach oben zurück
287 }
288
289 while ( child != root ) // maximal zum Ausgangspunkt zurück
290 {
291 parent = (child - 1) >> 1; // den Vergleichswert haben wir bereits
292 // nach oben verschoben
293 if ( ++count, data[parent] >= val ) // größer als der zu versickernde
294 break; // Wert, also Position gefunden
295
296 data[child] = data[parent]; // Rückverschiebung nötig
297 child = parent; // 1 Ebene nach oben zurück
298 }
299
300 data[child] = val; // versickerten Wert eintragen
301 }
302}
303
304/*----------------------------------------------------------------------*/
305/* BOTTOM-UP HEAPSORT */
306/* Written by J. Teuhola <teuhola@cs.utu.fi>; the original idea is */
307/* probably due to R.W. Floyd. Thereafter it has been used by many */
308/* authors, among others S. Carlsson and I. Wegener. Building the heap */
309/* bottom-up is also due to R. W. Floyd: Treesort 3 (Algorithm 245), */
310/* Communications of the ACM 7, p. 701, 1964. */
311/*----------------------------------------------------------------------*/
312
313#define element float
314
315/*-----------------------------------------------------------------------*/
316/* The sift-up procedure sinks a hole from v[i] to leaf and then sifts */
317/* the original v[i] element from the leaf level up. This is the main */
318/* idea of bottom-up heapsort. */
319/*-----------------------------------------------------------------------*/
320static void
321siftup(T v[], int i, int n)
322{
323 int j, start;
324 T x;
325
326 start = i;
327 x = v[i];
328 j = i << 1;
329 while ( j <= n ) {
330 if ( j < n )
331 if ( v[j] < v[j + 1] )
332 j++;
333 v[i] = v[j];
334 i = j;
335 j = i << 1;
336 }
337 j = i >> 1;
338 while ( j >= start ) {
339 if ( v[j] < x ) {
340 v[i] = v[j];
341 i = j;
342 j = i >> 1;
343 }
344 else
345 break;
346 }
347 v[i] = x;
348} /* End of siftup */
349
350/*----------------------------------------------------------------------*/
351/* The heapsort procedure; the original array is r[0..n-1], but here */
352/* it is shifted to vector v[1..n], for convenience. */
353/*----------------------------------------------------------------------*/
354void
355bottom_up_heapsort(T r[], int n)
356{
357 int k;
358 T x;
359 T * v;
360
361 v = r - 1; /* The address shift */
362
363 /* Build the heap bottom-up, using siftup. */
364 for ( k = n >> 1; k > 1; k-- )
365 siftup(v, k, n);
366
367 /* The main loop of sorting follows. The root is swapped with the last */
368 /* leaf after each sift-up. */
369 for ( k = n; k > 1; k-- ) {
370 siftup(v, 1, k);
371 x = v[k];
372 v[k] = v[1];
373 v[1] = x;
374 }
375} /* End of bottom_up_heapsort */
376
377/* ====================== HEAPSORT ======================= */
378
379/* ====================== INTROSORT ======================= */
380
381static void
382introsort(T a[], int n, int h)
383{
384 int i, last;
385
386 if ( n <= CUTOFF )
387 return;
388
389 if ( --h == 1 ) {
390 my_heapsort(a, n);
391 return;
392 }
393
394 swap(a, 0, bigrand() % n);
395
396 last = 0;
397 for ( i = 1; i < n; ++i )
398 if ( a[i] < a[0] )
399 swap(a, ++last, i);
400
401 swap(a, 0, last);
402
403 introsort(a, last, h);
404 introsort(a + last + 1, n - last - 1, h);
405}
406
407void
408my_introsort(T a[], int n)
409{
410 int h = 1;
411
412 for ( int nn = 1; nn < n; nn <<= 1 )
413 ++h;
414
415 introsort(a, n, h);
416 insertsort(a, n);
417}
418
419static void
420pp_quicksort_impl(T a[], int l, int u)
421{
422 if ( u - l < CUTOFF )
423 return;
424
425 swap(a, l, randint(l, u));
426
427 T t = a[l];
428 int i = l;
429 int j = u + 1;
430 for ( ;; ) {
431 do
432 i++;
433 while ( /*i <= u &&*/ a[i] < t );
434 do
435 j--;
436 while ( a[j] > t );
437 if ( i > j )
438 break;
439 swap(a, i, j);
440 }
441 swap(a, l, j);
442 pp_quicksort_impl(a, l, j - 1);
443 pp_quicksort_impl(a, j + 1, u);
444}
445
446void
447pp_quicksort(T a[], int n)
448{
449 pp_quicksort_impl(a, 0, n - 1);
450 insertsort(a, n);
451}
452
453static void
454pp_quicksort_impl_it(T a[], int l, int u, int h)
455{
456 if ( --h == 1 ) {
457 my_heapsort(a + l, u - l + 1);
458 return;
459 }
460
461 while ( u - l >= CUTOFF ) {
462 swap(a, l, randint(l, u));
463
464 T t = a[l];
465 int i = l;
466 int j = u + 1;
467
468 for ( ;; ) {
469 do
470 i++;
471 while ( /*i <= u && */ a[i] < t );
472 do
473 j--;
474 while ( a[j] > t );
475 if ( i > j )
476 break;
477 swap(a, i, j);
478 }
479 swap(a, l, j);
480
481 if ( j - l < u - j ) {
482 pp_quicksort_impl_it(a, l, j - 1, h);
483 l = j + 1;
484 }
485 else {
486 pp_quicksort_impl_it(a, j + 1, u, h);
487 u = j - 1;
488 }
489 }
490}
491
492void
493pp_quicksort_it(T a[], int n)
494{
495 int h = 1;
496
497 for ( int nn = 1; nn < n; nn <<= 1 )
498 ++h;
499
500 pp_quicksort_impl_it(a, 0, n - 1, h);
501 insertsort(a, n);
502}
503
504int
505binary_search(T x, T v[], int n)
506{
507 int low, high;
508
509 low = 0;
510 high = n - 1;
511 while ( low <= high ) {
512 int mid = low + ((high - low) / 2);
513 if ( x > v[mid] )
514 low = mid + 1;
515 else if ( x < v[mid] )
516 high = mid - 1;
517 else
518 return mid;
519 }
520 return -1;
521}
522
523int
524lower_bound(T x, T v[], int n)
525{
526 int low, high;
527
528 low = 0;
529 high = n;
530 while ( low < high ) {
531 int mid = low + ((high - low) / 2);
532
533 if ( x > v[mid] )
534 low = mid + 1;
535 else
536 high = mid;
537 }
538 return x == v[low] ? low : -1;
539}
540
541int
542upper_bound(T x, T v[], int n)
543{
544 int low, high;
545
546 low = 0;
547 high = n;
548 while ( low < high ) {
549 int mid = low + ((high - low) / 2);
550
551 if ( x >= v[mid] )
552 low = mid + 1;
553 else
554 high = mid;
555 }
556 return (low > 0 && x == v[low - 1]) ? low - 1 : -1;
557}
558
559/* TESTTREIBER */
560
561void
562gen_testset_random(T a[], int n)
563{
564 for ( int i = 0; i < n; ++i )
565 a[i] = bigrand();
566}
567
568void
569gen_testset_random2(T a[], int n)
570{
571 for ( int i = 0; i < n; ++i )
572 a[i] = bigrand() % 100;
573}
574
575void
576gen_testset_asc(T a[], int n)
577{
578 for ( int i = 0; i < n; ++i )
579 a[i] = i;
580}
581
582void
583gen_testset_desc(T a[], int n)
584{
585 for ( int i = n; i >= 0; --i )
586 a[i] = i;
587}
588
589void
590gen_testset_unique(T a[], int n)
591{
592 for ( int i = 0; i < n; ++i )
593 a[i] = 1;
594}
595
596void
597test_sorting(T a[], int n)
598{
599 for ( int i = 1; i < n; ++i )
600 if ( a[i - 1] > a[i] ) {
601 puts("Fehler!");
602 exit(EXIT_SUCCESS);
603 }
604}
605
606void
607do_one_test(int n, void (*do_sort)(T a[], int n), void (*gen_testset)(T a[], int n))
608{
609 T * a;
610 clock_t start, ende;
611
612 a = malloc(sizeof(T) * (size_t) n);
613
614 (*gen_testset)(a, n);
615
616 start = clock();
617 (*do_sort)(a, n);
618 ende = clock();
619
620 test_sorting(a, n);
621
622 free(a);
623
624 printf("%10.3lf sec", ((double) ende - start) / CLOCKS_PER_SEC);
625 fflush(stdout);
626}
627
628void
629do_all_tests(const char *msg, int n, void (*do_sort)(T a[], int n))
630{
631 printf("%-15.15s n=%-10d: ", msg, n);
632 do_one_test(n, do_sort, gen_testset_random);
633 do_one_test(n, do_sort, gen_testset_random2);
634 do_one_test(n, do_sort, gen_testset_asc);
635 do_one_test(n, do_sort, gen_testset_desc);
636 do_one_test(n, do_sort, gen_testset_unique);
637 putchar('\n');
638}
639
640/* ENDE TESTTREIBER */
641
642int
643main(void)
644{
645 const int n = 20000000;
646
647 srand(time(0));
648 do_all_tests("my_heapsort", n, my_heapsort);
649 do_all_tests("heapsort_bu", n, heapsort_bu);
650 do_all_tests("bottom_up_heapsort", n, bottom_up_heapsort);
651 do_all_tests("c_quicksort", n, c_quicksort);
652 //do_all_tests("g4g_quicksort", n, g4g_quicksort);
653 //do_all_tests("sed_quicksort", n, sed_quicksort);
654 do_all_tests("my_introsort", n, my_introsort);
655 //do_all_tests("my_quicksort", n, my_quicksort);
656 do_all_tests("pp_quicksort", n, pp_quicksort);
657 do_all_tests("pp_quicksort_it", n, pp_quicksort_it);
658
659 return 0;
660}
661
662#if 0
663int _main(void)
664{
665 T array[20];
666
667 for ( int i = 0; i != NELEM(array); ++i )
668 array[i] = rand() % 10;
669
670 sort(array, NELEM(array));
671 print(array, NELEM(array));
672
673 int value;
674 while ( scanf("%d", &value) == 1 && value != -1 ) {
675 int bs = binary_search(value, array, NELEM(array));
676 int lb = lower_bound(value, array, NELEM(array));
677 int ub = upper_bound(value, array, NELEM(array));
678
679 printf("bs: %d - lb: %d - ub: %d\n", bs, lb, ub);
680 }
681
682 return EXIT_SUCCESS;
683}
684#endif
diff --git a/src/random.h b/src/random.h
new file mode 100644
index 0000000..9094d5b
--- /dev/null
+++ b/src/random.h
@@ -0,0 +1,47 @@
1#ifndef ITS1_RANDOM_H_INCLUDED
2#define ITS1_RANDOM_H_INCLUDED
3
4#ifdef __cplusplus
5extern "C" {
6#endif
7
8struct random_ctx {
9 unsigned char (*get_byte)(struct random_ctx *ctx);
10};
11
12static unsigned char
13random_get_byte(struct random_ctx *ctx)
14{
15 return ctx->get_byte(ctx);
16}
17
18static unsigned short
19random_get_word(struct random_ctx *ctx)
20{
21 return (ctx->get_byte(ctx) << 8)
22 | ctx->get_byte(ctx)
23 ;
24}
25
26static unsigned long
27random_get_dword(struct random_ctx *ctx)
28{
29 return (ctx->get_byte(ctx) << 24)
30 | (ctx->get_byte(ctx) << 16)
31 | (ctx->get_byte(ctx) << 8)
32 | ctx->get_byte(ctx)
33 ;
34}
35
36static unsigned long
37random_get_dword_range(struct random_ctx *ctx, unsigned long l, unsigned long u)
38{
39 return l + random_get_dword(ctx) % (u - l + 1);
40}
41
42#ifdef __cplusplus
43}
44#endif
45
46#endif /* ITS1_RANDOM_H_INCLUDED */
47
diff --git a/src/rb.c b/src/rb.c
new file mode 100644
index 0000000..7c2d2c1
--- /dev/null
+++ b/src/rb.c
@@ -0,0 +1,614 @@
1/*
2 Implementierung übernommen von: https://web.archive.org/web/20140328232325/http://en.literateprograms.org/Red-black_tree_(C)
3 */
4
5#include <stdio.h>
6#include <stdlib.h>
7#include <time.h>
8
9#include "util.h"
10
11/* The authors of this work have released all rights to it and placed it
12in the public domain under the Creative Commons CC0 1.0 waiver
13(http://creativecommons.org/publicdomain/zero/1.0/).
14
15THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
16EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
17MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
18IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
19CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
20TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
21SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
22
23Retrieved from: http://en.literateprograms.org/Red-black_tree_(C)?oldid=19567
24*/
25
26enum rbtree_node_color { RED,
27 BLACK };
28
29typedef struct rbtree_node_t {
30 void * key;
31 void * value;
32 struct rbtree_node_t * left;
33 struct rbtree_node_t * right;
34 struct rbtree_node_t * parent;
35 enum rbtree_node_color color;
36} * rbtree_node;
37
38typedef struct rbtree_t {
39 rbtree_node root;
40} * rbtree;
41
42typedef int (*compare_func)(void *left, void *right);
43
44rbtree rbtree_create();
45void * rbtree_lookup(rbtree t, void *key, compare_func compare);
46void rbtree_insert(rbtree t, void *key, void *value, compare_func compare);
47void rbtree_delete(rbtree t, void *key, compare_func compare);
48
49#include <assert.h>
50#include <stdlib.h>
51
52typedef rbtree_node node;
53typedef enum rbtree_node_color color;
54
55static node grandparent(node n);
56static node sibling(node n);
57static node uncle(node n);
58static void verify_properties(rbtree t);
59static void verify_property_1(node root);
60static void verify_property_2(node root);
61static color node_color(node n);
62static void verify_property_4(node root);
63static void verify_property_5(node root);
64static void verify_property_5_helper(node n, int black_count, int *black_count_path);
65
66static node new_node(void *key, void *value, color node_color, node left, node right);
67static node lookup_node(rbtree t, void *key, compare_func compare);
68static void rotate_left(rbtree t, node n);
69static void rotate_right(rbtree t, node n);
70
71static void replace_node(rbtree t, node oldn, node newn);
72static void insert_case1(rbtree t, node n);
73static void insert_case2(rbtree t, node n);
74static void insert_case3(rbtree t, node n);
75static void insert_case4(rbtree t, node n);
76static void insert_case5(rbtree t, node n);
77static node maximum_node(node root);
78static void delete_case1(rbtree t, node n);
79static void delete_case2(rbtree t, node n);
80static void delete_case3(rbtree t, node n);
81static void delete_case4(rbtree t, node n);
82static void delete_case5(rbtree t, node n);
83static void delete_case6(rbtree t, node n);
84
85node
86grandparent(node n)
87{
88 assert(n != NULL);
89 assert(n->parent != NULL); /* Not the root node */
90 assert(n->parent->parent != NULL); /* Not child of root */
91 return n->parent->parent;
92}
93
94node
95sibling(node n)
96{
97 assert(n != NULL);
98 assert(n->parent != NULL); /* Root node has no sibling */
99 if ( n == n->parent->left )
100 return n->parent->right;
101 else
102 return n->parent->left;
103}
104
105node
106uncle(node n)
107{
108 assert(n != NULL);
109 assert(n->parent != NULL); /* Root node has no uncle */
110 assert(n->parent->parent != NULL); /* Children of root have no uncle */
111 return sibling(n->parent);
112}
113
114void
115verify_properties(rbtree t)
116{
117 (void) t;
118#ifdef VERIFY_RBTREE
119 verify_property_1(t->root);
120 verify_property_2(t->root);
121 /* Property 3 is implicit */
122 verify_property_4(t->root);
123 verify_property_5(t->root);
124#endif
125}
126
127void
128verify_property_1(node n)
129{
130 assert(node_color(n) == RED || node_color(n) == BLACK);
131 if ( n == NULL )
132 return;
133 verify_property_1(n->left);
134 verify_property_1(n->right);
135}
136
137void
138verify_property_2(node root)
139{
140 assert(node_color(root) == BLACK);
141}
142
143color
144node_color(node n)
145{
146 return n == NULL ? BLACK : n->color;
147}
148
149void
150verify_property_4(node n)
151{
152 if ( node_color(n) == RED ) {
153 assert(node_color(n->left) == BLACK);
154 assert(node_color(n->right) == BLACK);
155 assert(node_color(n->parent) == BLACK);
156 }
157 if ( n == NULL )
158 return;
159 verify_property_4(n->left);
160 verify_property_4(n->right);
161}
162
163void
164verify_property_5(node root)
165{
166 int black_count_path = -1;
167 verify_property_5_helper(root, 0, &black_count_path);
168}
169
170void
171verify_property_5_helper(node n, int black_count, int *path_black_count)
172{
173 if ( node_color(n) == BLACK ) {
174 black_count++;
175 }
176 if ( n == NULL ) {
177 if ( *path_black_count == -1 ) {
178 *path_black_count = black_count;
179 }
180 else {
181 assert(black_count == *path_black_count);
182 }
183 return;
184 }
185 verify_property_5_helper(n->left, black_count, path_black_count);
186 verify_property_5_helper(n->right, black_count, path_black_count);
187}
188
189rbtree
190rbtree_create()
191{
192 rbtree t = malloc(sizeof *t);
193 t->root = NULL;
194 verify_properties(t);
195 return t;
196}
197
198node
199new_node(void *key, void *value, color node_color, node left, node right)
200{
201 node result = malloc(sizeof *result);
202 result->key = key;
203 result->value = value;
204 result->color = node_color;
205 result->left = left;
206 result->right = right;
207 if ( left != NULL )
208 left->parent = result;
209 if ( right != NULL )
210 right->parent = result;
211 result->parent = NULL;
212 return result;
213}
214
215node
216lookup_node(rbtree t, void *key, compare_func compare)
217{
218 node n = t->root;
219 while ( n != NULL ) {
220 int comp_result = compare(key, n->key);
221 if ( comp_result == 0 ) {
222 return n;
223 }
224 else if ( comp_result < 0 ) {
225 n = n->left;
226 }
227 else {
228 assert(comp_result > 0);
229 n = n->right;
230 }
231 }
232 return n;
233}
234
235void *
236rbtree_lookup(rbtree t, void *key, compare_func compare)
237{
238 node n = lookup_node(t, key, compare);
239 return n == NULL ? NULL : n->value;
240}
241
242void
243rotate_left(rbtree t, node n)
244{
245 node r = n->right;
246 replace_node(t, n, r);
247 n->right = r->left;
248 if ( r->left != NULL ) {
249 r->left->parent = n;
250 }
251 r->left = n;
252 n->parent = r;
253}
254
255void
256rotate_right(rbtree t, node n)
257{
258 node L = n->left;
259 replace_node(t, n, L);
260 n->left = L->right;
261 if ( L->right != NULL ) {
262 L->right->parent = n;
263 }
264 L->right = n;
265 n->parent = L;
266}
267
268void
269replace_node(rbtree t, node oldn, node newn)
270{
271 if ( oldn->parent == NULL ) {
272 t->root = newn;
273 }
274 else {
275 if ( oldn == oldn->parent->left )
276 oldn->parent->left = newn;
277 else
278 oldn->parent->right = newn;
279 }
280 if ( newn != NULL ) {
281 newn->parent = oldn->parent;
282 }
283}
284
285void
286rbtree_insert(rbtree t, void *key, void *value, compare_func compare)
287{
288 node inserted_node = new_node(key, value, RED, NULL, NULL);
289 if ( t->root == NULL ) {
290 t->root = inserted_node;
291 }
292 else {
293 node n = t->root;
294 while ( 1 ) {
295 int comp_result = compare(key, n->key);
296 if ( comp_result == 0 ) {
297 n->value = value;
298 return;
299 }
300 else if ( comp_result < 0 ) {
301 if ( n->left == NULL ) {
302 n->left = inserted_node;
303 break;
304 }
305 else {
306 n = n->left;
307 }
308 }
309 else {
310 assert(comp_result > 0);
311 if ( n->right == NULL ) {
312 n->right = inserted_node;
313 break;
314 }
315 else {
316 n = n->right;
317 }
318 }
319 }
320 inserted_node->parent = n;
321 }
322 insert_case1(t, inserted_node);
323 verify_properties(t);
324}
325
326void
327insert_case1(rbtree t, node n)
328{
329 if ( n->parent == NULL )
330 n->color = BLACK;
331 else
332 insert_case2(t, n);
333}
334
335void
336insert_case2(rbtree t, node n)
337{
338 if ( node_color(n->parent) == BLACK )
339 return; /* Tree is still valid */
340 else
341 insert_case3(t, n);
342}
343
344void
345insert_case3(rbtree t, node n)
346{
347 if ( node_color(uncle(n)) == RED ) {
348 n->parent->color = BLACK;
349 uncle(n)->color = BLACK;
350 grandparent(n)->color = RED;
351 insert_case1(t, grandparent(n));
352 }
353 else {
354 insert_case4(t, n);
355 }
356}
357
358void
359insert_case4(rbtree t, node n)
360{
361 if ( n == n->parent->right && n->parent == grandparent(n)->left ) {
362 rotate_left(t, n->parent);
363 n = n->left;
364 }
365 else if ( n == n->parent->left && n->parent == grandparent(n)->right ) {
366 rotate_right(t, n->parent);
367 n = n->right;
368 }
369 insert_case5(t, n);
370}
371
372void
373insert_case5(rbtree t, node n)
374{
375 n->parent->color = BLACK;
376 grandparent(n)->color = RED;
377 if ( n == n->parent->left && n->parent == grandparent(n)->left ) {
378 rotate_right(t, grandparent(n));
379 }
380 else {
381 assert(n == n->parent->right && n->parent == grandparent(n)->right);
382 rotate_left(t, grandparent(n));
383 }
384}
385
386void
387rbtree_delete(rbtree t, void *key, compare_func compare)
388{
389 node child;
390 node n = lookup_node(t, key, compare);
391 if ( n == NULL )
392 return; /* Key not found, do nothing */
393 if ( n->left != NULL && n->right != NULL ) {
394 /* Copy key/value from predecessor and then delete it instead */
395 node pred = maximum_node(n->left);
396 n->key = pred->key;
397 n->value = pred->value;
398 n = pred;
399 }
400
401 assert(n->left == NULL || n->right == NULL);
402 child = n->right == NULL ? n->left : n->right;
403 if ( node_color(n) == BLACK ) {
404 n->color = node_color(child);
405 delete_case1(t, n);
406 }
407 replace_node(t, n, child);
408 if ( n->parent == NULL && child != NULL ) // root should be black
409 child->color = BLACK;
410 free(n);
411
412 verify_properties(t);
413}
414
415static node
416maximum_node(node n)
417{
418 assert(n != NULL);
419 while ( n->right != NULL ) {
420 n = n->right;
421 }
422 return n;
423}
424
425void
426delete_case1(rbtree t, node n)
427{
428 if ( n->parent == NULL )
429 return;
430 else
431 delete_case2(t, n);
432}
433
434void
435delete_case2(rbtree t, node n)
436{
437 if ( node_color(sibling(n)) == RED ) {
438 n->parent->color = RED;
439 sibling(n)->color = BLACK;
440 if ( n == n->parent->left )
441 rotate_left(t, n->parent);
442 else
443 rotate_right(t, n->parent);
444 }
445 delete_case3(t, n);
446}
447
448void
449delete_case3(rbtree t, node n)
450{
451 if ( node_color(n->parent) == BLACK &&
452 node_color(sibling(n)) == BLACK &&
453 node_color(sibling(n)->left) == BLACK &&
454 node_color(sibling(n)->right) == BLACK ) {
455 sibling(n)->color = RED;
456 delete_case1(t, n->parent);
457 }
458 else
459 delete_case4(t, n);
460}
461
462void
463delete_case4(rbtree t, node n)
464{
465 if ( node_color(n->parent) == RED &&
466 node_color(sibling(n)) == BLACK &&
467 node_color(sibling(n)->left) == BLACK &&
468 node_color(sibling(n)->right) == BLACK ) {
469 sibling(n)->color = RED;
470 n->parent->color = BLACK;
471 }
472 else
473 delete_case5(t, n);
474}
475
476void
477delete_case5(rbtree t, node n)
478{
479 if ( n == n->parent->left &&
480 node_color(sibling(n)) == BLACK &&
481 node_color(sibling(n)->left) == RED &&
482 node_color(sibling(n)->right) == BLACK ) {
483 sibling(n)->color = RED;
484 sibling(n)->left->color = BLACK;
485 rotate_right(t, sibling(n));
486 }
487 else if ( n == n->parent->right &&
488 node_color(sibling(n)) == BLACK &&
489 node_color(sibling(n)->right) == RED &&
490 node_color(sibling(n)->left) == BLACK ) {
491 sibling(n)->color = RED;
492 sibling(n)->right->color = BLACK;
493 rotate_left(t, sibling(n));
494 }
495 delete_case6(t, n);
496}
497
498void
499delete_case6(rbtree t, node n)
500{
501 sibling(n)->color = node_color(n->parent);
502 n->parent->color = BLACK;
503 if ( n == n->parent->left ) {
504 assert(node_color(sibling(n)->right) == RED);
505 sibling(n)->right->color = BLACK;
506 rotate_left(t, n->parent);
507 }
508 else {
509 assert(node_color(sibling(n)->left) == RED);
510 sibling(n)->left->color = BLACK;
511 rotate_right(t, n->parent);
512 }
513}
514
515/* The authors of this work have released all rights to it and placed it
516in the public domain under the Creative Commons CC0 1.0 waiver
517(http://creativecommons.org/publicdomain/zero/1.0/).
518
519THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
520EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
521MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
522IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
523CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
524TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
525SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
526
527Retrieved from: http://en.literateprograms.org/Red-black_tree_(C)?oldid=19567
528*/
529
530#include <assert.h>
531#include <stdio.h>
532#include <stdlib.h> /* rand() */
533
534static int compare_int(void *left, void *right);
535static void print_tree(rbtree t);
536static void print_tree_helper(rbtree_node n, int indent);
537
538int
539compare_int(void *leftp, void *rightp)
540{
541 int left = (int) leftp;
542 int right = (int) rightp;
543 if ( left < right )
544 return -1;
545 else if ( left > right )
546 return 1;
547 else {
548 assert(left == right);
549 return 0;
550 }
551}
552
553#define INDENT_STEP 4
554
555void print_tree_helper(rbtree_node n, int indent);
556
557void
558print_tree(rbtree t)
559{
560 print_tree_helper(t->root, 0);
561 puts("");
562}
563
564void
565print_tree_helper(rbtree_node n, int indent)
566{
567 int i;
568 if ( n == NULL ) {
569 fputs("<empty tree>", stdout);
570 return;
571 }
572 if ( n->right != NULL ) {
573 print_tree_helper(n->right, indent + INDENT_STEP);
574 }
575 for ( i = 0; i < indent; i++ )
576 fputs(" ", stdout);
577 if ( n->color == BLACK )
578 printf("%d\n", (int) n->key);
579 else
580 printf("<%d>\n", (int) n->key);
581 if ( n->left != NULL ) {
582 print_tree_helper(n->left, indent + INDENT_STEP);
583 }
584}
585
586int
587main()
588{
589 int i;
590 rbtree t = rbtree_create();
591
592 for ( i = 0; i < 50; i++ ) {
593 long x = rand() % 10000;
594 long y = rand() % 10000;
595#ifdef TRACE
596 print_tree(t);
597 printf("Inserting %ld -> %ld\n\n", x, y);
598#endif
599 rbtree_insert(t, (void *) x, (void *) y, compare_int);
600 assert(rbtree_lookup(t, (void *) x, compare_int) == (void *) y);
601 }
602
603 print_tree(t);
604
605 for ( i = 0; i < 60000; i++ ) {
606 long x = rand() % 10000;
607#ifdef TRACE
608 print_tree(t);
609 printf("Deleting key %ld\n\n", x);
610#endif
611 rbtree_delete(t, (void *) x, compare_int);
612 }
613 return 0;
614}
diff --git a/src/rc4.c b/src/rc4.c
new file mode 100644
index 0000000..8a67303
--- /dev/null
+++ b/src/rc4.c
@@ -0,0 +1,156 @@
1#include <stdio.h>
2#include <stdlib.h>
3#include <string.h> /* memset() */
4
5#include "random.h"
6#include "util.h"
7
8struct rc4_ctx {
9 struct random_ctx ctx;
10
11 unsigned int i;
12 unsigned int j;
13 unsigned char S[256];
14};
15
16static void
17swap(unsigned char a[], unsigned int i, unsigned int j)
18{
19 unsigned char t = a[i];
20 a[i] = a[j];
21 a[j] = t;
22}
23
24unsigned char
25rc4_get_byte(struct rc4_ctx *ctx)
26{
27 ctx->i = (ctx->i + 1) % 256;
28 ctx->j = (ctx->j + ctx->S[ctx->i]) % 256;
29 swap(ctx->S, ctx->i, ctx->j);
30
31 return ctx->S[(ctx->S[ctx->i] + ctx->S[ctx->j]) % 256];
32}
33
34void
35rc4_init(struct rc4_ctx *ctx, void *key, size_t sz)
36{
37 const unsigned char *K = key;
38 unsigned int i, j;
39
40 for ( i = 0; i != 256; ++i )
41 ctx->S[i] = i;
42
43 for ( i = j = 0; i != 256; ++i ) {
44 j = (j + ctx->S[i] + K[i % sz]) % 256;
45 swap(ctx->S, i, j);
46 }
47
48 ctx->i = 0;
49 ctx->j = 0;
50 ctx->ctx.get_byte = (unsigned char (*)(struct random_ctx *)) rc4_get_byte;
51}
52
53void
54rc4_clear(struct rc4_ctx *ctx)
55{
56 memset(ctx, 0, sizeof *ctx);
57}
58
59struct random_ctx *
60rc4_create(void *key, size_t sz)
61{
62 struct rc4_ctx *ctx;
63
64 ctx = malloc(sizeof(*ctx));
65 if ( ctx ) {
66 rc4_init(ctx, key, sz);
67
68 return &(ctx->ctx);
69 }
70
71 return NULL;
72}
73
74void
75rc4_free(struct random_ctx *ctx)
76{
77 rc4_clear((struct rc4_ctx *) ctx);
78 free(ctx);
79}
80
81void
82rc4_test(void)
83{
84 static struct {
85 char * key;
86 unsigned int sz;
87 struct {
88 unsigned int pos;
89 unsigned char bytes[16];
90 } test[18];
91 } cases[] = {
92 { "\x01\x02\x03\x04\x05", 5, { { 0, "\xb2\x39\x63\x05\xf0\x3d\xc0\x27\xcc\xc3\x52\x4a\x0a\x11\x18\xa8" }, { 16, "\x69\x82\x94\x4f\x18\xfc\x82\xd5\x89\xc4\x03\xa4\x7a\x0d\x09\x19" }, { 240, "\x28\xcb\x11\x32\xc9\x6c\xe2\x86\x42\x1d\xca\xad\xb8\xb6\x9e\xae" }, { 256, "\x1c\xfc\xf6\x2b\x03\xed\xdb\x64\x1d\x77\xdf\xcf\x7f\x8d\x8c\x93" }, { 496, "\x42\xb7\xd0\xcd\xd9\x18\xa8\xa3\x3d\xd5\x17\x81\xc8\x1f\x40\x41" }, { 512, "\x64\x59\x84\x44\x32\xa7\xda\x92\x3c\xfb\x3e\xb4\x98\x06\x61\xf6" }, { 752, "\xec\x10\x32\x7b\xde\x2b\xee\xfd\x18\xf9\x27\x76\x80\x45\x7e\x22" }, { 768, "\xeb\x62\x63\x8d\x4f\x0b\xa1\xfe\x9f\xca\x20\xe0\x5b\xf8\xff\x2b" }, { 1008, "\x45\x12\x90\x48\xe6\xa0\xed\x0b\x56\xb4\x90\x33\x8f\x07\x8d\xa5" }, { 1024, "\x30\xab\xbc\xc7\xc2\x0b\x01\x60\x9f\x23\xee\x2d\x5f\x6b\xb7\xdf" }, { 1520, "\x32\x94\xf7\x44\xd8\xf9\x79\x05\x07\xe7\x0f\x62\xe5\xbb\xce\xea" }, { 1536, "\xd8\x72\x9d\xb4\x18\x82\x25\x9b\xee\x4f\x82\x53\x25\xf5\xa1\x30" }, { 2032, "\x1e\xb1\x4a\x0c\x13\xb3\xbf\x47\xfa\x2a\x0b\xa9\x3a\xd4\x5b\x8b" }, { 2048, "\xcc\x58\x2f\x8b\xa9\xf2\x65\xe2\xb1\xbe\x91\x12\xe9\x75\xd2\xd7" }, { 3056, "\xf2\xe3\x0f\x9b\xd1\x02\xec\xbf\x75\xaa\xad\xe9\xbc\x35\xc4\x3c" }, { 3072, "\xec\x0e\x11\xc4\x79\xdc\x32\x9d\xc8\xda\x79\x68\xfe\x96\x56\x81" }, { 4080, "\x06\x83\x26\xa2\x11\x84\x16\xd2\x1f\x9d\x04\xb2\xcd\x1c\xa0\x50" }, { 4096, "\xff\x25\xb5\x89\x95\x99\x67\x07\xe5\x1f\xbd\xf0\x8b\x34\xd8\x75" } } },
93 { "\x01\x02\x03\x04\x05\x06\x07", 7, { { 0, "\x29\x3f\x02\xd4\x7f\x37\xc9\xb6\x33\xf2\xaf\x52\x85\xfe\xb4\x6b" }, { 16, "\xe6\x20\xf1\x39\x0d\x19\xbd\x84\xe2\xe0\xfd\x75\x20\x31\xaf\xc1" }, { 240, "\x91\x4f\x02\x53\x1c\x92\x18\x81\x0d\xf6\x0f\x67\xe3\x38\x15\x4c" }, { 256, "\xd0\xfd\xb5\x83\x07\x3c\xe8\x5a\xb8\x39\x17\x74\x0e\xc0\x11\xd5" }, { 496, "\x75\xf8\x14\x11\xe8\x71\xcf\xfa\x70\xb9\x0c\x74\xc5\x92\xe4\x54" }, { 512, "\x0b\xb8\x72\x02\x93\x8d\xad\x60\x9e\x87\xa5\xa1\xb0\x79\xe5\xe4" }, { 752, "\xc2\x91\x12\x46\xb6\x12\xe7\xe7\xb9\x03\xdf\xed\xa1\xda\xd8\x66" }, { 768, "\x32\x82\x8f\x91\x50\x2b\x62\x91\x36\x8d\xe8\x08\x1d\xe3\x6f\xc2" }, { 1008, "\xf3\xb9\xa7\xe3\xb2\x97\xbf\x9a\xd8\x04\x51\x2f\x90\x63\xef\xf1" }, { 1024, "\x8e\xcb\x67\xa9\xba\x1f\x55\xa5\xa0\x67\xe2\xb0\x26\xa3\x67\x6f" }, { 1520, "\xd2\xaa\x90\x2b\xd4\x2d\x0d\x7c\xfd\x34\x0c\xd4\x58\x10\x52\x9f" }, { 1536, "\x78\xb2\x72\xc9\x6e\x42\xea\xb4\xc6\x0b\xd9\x14\xe3\x9d\x06\xe3" }, { 2032, "\xf4\x33\x2f\xd3\x1a\x07\x93\x96\xee\x3c\xee\x3f\x2a\x4f\xf0\x49" }, { 2048, "\x05\x45\x97\x81\xd4\x1f\xda\x7f\x30\xc1\xbe\x7e\x12\x46\xc6\x23" }, { 3056, "\xad\xfd\x38\x68\xb8\xe5\x14\x85\xd5\xe6\x10\x01\x7e\x3d\xd6\x09" }, { 3072, "\xad\x26\x58\x1c\x0c\x5b\xe4\x5f\x4c\xea\x01\xdb\x2f\x38\x05\xd5" }, { 4080, "\xf3\x17\x2c\xef\xfc\x3b\x3d\x99\x7c\x85\xcc\xd5\xaf\x1a\x95\x0c" }, { 4096, "\xe7\x4b\x0b\x97\x31\x22\x7f\xd3\x7c\x0e\xc0\x8a\x47\xdd\xd8\xb8" } } },
94 { "\x01\x02\x03\x04\x05\x06\x07\x08", 8, { { 0, "\x97\xab\x8a\x1b\xf0\xaf\xb9\x61\x32\xf2\xf6\x72\x58\xda\x15\xa8" }, { 16, "\x82\x63\xef\xdb\x45\xc4\xa1\x86\x84\xef\x87\xe6\xb1\x9e\x5b\x09" }, { 240, "\x96\x36\xeb\xc9\x84\x19\x26\xf4\xf7\xd1\xf3\x62\xbd\xdf\x6e\x18" }, { 256, "\xd0\xa9\x90\xff\x2c\x05\xfe\xf5\xb9\x03\x73\xc9\xff\x4b\x87\x0a" }, { 496, "\x73\x23\x9f\x1d\xb7\xf4\x1d\x80\xb6\x43\xc0\xc5\x25\x18\xec\x63" }, { 512, "\x16\x3b\x31\x99\x23\xa6\xbd\xb4\x52\x7c\x62\x61\x26\x70\x3c\x0f" }, { 752, "\x49\xd6\xc8\xaf\x0f\x97\x14\x4a\x87\xdf\x21\xd9\x14\x72\xf9\x66" }, { 768, "\x44\x17\x3a\x10\x3b\x66\x16\xc5\xd5\xad\x1c\xee\x40\xc8\x63\xd0" }, { 1008, "\x27\x3c\x9c\x4b\x27\xf3\x22\xe4\xe7\x16\xef\x53\xa4\x7d\xe7\xa4" }, { 1024, "\xc6\xd0\xe7\xb2\x26\x25\x9f\xa9\x02\x34\x90\xb2\x61\x67\xad\x1d" }, { 1520, "\x1f\xe8\x98\x67\x13\xf0\x7c\x3d\x9a\xe1\xc1\x63\xff\x8c\xf9\xd3" }, { 1536, "\x83\x69\xe1\xa9\x65\x61\x0b\xe8\x87\xfb\xd0\xc7\x91\x62\xaa\xfb" }, { 2032, "\x0a\x01\x27\xab\xb4\x44\x84\xb9\xfb\xef\x5a\xbc\xae\x1b\x57\x9f" }, { 2048, "\xc2\xcd\xad\xc6\x40\x2e\x8e\xe8\x66\xe1\xf3\x7b\xdb\x47\xe4\x2c" }, { 3056, "\x26\xb5\x1e\xa3\x7d\xf8\xe1\xd6\xf7\x6f\xc3\xb6\x6a\x74\x29\xb3" }, { 3072, "\xbc\x76\x83\x20\x5d\x4f\x44\x3d\xc1\xf2\x9d\xda\x33\x15\xc8\x7b" }, { 4080, "\xd5\xfa\x5a\x34\x69\xd2\x9a\xaa\xf8\x3d\x23\x58\x9d\xb8\xc8\x5b" }, { 4096, "\x3f\xb4\x6e\x2c\x8f\x0f\x06\x8e\xdc\xe8\xcd\xcd\x7d\xfc\x58\x62" } } },
95 { "\x01\x02\x03\x04\x05\x06\x07\x08\x09\x0a", 10, { { 0, "\xed\xe3\xb0\x46\x43\xe5\x86\xcc\x90\x7d\xc2\x18\x51\x70\x99\x02" }, { 16, "\x03\x51\x6b\xa7\x8f\x41\x3b\xeb\x22\x3a\xa5\xd4\xd2\xdf\x67\x11" }, { 240, "\x3c\xfd\x6c\xb5\x8e\xe0\xfd\xde\x64\x01\x76\xad\x00\x00\x04\x4d" }, { 256, "\x48\x53\x2b\x21\xfb\x60\x79\xc9\x11\x4c\x0f\xfd\x9c\x04\xa1\xad" }, { 496, "\x3e\x8c\xea\x98\x01\x71\x09\x97\x90\x84\xb1\xef\x92\xf9\x9d\x86" }, { 512, "\xe2\x0f\xb4\x9b\xdb\x33\x7e\xe4\x8b\x8d\x8d\xc0\xf4\xaf\xef\xfe" }, { 752, "\x5c\x25\x21\xea\xcd\x79\x66\xf1\x5e\x05\x65\x44\xbe\xa0\xd3\x15" }, { 768, "\xe0\x67\xa7\x03\x19\x31\xa2\x46\xa6\xc3\x87\x5d\x2f\x67\x8a\xcb" }, { 1008, "\xa6\x4f\x70\xaf\x88\xae\x56\xb6\xf8\x75\x81\xc0\xe2\x3e\x6b\x08" }, { 1024, "\xf4\x49\x03\x1d\xe3\x12\x81\x4e\xc6\xf3\x19\x29\x1f\x4a\x05\x16" }, { 1520, "\xbd\xae\x85\x92\x4b\x3c\xb1\xd0\xa2\xe3\x3a\x30\xc6\xd7\x95\x99" }, { 1536, "\x8a\x0f\xed\xdb\xac\x86\x5a\x09\xbc\xd1\x27\xfb\x56\x2e\xd6\x0a" }, { 2032, "\xb5\x5a\x0a\x5b\x51\xa1\x2a\x8b\xe3\x48\x99\xc3\xe0\x47\x51\x1a" }, { 2048, "\xd9\xa0\x9c\xea\x3c\xe7\x5f\xe3\x96\x98\x07\x03\x17\xa7\x13\x39" }, { 3056, "\x55\x22\x25\xed\x11\x77\xf4\x45\x84\xac\x8c\xfa\x6c\x4e\xb5\xfc" }, { 3072, "\x7e\x82\xcb\xab\xfc\x95\x38\x1b\x08\x09\x98\x44\x21\x29\xc2\xf8" }, { 4080, "\x1f\x13\x5e\xd1\x4c\xe6\x0a\x91\x36\x9d\x23\x22\xbe\xf2\x5e\x3c" }, { 4096, "\x08\xb6\xbe\x45\x12\x4a\x43\xe2\xeb\x77\x95\x3f\x84\xdc\x85\x53" } } },
96 { "\x01\x02\x03\x04\x05\x06\x07\x08\x09\x0a\x0b\x0c\x0d\x0e\x0f\x10", 16, { { 0, "\x9a\xc7\xcc\x9a\x60\x9d\x1e\xf7\xb2\x93\x28\x99\xcd\xe4\x1b\x97" }, { 16, "\x52\x48\xc4\x95\x90\x14\x12\x6a\x6e\x8a\x84\xf1\x1d\x1a\x9e\x1c" }, { 240, "\x06\x59\x02\xe4\xb6\x20\xf6\xcc\x36\xc8\x58\x9f\x66\x43\x2f\x2b" }, { 256, "\xd3\x9d\x56\x6b\xc6\xbc\xe3\x01\x07\x68\x15\x15\x49\xf3\x87\x3f" }, { 496, "\xb6\xd1\xe6\xc4\xa5\xe4\x77\x1c\xad\x79\x53\x8d\xf2\x95\xfb\x11" }, { 512, "\xc6\x8c\x1d\x5c\x55\x9a\x97\x41\x23\xdf\x1d\xbc\x52\xa4\x3b\x89" }, { 752, "\xc5\xec\xf8\x8d\xe8\x97\xfd\x57\xfe\xd3\x01\x70\x1b\x82\xa2\x59" }, { 768, "\xec\xcb\xe1\x3d\xe1\xfc\xc9\x1c\x11\xa0\xb2\x6c\x0b\xc8\xfa\x4d" }, { 1008, "\xe7\xa7\x25\x74\xf8\x78\x2a\xe2\x6a\xab\xcf\x9e\xbc\xd6\x60\x65" }, { 1024, "\xbd\xf0\x32\x4e\x60\x83\xdc\xc6\xd3\xce\xdd\x3c\xa8\xc5\x3c\x16" }, { 1520, "\xb4\x01\x10\xc4\x19\x0b\x56\x22\xa9\x61\x16\xb0\x01\x7e\xd2\x97" }, { 1536, "\xff\xa0\xb5\x14\x64\x7e\xc0\x4f\x63\x06\xb8\x92\xae\x66\x11\x81" }, { 2032, "\xd0\x3d\x1b\xc0\x3c\xd3\x3d\x70\xdf\xf9\xfa\x5d\x71\x96\x3e\xbd" }, { 2048, "\x8a\x44\x12\x64\x11\xea\xa7\x8b\xd5\x1e\x8d\x87\xa8\x87\x9b\xf5" }, { 3056, "\xfa\xbe\xb7\x60\x28\xad\xe2\xd0\xe4\x87\x22\xe4\x6c\x46\x15\xa3" }, { 3072, "\xc0\x5d\x88\xab\xd5\x03\x57\xf9\x35\xa6\x3c\x59\xee\x53\x76\x23" }, { 4080, "\xff\x38\x26\x5c\x16\x42\xc1\xab\xe8\xd3\xc2\xfe\x5e\x57\x2b\xf8" }, { 4096, "\xa3\x6a\x4c\x30\x1a\xe8\xac\x13\x61\x0c\xcb\xc1\x22\x56\xca\xcc" } } },
97 { "\x01\x02\x03\x04\x05\x06\x07\x08\x09\x0a\x0b\x0c\x0d\x0e\x0f\x10\x11\x12\x13\x14\x15\x16\x17\x18", 24, { { 0, "\x05\x95\xe5\x7f\xe5\xf0\xbb\x3c\x70\x6e\xda\xc8\xa4\xb2\xdb\x11" }, { 16, "\xdf\xde\x31\x34\x4a\x1a\xf7\x69\xc7\x4f\x07\x0a\xee\x9e\x23\x26" }, { 240, "\xb0\x6b\x9b\x1e\x19\x5d\x13\xd8\xf4\xa7\x99\x5c\x45\x53\xac\x05" }, { 256, "\x6b\xd2\x37\x8e\xc3\x41\xc9\xa4\x2f\x37\xba\x79\xf8\x8a\x32\xff" }, { 496, "\xe7\x0b\xce\x1d\xf7\x64\x5a\xdb\x5d\x2c\x41\x30\x21\x5c\x35\x22" }, { 512, "\x9a\x57\x30\xc7\xfc\xb4\xc9\xaf\x51\xff\xda\x89\xc7\xf1\xad\x22" }, { 752, "\x04\x85\x05\x5f\xd4\xf6\xf0\xd9\x63\xef\x5a\xb9\xa5\x47\x69\x82" }, { 768, "\x59\x1f\xc6\x6b\xcd\xa1\x0e\x45\x2b\x03\xd4\x55\x1f\x6b\x62\xac" }, { 1008, "\x27\x53\xcc\x83\x98\x8a\xfa\x3e\x16\x88\xa1\xd3\xb4\x2c\x9a\x02" }, { 1024, "\x93\x61\x0d\x52\x3d\x1d\x3f\x00\x62\xb3\xc2\xa3\xbb\xc7\xc7\xf0" }, { 1520, "\x96\xc2\x48\x61\x0a\xad\xed\xfe\xaf\x89\x78\xc0\x3d\xe8\x20\x5a" }, { 1536, "\x0e\x31\x7b\x3d\x1c\x73\xb9\xe9\xa4\x68\x8f\x29\x6d\x13\x3a\x19" }, { 2032, "\xbd\xf0\xe6\xc3\xcc\xa5\xb5\xb9\xd5\x33\xb6\x9c\x56\xad\xa1\x20" }, { 2048, "\x88\xa2\x18\xb6\xe2\xec\xe1\xe6\x24\x6d\x44\xc7\x59\xd1\x9b\x10" }, { 3056, "\x68\x66\x39\x7e\x95\xc1\x40\x53\x4f\x94\x26\x34\x21\x00\x6e\x40" }, { 3072, "\x32\xcb\x0a\x1e\x95\x42\xc6\xb3\xb8\xb3\x98\xab\xc3\xb0\xf1\xd5" }, { 4080, "\x29\xa0\xb8\xae\xd5\x4a\x13\x23\x24\xc6\x2e\x42\x3f\x54\xb4\xc8" }, { 4096, "\x3c\xb0\xf3\xb5\x02\x0a\x98\xb8\x2a\xf9\xfe\x15\x44\x84\xa1\x68" } } },
98 { "\x01\x02\x03\x04\x05\x06\x07\x08\x09\x0a\x0b\x0c\x0d\x0e\x0f\x10\x11\x12\x13\x14\x15\x16\x17\x18\x19\x1a\x1b\x1c\x1d\x1e\x1f\x20", 32, { { 0, "\xea\xa6\xbd\x25\x88\x0b\xf9\x3d\x3f\x5d\x1e\x4c\xa2\x61\x1d\x91" }, { 16, "\xcf\xa4\x5c\x9f\x7e\x71\x4b\x54\xbd\xfa\x80\x02\x7c\xb1\x43\x80" }, { 240, "\x11\x4a\xe3\x44\xde\xd7\x1b\x35\xf2\xe6\x0f\xeb\xad\x72\x7f\xd8" }, { 256, "\x02\xe1\xe7\x05\x6b\x0f\x62\x39\x00\x49\x64\x22\x94\x3e\x97\xb6" }, { 496, "\x91\xcb\x93\xc7\x87\x96\x4e\x10\xd9\x52\x7d\x99\x9c\x6f\x93\x6b" }, { 512, "\x49\xb1\x8b\x42\xf8\xe8\x36\x7c\xbe\xb5\xef\x10\x4b\xa1\xc7\xcd" }, { 752, "\x87\x08\x4b\x3b\xa7\x00\xba\xde\x95\x56\x10\x67\x27\x45\xb3\x74" }, { 768, "\xe7\xa7\xb9\xe9\xec\x54\x0d\x5f\xf4\x3b\xdb\x12\x79\x2d\x1b\x35" }, { 1008, "\xc7\x99\xb5\x96\x73\x8f\x6b\x01\x8c\x76\xc7\x4b\x17\x59\xbd\x90" }, { 1024, "\x7f\xec\x5b\xfd\x9f\x9b\x89\xce\x65\x48\x30\x90\x92\xd7\xe9\x58" }, { 1520, "\x40\xf2\x50\xb2\x6d\x1f\x09\x6a\x4a\xfd\x4c\x34\x0a\x58\x88\x15" }, { 1536, "\x3e\x34\x13\x5c\x79\xdb\x01\x02\x00\x76\x76\x51\xcf\x26\x30\x73" }, { 2032, "\xf6\x56\xab\xcc\xf8\x8d\xd8\x27\x02\x7b\x2c\xe9\x17\xd4\x64\xec" }, { 2048, "\x18\xb6\x25\x03\xbf\xbc\x07\x7f\xba\xbb\x98\xf2\x0d\x98\xab\x34" }, { 3056, "\x8a\xed\x95\xee\x5b\x0d\xcb\xfb\xef\x4e\xb2\x1d\x3a\x3f\x52\xf9" }, { 3072, "\x62\x5a\x1a\xb0\x0e\xe3\x9a\x53\x27\x34\x6b\xdd\xb0\x1a\x9c\x18" }, { 4080, "\xa1\x3a\x7c\x79\xc7\xe1\x19\xb5\xab\x02\x96\xab\x28\xc3\x00\xb9" }, { 4096, "\xf3\xe4\xc0\xa2\xe0\x2d\x1d\x01\xf7\xf0\xa7\x46\x18\xaf\x2b\x48" } } },
99 { "\x83\x32\x22\x77\x2a", 5, { { 0, "\x80\xad\x97\xbd\xc9\x73\xdf\x8a\x2e\x87\x9e\x92\xa4\x97\xef\xda" }, { 16, "\x20\xf0\x60\xc2\xf2\xe5\x12\x65\x01\xd3\xd4\xfe\xa1\x0d\x5f\xc0" }, { 240, "\xfa\xa1\x48\xe9\x90\x46\x18\x1f\xec\x6b\x20\x85\xf3\xb2\x0e\xd9" }, { 256, "\xf0\xda\xf5\xba\xb3\xd5\x96\x83\x98\x57\x84\x6f\x73\xfb\xfe\x5a" }, { 496, "\x1c\x7e\x2f\xc4\x63\x92\x32\xfe\x29\x75\x84\xb2\x96\x99\x6b\xc8" }, { 512, "\x3d\xb9\xb2\x49\x40\x6c\xc8\xed\xff\xac\x55\xcc\xd3\x22\xba\x12" }, { 752, "\xe4\xf9\xf7\xe0\x06\x61\x54\xbb\xd1\x25\xb7\x45\x56\x9b\xc8\x97" }, { 768, "\x75\xd5\xef\x26\x2b\x44\xc4\x1a\x9c\xf6\x3a\xe1\x45\x68\xe1\xb9" }, { 1008, "\x6d\xa4\x53\xdb\xf8\x1e\x82\x33\x4a\x3d\x88\x66\xcb\x50\xa1\xe3" }, { 1024, "\x78\x28\xd0\x74\x11\x9c\xab\x5c\x22\xb2\x94\xd7\xa9\xbf\xa0\xbb" }, { 1520, "\xad\xb8\x9c\xea\x9a\x15\xfb\xe6\x17\x29\x5b\xd0\x4b\x8c\xa0\x5c" }, { 1536, "\x62\x51\xd8\x7f\xd4\xaa\xae\x9a\x7e\x4a\xd5\xc2\x17\xd3\xf3\x00" }, { 2032, "\xe7\x11\x9b\xd6\xdd\x9b\x22\xaf\xe8\xf8\x95\x85\x43\x28\x81\xe2" }, { 2048, "\x78\x5b\x60\xfd\x7e\xc4\xe9\xfc\xb6\x54\x5f\x35\x0d\x66\x0f\xab" }, { 3056, "\xaf\xec\xc0\x37\xfd\xb7\xb0\x83\x8e\xb3\xd7\x0b\xcd\x26\x83\x82" }, { 3072, "\xdb\xc1\xa7\xb4\x9d\x57\x35\x8c\xc9\xfa\x6d\x61\xd7\x3b\x7c\xf0" }, { 4080, "\x63\x49\xd1\x26\xa3\x7a\xfc\xba\x89\x79\x4f\x98\x04\x91\x4f\xdc" }, { 4096, "\xbf\x42\xc3\x01\x8c\x2f\x7c\x66\xbf\xde\x52\x49\x75\x76\x81\x15" } } },
100 { "\x19\x10\x83\x32\x22\x77\x2a", 7, { { 0, "\xbc\x92\x22\xdb\xd3\x27\x4d\x8f\xc6\x6d\x14\xcc\xbd\xa6\x69\x0b" }, { 16, "\x7a\xe6\x27\x41\x0c\x9a\x2b\xe6\x93\xdf\x5b\xb7\x48\x5a\x63\xe3" }, { 240, "\x3f\x09\x31\xaa\x03\xde\xfb\x30\x0f\x06\x01\x03\x82\x6f\x2a\x64" }, { 256, "\xbe\xaa\x9e\xc8\xd5\x9b\xb6\x81\x29\xf3\x02\x7c\x96\x36\x11\x81" }, { 496, "\x74\xe0\x4d\xb4\x6d\x28\x64\x8d\x7d\xee\x8a\x00\x64\xb0\x6c\xfe" }, { 512, "\x9b\x5e\x81\xc6\x2f\xe0\x23\xc5\x5b\xe4\x2f\x87\xbb\xf9\x32\xb8" }, { 752, "\xce\x17\x8f\xc1\x82\x6e\xfe\xcb\xc1\x82\xf5\x79\x99\xa4\x61\x40" }, { 768, "\x8b\xdf\x55\xcd\x55\x06\x1c\x06\xdb\xa6\xbe\x11\xde\x4a\x57\x8a" }, { 1008, "\x62\x6f\x5f\x4d\xce\x65\x25\x01\xf3\x08\x7d\x39\xc9\x2c\xc3\x49" }, { 1024, "\x42\xda\xac\x6a\x8f\x9a\xb9\xa7\xfd\x13\x7c\x60\x37\x82\x56\x82" }, { 1520, "\xcc\x03\xfd\xb7\x91\x92\xa2\x07\x31\x2f\x53\xf5\xd4\xdc\x33\xd9" }, { 1536, "\xf7\x0f\x14\x12\x2a\x1c\x98\xa3\x15\x5d\x28\xb8\xa0\xa8\xa4\x1d" }, { 2032, "\x2a\x3a\x30\x7a\xb2\x70\x8a\x9c\x00\xfe\x0b\x42\xf9\xc2\xd6\xa1" }, { 2048, "\x86\x26\x17\x62\x7d\x22\x61\xea\xb0\xb1\x24\x65\x97\xca\x0a\xe9" }, { 3056, "\x55\xf8\x77\xce\x4f\x2e\x1d\xdb\xbf\x8e\x13\xe2\xcd\xe0\xfd\xc8" }, { 3072, "\x1b\x15\x56\xcb\x93\x5f\x17\x33\x37\x70\x5f\xbb\x5d\x50\x1f\xc1" }, { 4080, "\xec\xd0\xe9\x66\x02\xbe\x7f\x8d\x50\x92\x81\x6c\xcc\xf2\xc2\xe9" }, { 4096, "\x02\x78\x81\xfa\xb4\x99\x3a\x1c\x26\x20\x24\xa9\x4f\xff\x3f\x61" } } },
101 { "\x64\x19\x10\x83\x32\x22\x77\x2a", 8, { { 0, "\xbb\xf6\x09\xde\x94\x13\x17\x2d\x07\x66\x0c\xb6\x80\x71\x69\x26" }, { 16, "\x46\x10\x1a\x6d\xab\x43\x11\x5d\x6c\x52\x2b\x4f\xe9\x36\x04\xa9" }, { 240, "\xcb\xe1\xff\xf2\x1c\x96\xf3\xee\xf6\x1e\x8f\xe0\x54\x2c\xbd\xf0" }, { 256, "\x34\x79\x38\xbf\xfa\x40\x09\xc5\x12\xcf\xb4\x03\x4b\x0d\xd1\xa7" }, { 496, "\x78\x67\xa7\x86\xd0\x0a\x71\x47\x90\x4d\x76\xdd\xf1\xe5\x20\xe3" }, { 512, "\x8d\x3e\x9e\x1c\xae\xfc\xcc\xb3\xfb\xf8\xd1\x8f\x64\x12\x0b\x32" }, { 752, "\x94\x23\x37\xf8\xfd\x76\xf0\xfa\xe8\xc5\x2d\x79\x54\x81\x06\x72" }, { 768, "\xb8\x54\x8c\x10\xf5\x16\x67\xf6\xe6\x0e\x18\x2f\xa1\x9b\x30\xf7" }, { 1008, "\x02\x11\xc7\xc6\x19\x0c\x9e\xfd\x12\x37\xc3\x4c\x8f\x2e\x06\xc4" }, { 1024, "\xbd\xa6\x4f\x65\x27\x6d\x2a\xac\xb8\xf9\x02\x12\x20\x3a\x80\x8e" }, { 1520, "\xbd\x38\x20\xf7\x32\xff\xb5\x3e\xc1\x93\xe7\x9d\x33\xe2\x7c\x73" }, { 1536, "\xd0\x16\x86\x16\x86\x19\x07\xd4\x82\xe3\x6c\xda\xc8\xcf\x57\x49" }, { 2032, "\x97\xb0\xf0\xf2\x24\xb2\xd2\x31\x71\x14\x80\x8f\xb0\x3a\xf7\xa0" }, { 2048, "\xe5\x96\x16\xe4\x69\x78\x79\x39\xa0\x63\xce\xea\x9a\xf9\x56\xd1" }, { 3056, "\xc4\x7e\x0d\xc1\x66\x09\x19\xc1\x11\x01\x20\x8f\x9e\x69\xaa\x1f" }, { 3072, "\x5a\xe4\xf1\x28\x96\xb8\x37\x9a\x2a\xad\x89\xb5\xb5\x53\xd6\xb0" }, { 4080, "\x6b\x6b\x09\x8d\x0c\x29\x3b\xc2\x99\x3d\x80\xbf\x05\x18\xb6\xd9" }, { 4096, "\x81\x70\xcc\x3c\xcd\x92\xa6\x98\x62\x1b\x93\x9d\xd3\x8f\xe7\xb9" } } },
102 { "\x8b\x37\x64\x19\x10\x83\x32\x22\x77\x2a", 10, { { 0, "\xab\x65\xc2\x6e\xdd\xb2\x87\x60\x0d\xb2\xfd\xa1\x0d\x1e\x60\x5c" }, { 16, "\xbb\x75\x90\x10\xc2\x96\x58\xf2\xc7\x2d\x93\xa2\xd1\x6d\x29\x30" }, { 240, "\xb9\x01\xe8\x03\x6e\xd1\xc3\x83\xcd\x3c\x4c\x4d\xd0\xa6\xab\x05" }, { 256, "\x3d\x25\xce\x49\x22\x92\x4c\x55\xf0\x64\x94\x33\x53\xd7\x8a\x6c" }, { 496, "\x12\xc1\xaa\x44\xbb\xf8\x7e\x75\xe6\x11\xf6\x9b\x2c\x38\xf4\x9b" }, { 512, "\x28\xf2\xb3\x43\x4b\x65\xc0\x98\x77\x47\x00\x44\xc6\xea\x17\x0d" }, { 752, "\xbd\x9e\xf8\x22\xde\x52\x88\x19\x61\x34\xcf\x8a\xf7\x83\x93\x04" }, { 768, "\x67\x55\x9c\x23\xf0\x52\x15\x84\x70\xa2\x96\xf7\x25\x73\x5a\x32" }, { 1008, "\x8b\xab\x26\xfb\xc2\xc1\x2b\x0f\x13\xe2\xab\x18\x5e\xab\xf2\x41" }, { 1024, "\x31\x18\x5a\x6d\x69\x6f\x0c\xfa\x9b\x42\x80\x8b\x38\xe1\x32\xa2" }, { 1520, "\x56\x4d\x3d\xae\x18\x3c\x52\x34\xc8\xaf\x1e\x51\x06\x1c\x44\xb5" }, { 1536, "\x3c\x07\x78\xa7\xb5\xf7\x2d\x3c\x23\xa3\x13\x5c\x7d\x67\xb9\xf4" }, { 2032, "\xf3\x43\x69\x89\x0f\xcf\x16\xfb\x51\x7d\xca\xae\x44\x63\xb2\xdd" }, { 2048, "\x02\xf3\x1c\x81\xe8\x20\x07\x31\xb8\x99\xb0\x28\xe7\x91\xbf\xa7" }, { 3056, "\x72\xda\x64\x62\x83\x22\x8c\x14\x30\x08\x53\x70\x17\x95\x61\x6f" }, { 3072, "\x4e\x0a\x8c\x6f\x79\x34\xa7\x88\xe2\x26\x5e\x81\xd6\xd0\xc8\xf4" }, { 4080, "\x43\x8d\xd5\xea\xfe\xa0\x11\x1b\x6f\x36\xb4\xb9\x38\xda\x2a\x68" }, { 4096, "\x5f\x6b\xfc\x73\x81\x58\x74\xd9\x71\x00\xf0\x86\x97\x93\x57\xd8" } } },
103 { "\xeb\xb4\x62\x27\xc6\xcc\x8b\x37\x64\x19\x10\x83\x32\x22\x77\x2a", 16, { { 0, "\x72\x0c\x94\xb6\x3e\xdf\x44\xe1\x31\xd9\x50\xca\x21\x1a\x5a\x30" }, { 16, "\xc3\x66\xfd\xea\xcf\x9c\xa8\x04\x36\xbe\x7c\x35\x84\x24\xd2\x0b" }, { 240, "\xb3\x39\x4a\x40\xaa\xbf\x75\xcb\xa4\x22\x82\xef\x25\xa0\x05\x9f" }, { 256, "\x48\x47\xd8\x1d\xa4\x94\x2d\xbc\x24\x9d\xef\xc4\x8c\x92\x2b\x9f" }, { 496, "\x08\x12\x8c\x46\x9f\x27\x53\x42\xad\xda\x20\x2b\x2b\x58\xda\x95" }, { 512, "\x97\x0d\xac\xef\x40\xad\x98\x72\x3b\xac\x5d\x69\x55\xb8\x17\x61" }, { 752, "\x3c\xb8\x99\x93\xb0\x7b\x0c\xed\x93\xde\x13\xd2\xa1\x10\x13\xac" }, { 768, "\xef\x2d\x67\x6f\x15\x45\xc2\xc1\x3d\xc6\x80\xa0\x2f\x4a\xdb\xfe" }, { 1008, "\xb6\x05\x95\x51\x4f\x24\xbc\x9f\xe5\x22\xa6\xca\xd7\x39\x36\x44" }, { 1024, "\xb5\x15\xa8\xc5\x01\x17\x54\xf5\x90\x03\x05\x8b\xdb\x81\x51\x4e" }, { 1520, "\x3c\x70\x04\x7e\x8c\xbc\x03\x8e\x3b\x98\x20\xdb\x60\x1d\xa4\x95" }, { 1536, "\x11\x75\xda\x6e\xe7\x56\xde\x46\xa5\x3e\x2b\x07\x56\x60\xb7\x70" }, { 2032, "\x00\xa5\x42\xbb\xa0\x21\x11\xcc\x2c\x65\xb3\x8e\xbd\xba\x58\x7e" }, { 2048, "\x58\x65\xfd\xbb\x5b\x48\x06\x41\x04\xe8\x30\xb3\x80\xf2\xae\xde" }, { 3056, "\x34\xb2\x1a\xd2\xad\x44\xe9\x99\xdb\x2d\x7f\x08\x63\xf0\xd9\xb6" }, { 3072, "\x84\xa9\x21\x8f\xc3\x6e\x8a\x5f\x2c\xcf\xbe\xae\x53\xa2\x7d\x25" }, { 4080, "\xa2\x22\x1a\x11\xb8\x33\xcc\xb4\x98\xa5\x95\x40\xf0\x54\x5f\x4a" }, { 4096, "\x5b\xbe\xb4\x78\x7d\x59\xe5\x37\x3f\xdb\xea\x6c\x6f\x75\xc2\x9b" } } },
104 { "\xc1\x09\x16\x39\x08\xeb\xe5\x1d\xeb\xb4\x62\x27\xc6\xcc\x8b\x37\x64\x19\x10\x83\x32\x22\x77\x2a", 24, { { 0, "\x54\xb6\x4e\x6b\x5a\x20\xb5\xe2\xec\x84\x59\x3d\xc7\x98\x9d\xa7" }, { 16, "\xc1\x35\xee\xe2\x37\xa8\x54\x65\xff\x97\xdc\x03\x92\x4f\x45\xce" }, { 240, "\xcf\xcc\x92\x2f\xb4\xa1\x4a\xb4\x5d\x61\x75\xaa\xbb\xf2\xd2\x01" }, { 256, "\x83\x7b\x87\xe2\xa4\x46\xad\x0e\xf7\x98\xac\xd0\x2b\x94\x12\x4f" }, { 496, "\x17\xa6\xdb\xd6\x64\x92\x6a\x06\x36\xb3\xf4\xc3\x7a\x4f\x46\x94" }, { 512, "\x4a\x5f\x9f\x26\xae\xee\xd4\xd4\xa2\x5f\x63\x2d\x30\x52\x33\xd9" }, { 752, "\x80\xa3\xd0\x1e\xf0\x0c\x8e\x9a\x42\x09\xc1\x7f\x4e\xeb\x35\x8c" }, { 768, "\xd1\x5e\x7d\x5f\xfa\xaa\xbc\x02\x07\xbf\x20\x0a\x11\x77\x93\xa2" }, { 1008, "\x34\x96\x82\xbf\x58\x8e\xaa\x52\xd0\xaa\x15\x60\x34\x6a\xea\xfa" }, { 1024, "\xf5\x85\x4c\xdb\x76\xc8\x89\xe3\xad\x63\x35\x4e\x5f\x72\x75\xe3" }, { 1520, "\x53\x2c\x7c\xec\xcb\x39\xdf\x32\x36\x31\x84\x05\xa4\xb1\x27\x9c" }, { 1536, "\xba\xef\xe6\xd9\xce\xb6\x51\x84\x22\x60\xe0\xd1\xe0\x5e\x3b\x90" }, { 2032, "\xe8\x2d\x8c\x6d\xb5\x4e\x3c\x63\x3f\x58\x1c\x95\x2b\xa0\x42\x07" }, { 2048, "\x4b\x16\xe5\x0a\xbd\x38\x1b\xd7\x09\x00\xa9\xcd\x9a\x62\xcb\x23" }, { 3056, "\x36\x82\xee\x33\xbd\x14\x8b\xd9\xf5\x86\x56\xcd\x8f\x30\xd9\xfb" }, { 3072, "\x1e\x5a\x0b\x84\x75\x04\x5d\x9b\x20\xb2\x62\x86\x24\xed\xfd\x9e" }, { 4080, "\x63\xed\xd6\x84\xfb\x82\x62\x82\xfe\x52\x8f\x9c\x0e\x92\x37\xbc" }, { 4096, "\xe4\xdd\x2e\x98\xd6\x96\x0f\xae\x0b\x43\x54\x54\x56\x74\x33\x91" } } },
105 { "\x1a\xda\x31\xd5\xcf\x68\x82\x21\xc1\x09\x16\x39\x08\xeb\xe5\x1d\xeb\xb4\x62\x27\xc6\xcc\x8b\x37\x64\x19\x10\x83\x32\x22\x77\x2a", 32, { { 0, "\xdd\x5b\xcb\x00\x18\xe9\x22\xd4\x94\x75\x9d\x7c\x39\x5d\x02\xd3" }, { 16, "\xc8\x44\x6f\x8f\x77\xab\xf7\x37\x68\x53\x53\xeb\x89\xa1\xc9\xeb" }, { 240, "\xaf\x3e\x30\xf9\xc0\x95\x04\x59\x38\x15\x15\x75\xc3\xfb\x90\x98" }, { 256, "\xf8\xcb\x62\x74\xdb\x99\xb8\x0b\x1d\x20\x12\xa9\x8e\xd4\x8f\x0e" }, { 496, "\x25\xc3\x00\x5a\x1c\xb8\x5d\xe0\x76\x25\x98\x39\xab\x71\x98\xab" }, { 512, "\x9d\xcb\xc1\x83\xe8\xcb\x99\x4b\x72\x7b\x75\xbe\x31\x80\x76\x9c" }, { 752, "\xa1\xd3\x07\x8d\xfa\x91\x69\x50\x3e\xd9\xd4\x49\x1d\xee\x4e\xb2" }, { 768, "\x85\x14\xa5\x49\x58\x58\x09\x6f\x59\x6e\x4b\xcd\x66\xb1\x06\x65" }, { 1008, "\x5f\x40\xd5\x9e\xc1\xb0\x3b\x33\x73\x8e\xfa\x60\xb2\x25\x5d\x31" }, { 1024, "\x34\x77\xc7\xf7\x64\xa4\x1b\xac\xef\xf9\x0b\xf1\x4f\x92\xb7\xcc" }, { 1520, "\xac\x4e\x95\x36\x8d\x99\xb9\xeb\x78\xb8\xda\x8f\x81\xff\xa7\x95" }, { 1536, "\x8c\x3c\x13\xf8\xc2\x38\x8b\xb7\x3f\x38\x57\x6e\x65\xb7\xc4\x46" }, { 2032, "\x13\xc4\xb9\xc1\xdf\xb6\x65\x79\xed\xdd\x8a\x28\x0b\x9f\x73\x16" }, { 2048, "\xdd\xd2\x78\x20\x55\x01\x26\x69\x8e\xfa\xad\xc6\x4b\x64\xf6\x6e" }, { 3056, "\xf0\x8f\x2e\x66\xd2\x8e\xd1\x43\xf3\xa2\x37\xcf\x9d\xe7\x35\x59" }, { 3072, "\x9e\xa3\x6c\x52\x55\x31\xb8\x80\xba\x12\x43\x34\xf5\x7b\x0b\x70" }, { 4080, "\xd5\xa3\x9e\x3d\xfc\xc5\x02\x80\xba\xc4\xa6\xb5\xaa\x0d\xca\x7d" }, { 4096, "\x37\x0b\x1c\x1f\xe6\x55\x91\x6d\x97\xfd\x0d\x47\xca\x1d\x72\xb8" } } }
106 };
107
108 struct rc4_ctx ctx;
109
110 for ( size_t i = 0; i != NELEM(cases); ++i ) {
111 rc4_init(&ctx, cases[i].key, cases[i].sz);
112
113 unsigned int pos = 0;
114
115 for ( int j = 0; j != 18; ++j ) {
116 while ( pos != cases[i].test[j].pos ) {
117 rc4_get_byte(&ctx);
118 ++pos;
119 }
120
121 unsigned char bytes[16];
122 for ( unsigned int k = 0; k != 16; ++k ) {
123 bytes[k] = rc4_get_byte(&ctx);
124 ++pos;
125 }
126
127 if ( memcmp(bytes, cases[i].test[j].bytes, 16) != 0 ) {
128 ERROR("Fehler");
129 exit(EXIT_FAILURE);
130 }
131 }
132
133 printf("Test #%zu : OK\n", i);
134
135 rc4_clear(&ctx);
136 }
137}
138
139int
140main()
141{
142 rc4_test();
143
144 struct random_ctx *random = rc4_create("\x01\x02\x03\x04\x05\x06\x07", 7);
145
146 for ( int j = 0; j != 18; ++j ) {
147 for ( int i = 0; i != 16; ++i ) {
148 printf("%02X ", random_get_byte(random));
149 }
150 puts("");
151 }
152
153 rc4_free(random);
154
155 return 0;
156}
diff --git a/src/ringbuff.c b/src/ringbuff.c
new file mode 100644
index 0000000..1294b3b
--- /dev/null
+++ b/src/ringbuff.c
@@ -0,0 +1,156 @@
1#include <assert.h>
2#include <stdbool.h>
3#include <stdio.h>
4#include <stdlib.h>
5
6#include "util.h"
7
8/* --8<-- ring_type */
9typedef int T;
10
11struct ring_buffer {
12 size_t head, tail;
13 T array[8]; /* fit for your needs... */
14};
15/* -->8-- */
16
17/* --8<-- ring_init */
18void
19ring_init(struct ring_buffer *rb)
20{
21 rb->head = rb->tail = 0;
22}
23/* -->8-- */
24
25/* --8<-- ring_push_front */
26bool
27ring_push_front(struct ring_buffer *rb, T data)
28{
29 const size_t prev = (rb->tail + NELEM(rb->array) - 1) % NELEM(rb->array);
30
31 if ( prev == rb->head ) {
32 return false;
33 }
34
35 rb->array[prev] = data;
36 rb->tail = prev;
37
38 return true;
39}
40/* -->8-- */
41
42/* --8<-- ring_push_back */
43bool
44ring_push_back(struct ring_buffer *rb, T data)
45{
46 const size_t next = (rb->head + 1) % NELEM(rb->array);
47
48 if ( next == rb->tail ) {
49 return false;
50 }
51
52 rb->array[rb->head] = data;
53 rb->head = next;
54
55 return true;
56}
57/* -->8-- */
58
59/* --8<-- ring_pop_front */
60bool
61ring_pop_front(struct ring_buffer *rb, T *data)
62{
63 if ( rb->head == rb->tail ) {
64 return false;
65 }
66
67 const size_t next = (rb->tail + 1) % NELEM(rb->array);
68
69 *data = rb->array[rb->tail];
70 rb->tail = next;
71
72 return true;
73}
74/* -->8-- */
75
76/* --8<-- ring_pop_back */
77bool
78ring_pop_back(struct ring_buffer *rb, T *data)
79{
80 if ( rb->head == rb->tail ) {
81 return false;
82 }
83
84 const size_t prev = (rb->head + NELEM(rb->array) - 1) % NELEM(rb->array);
85
86 *data = rb->array[prev];
87 rb->head = prev;
88
89 return true;
90}
91/* -->8-- */
92
93/* --8<-- ring_put */
94bool
95ring_put(struct ring_buffer *rb, T data)
96{
97 return ring_push_back(rb, data);
98}
99/* -->8-- */
100
101/* --8<-- ring_get */
102bool
103ring_get(struct ring_buffer *rb, T *data)
104{
105 return ring_pop_front(rb, data);
106}
107/* -->8-- */
108
109void
110debug_print(const char *msg, struct ring_buffer *rb)
111{
112 printf("%s: head: %zu, tail: %zu\n", msg, rb->head, rb->tail);
113}
114
115int
116main(void)
117{
118#if 0
119 struct ring_buffer rb;
120 ring_init(&rb);
121#else
122 struct ring_buffer rb = { .head = 0, .tail = 0 };
123#endif
124
125 assert(ring_push_back(&rb, 1) == true); // 1
126 assert(ring_push_back(&rb, 2) == true); // 1, 2
127 assert(ring_push_back(&rb, 3) == true); // 1, 2, 3
128 assert(ring_push_back(&rb, 4) == true); // 1, 2, 3, 4
129
130 debug_print("Stand", &rb);
131
132 assert(ring_push_front(&rb, 0) == true); // 0, 1, 2, 3, 4
133 assert(ring_push_front(&rb, -1) == true); // -1, 0, 1, 2, 3, 4
134
135 debug_print("Stand", &rb);
136
137 T temp;
138 assert(ring_pop_back(&rb, &temp) == true); // -1, 0, 1, 2, 3
139 assert(ring_pop_front(&rb, &temp) == true); // 0, 1, 2, 3
140
141 debug_print("Stand", &rb);
142
143 assert(ring_push_back(&rb, 4) == true); // 0, 1, 2, 3, 4
144 assert(ring_push_back(&rb, 5) == true); // 0, 1, 2, 3, 4, 5
145 assert(ring_push_back(&rb, 6) == true); // 0, 1, 2, 3, 4, 5, 6
146 assert(ring_push_back(&rb, 7) == false); // 0, 1, 2, 3, 4, 5, 6
147 assert(ring_push_front(&rb, 7) == false); // 0, 1, 2, 3, 4, 5, 6
148
149 while ( ring_pop_back(&rb, &temp) ) {
150 printf("temp: %d\n", temp);
151 }
152
153 debug_print("Stand", &rb);
154
155 return EXIT_SUCCESS;
156}
diff --git a/src/shellsort.c b/src/shellsort.c
new file mode 100644
index 0000000..29e6bf8
--- /dev/null
+++ b/src/shellsort.c
@@ -0,0 +1,63 @@
1#include <stdio.h>
2#include <stdlib.h>
3#include <time.h>
4
5#include "util.h"
6
7typedef int T;
8
9void
10shellsort(T a[], size_t n)
11{
12 //static const size_t gaps[] = { 701, 301, 132, 57, 23, 10, 4, 1 };
13
14 // Wikipedia:
15 //static const size_t gaps[] = { 2147483647, 1131376761, 410151271, 157840433, 58548857, 21521774, 8810089, 3501671, 1355339, 543749, 213331, 84801, 27901, 11969, 4711, 1968, 815, 271, 111, 41, 13, 4, 1 };
16
17 // https://www.cs.princeton.edu/~rs/shell/paperF.pdf
18 static const size_t gaps[] = { 1391376, 463792, 198768, 86961, 33936, 13776, 4592, 1968, 861, 336, 112, 48, 21, 7, 3, 1 };
19
20 for ( size_t k = 0; k < NELEM(gaps); ++k ) {
21 const size_t gap = gaps[k];
22
23 for ( size_t i = gap; i < n; i++ ) {
24 size_t j = i;
25 T temp = a[i];
26
27 for ( ; j >= gap && a[j - gap] > temp; j -= gap )
28 a[j] = a[j - gap];
29
30 a[j] = temp;
31 }
32 }
33}
34
35static void
36test(T a[], size_t n)
37{
38 for ( size_t i = 1; i < n; ++i ) {
39 if ( a[i - 1] > a[i] ) {
40 ERROR("sortierung passt nicht");
41 }
42 }
43}
44
45int
46main(void)
47{
48 T a[1000000];
49
50 srand(time(NULL));
51 for ( size_t i = 0; i != NELEM(a); ++i )
52 a[i] = rand() % 1000;
53
54 clock_t start = clock();
55 shellsort(a, NELEM(a));
56 clock_t end = clock();
57
58 test(a, NELEM(a));
59
60 printf("duration: %.3f sec\n", ((double) (end - start)) / CLOCKS_PER_SEC);
61
62 return EXIT_SUCCESS;
63}
diff --git a/src/stack.c b/src/stack.c
new file mode 100644
index 0000000..48b9eba
--- /dev/null
+++ b/src/stack.c
@@ -0,0 +1,110 @@
1/* Standard C */
2#include <stdbool.h>
3#include <stdio.h>
4#include <stdlib.h>
5
6/* Project */
7#include "util.h"
8
9/* --8<-- stack_type */
10typedef int T;
11
12struct stack_item {
13 struct stack_item *next;
14 T data;
15};
16
17struct stack {
18 struct stack_item *head;
19};
20/* -->8-- */
21
22/* --8<-- stack_init */
23void
24stack_init(struct stack *stack)
25{
26 stack->head = NULL;
27}
28/* -->8-- */
29
30/* --8<-- stack_push */
31void
32stack_push(struct stack *stack, T data)
33{
34 struct stack_item *new_item;
35
36 if ( (new_item = malloc(sizeof *new_item)) != NULL ) {
37 new_item->data = data;
38 new_item->next = stack->head;
39 stack->head = new_item;
40 }
41 else
42 ERROR("out of memory");
43}
44/* -->8-- */
45
46/* --8<-- stack_pop */
47bool
48stack_pop(struct stack *stack, T *data)
49{
50 if ( stack->head ) {
51 struct stack_item *next = stack->head->next;
52
53 if ( data ) {
54 *data = stack->head->data;
55 }
56 free(stack->head);
57 stack->head = next;
58
59 return true;
60 }
61 else
62 return false;
63}
64/* -->8-- */
65
66/* --8<-- stack_empty */
67bool
68stack_empty(struct stack *stack)
69{
70 return stack->head == NULL;
71}
72/* -->8-- */
73
74/* --8<-- stack_free */
75void
76stack_free(struct stack *stack)
77{
78 struct stack_item *item, *next;
79
80 for ( item = stack->head; item; item = next ) {
81 next = item->next;
82 free(item);
83 }
84}
85/* -->8-- */
86
87int
88main()
89{
90 struct stack stack[1];
91
92 stack_init(stack);
93
94 for ( int i = 0; i != 10; ++i )
95 stack_push(stack, i);
96
97 /*
98 while ( !stack_empty(stack) ) {
99 int i;
100 if ( stack_pop(stack, &i) )
101 printf("%d\n", i);
102 else
103 ERROR("this shouldn't happen!");
104 }
105 */
106
107 stack_free(stack);
108
109 return EXIT_SUCCESS;
110}
diff --git a/src/stack2.c b/src/stack2.c
new file mode 100644
index 0000000..5f4ba41
--- /dev/null
+++ b/src/stack2.c
@@ -0,0 +1,115 @@
1#include <stdbool.h>
2#include <stdio.h>
3#include <stdlib.h>
4
5#include "util.h"
6
7/* --8<-- stack2_type */
8typedef int T;
9
10struct stack {
11 T * array;
12 size_t sz, p;
13};
14/* -->8-- */
15
16/* --8<-- stack2_init */
17void
18stack_init(struct stack *stack)
19{
20 stack->array = NULL;
21 stack->sz = 0;
22 stack->p = 0;
23}
24/* -->8-- */
25
26/* --8<-- stack2_push */
27bool
28stack_push(struct stack *stack, T data)
29{
30 if ( stack->array == NULL ) {
31 if ( (stack->array = malloc(10 * sizeof *stack->array)) != NULL ) {
32 stack->sz = 10;
33 stack->p = 0;
34 }
35 else {
36 ERROR("out of memory");
37 return false;
38 }
39 }
40
41 if ( stack->p == stack->sz ) {
42 size_t new_sz;
43 T * new_array;
44
45 if ( (new_array = realloc(stack->array, (new_sz = (stack->sz * 3 / 2)) * sizeof *stack->array)) != NULL ) {
46 stack->array = new_array;
47 stack->sz = new_sz;
48 }
49 else {
50 ERROR("out of memory");
51 return false;
52 }
53 }
54
55 stack->array[stack->p++] = data;
56 return true;
57}
58/* -->8-- */
59
60/* --8<-- stack2_pop */
61bool
62stack_pop(struct stack *stack, T *data)
63{
64 if ( stack->p != 0 ) {
65 --stack->p;
66
67 if ( data ) {
68 *data = stack->array[stack->p];
69 }
70 return true;
71 }
72 else
73 return false;
74}
75/* -->8-- */
76
77/* --8<-- stack2_empty */
78bool
79stack_empty(struct stack *stack)
80{
81 return stack->p == 0;
82}
83/* -->8-- */
84
85/* --8<-- stack2_free */
86void
87stack_free(struct stack *stack)
88{
89 free(stack->array);
90}
91/* -->8-- */
92
93int
94main()
95{
96 struct stack stack[1];
97
98 stack_init(stack);
99
100 for ( int i = 0; i != 20; ++i )
101 stack_push(stack, i);
102
103 while ( !stack_empty(stack) ) {
104 int i;
105
106 if ( stack_pop(stack, &i) )
107 printf("%d\n", i);
108 else
109 ERROR("this shouldn't happen!");
110 }
111
112 stack_free(stack);
113
114 return EXIT_SUCCESS;
115}
diff --git a/src/tree.c b/src/tree.c
new file mode 100644
index 0000000..93690e2
--- /dev/null
+++ b/src/tree.c
@@ -0,0 +1,806 @@
1// Binary Search Tree
2#include <limits.h>
3#include <stdbool.h>
4#include <stdio.h>
5#include <stdlib.h>
6#include <time.h>
7
8#include "util.h"
9
10/* --8<-- tree_type */
11typedef int T;
12
13struct tree_node {
14 struct tree_node *left, *right;
15 T key;
16 int count; /* collision counter */
17 /* ggf. weitere Felder... */
18};
19/* -->8-- */
20
21/* --8<-- tree_isBst */
22static bool
23tree_isBstUntil(struct tree_node *tree, T min, T max)
24{
25 if ( tree == NULL )
26 return true;
27
28 if ( tree->key < min || tree->key > max )
29 return false;
30
31 return tree_isBstUntil(tree->left, min, tree->key - 1) &&
32 tree_isBstUntil(tree->right, tree->key + 1, max);
33}
34
35bool
36tree_isBst(struct tree_node *tree)
37{
38 return tree_isBstUntil(tree, INT_MIN, INT_MAX);
39}
40/* -->8-- */
41
42/* --8<-- tree_insert */
43struct tree_node *
44tree_insert(struct tree_node *tree, T key)
45{
46 if ( tree == NULL ) {
47 tree = malloc(sizeof *tree);
48 if ( tree ) {
49 tree->key = key;
50 tree->count = 1;
51 tree->left = NULL;
52 tree->right = NULL;
53 }
54 else
55 ERROR("out of memory");
56 }
57 else if ( key < tree->key )
58 tree->left = tree_insert(tree->left, key);
59 else if ( key > tree->key )
60 tree->right = tree_insert(tree->right, key);
61 else /* key == tree->key */
62 tree->count++; /* handle collision */
63
64 return tree;
65}
66/* -->8-- */
67
68/* --8<-- tree_insert_it */
69struct tree_node *
70tree_insert_it(struct tree_node *tree, T key)
71{
72 struct tree_node *parent = NULL;
73
74 for ( struct tree_node *curr = tree; curr; ) {
75 parent = curr;
76
77 if ( key < curr->key ) {
78 curr = curr->left;
79 }
80 else if ( key > curr->key ) {
81 curr = curr->right;
82 }
83 else { /* key == current->key */
84 curr->count++;
85 return tree;
86 }
87 }
88
89 struct tree_node *new_node;
90
91 new_node = malloc(sizeof *new_node);
92 if ( new_node ) {
93 new_node->key = key;
94 new_node->count = 1;
95 new_node->left = NULL;
96 new_node->right = NULL;
97
98 if ( parent == NULL ) {
99 tree = new_node;
100 }
101 else if ( key < parent->key ) {
102 parent->left = new_node;
103 }
104 else {
105 parent->right = new_node;
106 }
107 }
108 else {
109 ERROR("out of memory");
110 }
111
112 return tree;
113}
114/* -->8-- */
115
116/* --8<-- tree_detach_min */
117static struct tree_node *
118tree_detach_min(struct tree_node **ptree)
119{
120 struct tree_node *tree = *ptree;
121
122 if ( tree == NULL )
123 return NULL;
124 else if ( tree->left )
125 return tree_detach_min(&tree->left);
126 else {
127 *ptree = tree->right;
128 return tree;
129 }
130}
131/* -->8-- */
132
133/* --8<-- tree_remove */
134struct tree_node *
135tree_remove(struct tree_node *tree, T key)
136{
137 if ( tree == NULL )
138 return NULL;
139
140 if ( key < tree->key )
141 tree->left = tree_remove(tree->left, key);
142 else if ( key > tree->key )
143 tree->right = tree_remove(tree->right, key);
144 else { /* key == tree->key */
145 if ( --tree->count == 0 ) { /* Handle Collision */
146 struct tree_node *temp = tree;
147
148 if ( tree->left == NULL ) {
149 tree = tree->right;
150 }
151 else if ( tree->right == NULL ) {
152 tree = tree->left;
153 }
154 else {
155 struct tree_node *min = tree_detach_min(&tree->right);
156
157 min->left = tree->left;
158 min->right = tree->right;
159
160 tree = min;
161 }
162
163 free(temp);
164 }
165 }
166 return tree;
167}
168/* -->8-- */
169
170/* --8<-- tree_clear */
171void
172tree_clear(struct tree_node *tree)
173{
174 if ( tree ) {
175 tree_clear(tree->left);
176 tree_clear(tree->right);
177 free(tree);
178 }
179}
180/* -->8-- */
181
182/* --8<-- tree_lookup */
183struct tree_node *
184tree_lookup(struct tree_node *tree, T key)
185{
186 while ( tree )
187 if ( key < tree->key )
188 tree = tree->left;
189 else if ( key > tree->key )
190 tree = tree->right;
191 else /* key == tree->key */
192 break;
193
194 return tree;
195}
196/* -->8-- */
197
198/* --8<-- tree_minimum */
199struct tree_node *
200tree_minimum(struct tree_node *tree)
201{
202 if ( tree )
203 while ( tree->left )
204 tree = tree->left;
205
206 return tree;
207}
208/* -->8-- */
209
210/* --8<-- tree_maximum */
211struct tree_node *
212tree_maximum(struct tree_node *tree)
213{
214 if ( tree )
215 while ( tree->right )
216 tree = tree->right;
217
218 return tree;
219}
220/* -->8-- */
221
222/* --8<-- tree_height */
223size_t
224tree_height(struct tree_node *tree)
225{
226 if ( tree ) {
227 size_t hl = tree_height(tree->left);
228 size_t hr = tree_height(tree->right);
229
230 return ((hl > hr) ? hl : hr) + 1;
231 }
232
233 return 0;
234}
235/* -->8-- */
236
237/* --8<-- tree_count */
238size_t
239tree_count(struct tree_node *tree)
240{
241 if ( tree )
242 return tree_count(tree->left) + tree_count(tree->right) + 1;
243
244 return 0;
245}
246/* -->8-- */
247
248/* --8<-- tree_copy */
249struct tree_node *
250tree_copy(struct tree_node *tree)
251{
252 if ( tree ) {
253 struct tree_node *new_node;
254
255 new_node = malloc(sizeof *new_node);
256 if ( new_node ) {
257 new_node->key = tree->key;
258 new_node->count = tree->count;
259 new_node->left = tree_copy(tree->left);
260 new_node->right = tree_copy(tree->right);
261 }
262 else {
263 ERROR("out of memory");
264 }
265
266 return new_node;
267 }
268 return NULL;
269}
270/* -->8-- */
271
272/* --8<-- tree_isleaf */
273bool
274tree_isleaf(struct tree_node *tree)
275{
276 return tree->left == NULL && tree->right == NULL;
277}
278/* -->8-- */
279
280/* --8<-- tree_apply_preorder */
281void
282tree_apply_preorder(struct tree_node *tree, void (*visit)(T key, void *cl), void *cl)
283{
284 if ( tree ) {
285 visit(tree->key, cl);
286 tree_apply_preorder(tree->left, visit, cl);
287 tree_apply_preorder(tree->right, visit, cl);
288 }
289}
290/* -->8-- */
291
292/* --8<-- tree_apply_inorder */
293void
294tree_apply_inorder(struct tree_node *tree, void (*visit)(T key, void *cl), void *cl)
295{
296 if ( tree ) {
297 tree_apply_inorder(tree->left, visit, cl);
298 visit(tree->key, cl);
299 tree_apply_inorder(tree->right, visit, cl);
300 }
301}
302/* -->8-- */
303
304/* --8<-- tree_apply_postorder */
305void
306tree_apply_postorder(struct tree_node *tree, void (*visit)(T key, void *cl), void *cl)
307{
308 if ( tree ) {
309 tree_apply_postorder(tree->left, visit, cl);
310 tree_apply_postorder(tree->right, visit, cl);
311 visit(tree->key, cl);
312 }
313}
314/* -->8-- */
315
316/* ===== */
317
318/* --8<-- tree_stack_type */
319struct stack_item {
320 struct stack_item *next;
321 struct tree_node * data;
322};
323
324struct stack {
325 struct stack_item *head;
326};
327/* -->8-- */
328
329/* --8<-- tree_stack_init */
330static void
331stack_init(struct stack *stack)
332{
333 stack->head = NULL;
334}
335/* -->8-- */
336
337/* --8<-- tree_stack_push */
338static void
339stack_push(struct stack *stack, struct tree_node *data)
340{
341 struct stack_item *new_item;
342
343 if ( (new_item = malloc(sizeof *new_item)) ) {
344 new_item->data = data;
345 new_item->next = stack->head;
346 stack->head = new_item;
347 }
348 else
349 ERROR("out of memory");
350}
351/* -->8-- */
352
353/* --8<-- tree_stack_pop */
354static bool
355stack_pop(struct stack *stack, struct tree_node **data)
356{
357 if ( stack->head ) {
358 struct stack_item *next;
359
360 next = stack->head->next;
361 *data = stack->head->data;
362
363 free(stack->head);
364 stack->head = next;
365
366 return true;
367 }
368 else
369 return false;
370}
371/* -->8-- */
372
373/* --8<-- tree_stack_peek */
374static struct tree_node *
375stack_peek(struct stack *stack)
376{
377 return (stack->head) ? stack->head->data : NULL;
378}
379/* -->8-- */
380
381/* --8<-- tree_stack_empty */
382static bool
383stack_empty(struct stack *stack)
384{
385 return stack->head == NULL;
386}
387/* -->8-- */
388
389/* --8<-- tree_stack_free */
390void
391stack_free(struct stack *stack)
392{
393 struct stack_item *item, *next;
394
395 for ( item = stack->head; item; item = next ) {
396 next = item->next;
397 free(item);
398 }
399}
400/* -->8-- */
401
402/* ===== */
403
404/* --8<-- tree_queue_type */
405struct queue_item {
406 struct queue_item *next;
407 struct tree_node * data;
408};
409
410struct queue {
411 struct queue_item *head, *tail;
412};
413/* -->8-- */
414
415/* --8<-- tree_queue_init */
416void
417queue_init(struct queue *queue)
418{
419 queue->head = NULL;
420}
421/* -->8-- */
422
423/* --8<-- tree_queue_put */
424void
425queue_put(struct queue *queue, struct tree_node *data)
426{
427 struct queue_item *new_item;
428
429 if ( (new_item = malloc(sizeof *new_item)) ) {
430 struct queue_item *tail;
431
432 tail = queue->tail;
433 new_item->data = data;
434 new_item->next = NULL;
435 queue->tail = new_item;
436
437 if ( queue->head == NULL )
438 queue->head = queue->tail;
439 else
440 tail->next = queue->tail;
441 }
442 else
443 ERROR("out of memory");
444}
445/* -->8-- */
446
447/* --8<-- tree_queue_get */
448bool
449queue_get(struct queue *queue, struct tree_node **data)
450{
451 if ( queue->head ) {
452 struct queue_item *next;
453
454 next = queue->head->next;
455 *data = queue->head->data;
456
457 free(queue->head);
458 queue->head = next;
459
460 return true;
461 }
462 else
463 return false;
464}
465/* -->8-- */
466
467/* --8<-- tree_queue_empty */
468bool
469queue_empty(struct queue *queue)
470{
471 return queue->head == NULL;
472}
473/* -->8-- */
474
475/* --8<-- tree_queue_free */
476void
477queue_free(struct queue *queue)
478{
479 struct queue_item *item, *next;
480
481 for ( item = queue->head; item; item = next ) {
482 next = item->next;
483 free(item);
484 }
485}
486/* -->8-- */
487
488/* ===== */
489
490/* --8<-- tree_apply_preorder_it */
491void
492tree_apply_preorder_it(struct tree_node *tree, void (*visit)(T key, void *cl), void *cl)
493{
494 if ( tree ) {
495 struct stack stack;
496
497 stack_init(&stack);
498
499 stack_push(&stack, tree);
500
501 while ( stack_pop(&stack, &tree) ) {
502 visit(tree->key, cl);
503
504 if ( tree->right )
505 stack_push(&stack, tree->right);
506 if ( tree->left )
507 stack_push(&stack, tree->left);
508 }
509
510 stack_free(&stack);
511 }
512}
513/* -->8-- */
514
515/* --8<-- tree_apply_inorder_it */
516void
517tree_apply_inorder_it(struct tree_node *tree, void (*visit)(T key, void *cl), void *cl)
518{
519 if ( tree ) {
520 struct stack stack;
521
522 stack_init(&stack);
523
524 while ( !stack_empty(&stack) || tree ) {
525 if ( tree ) {
526 stack_push(&stack, tree);
527 tree = tree->left;
528 }
529 else {
530 stack_pop(&stack, &tree);
531 visit(tree->key, cl);
532 tree = tree->right;
533 }
534 }
535
536 stack_free(&stack);
537 }
538}
539/* -->8-- */
540
541// Hier eine Version für PostOrder-Iterativ:
542// Quelle: https://stackoverflow.com/a/16092333
543
544/* --8<-- tree_apply_postorder_it */
545void
546tree_apply_postorder_it(struct tree_node *tree, void (*visit)(T key, void *cl), void *cl)
547{
548 if ( tree ) {
549 struct stack stack;
550
551 stack_init(&stack);
552 stack_push(&stack, tree);
553
554 while ( !stack_empty(&stack) ) {
555 struct tree_node *next = stack_peek(&stack);
556
557 bool finishedSubtrees = (next->left == tree || next->right == tree);
558
559 if ( finishedSubtrees || tree_isleaf(next) ) {
560 stack_pop(&stack, &next);
561
562 visit(next->key, cl);
563
564 tree = next;
565 }
566 else {
567 if ( next->right ) {
568 stack_push(&stack, next->right);
569 }
570 if ( next->left ) {
571 stack_push(&stack, next->left);
572 }
573 }
574 }
575 stack_free(&stack);
576 }
577}
578/* -->8-- */
579
580/* --8<-- tree_apply_levelorder_it */
581void
582tree_apply_levelorder_it(struct tree_node *tree, void (*visit)(T key, void *cl), void *cl)
583{
584 if ( tree ) {
585 struct queue queue;
586
587 queue_init(&queue);
588
589 queue_put(&queue, tree);
590
591 while ( queue_get(&queue, &tree) ) {
592 visit(tree->key, cl);
593
594 if ( tree->left )
595 queue_put(&queue, tree->left);
596 if ( tree->right )
597 queue_put(&queue, tree->right);
598 }
599
600 queue_free(&queue);
601 }
602}
603/* -->8-- */
604
605/* ======================== */
606
607/* --8<-- tree_iterator_type */
608struct tree_iterator {
609 struct stack stack;
610};
611/* -->8-- */
612
613/* --8<-- tree_iterator_push_leftmost */
614static void
615tree_iterator_push_leftmost(struct stack *stack, struct tree_node *node)
616{
617 for ( ; node; node = node->left ) {
618 stack_push(stack, node);
619 }
620}
621/* -->8-- */
622
623/* --8<-- tree_iterator_next */
624struct tree_node *
625tree_iterator_next(struct tree_iterator *it)
626{
627 struct tree_node *node = NULL;
628
629 if ( stack_pop(&it->stack, &node) ) {
630 tree_iterator_push_leftmost(&it->stack, node->right);
631 }
632
633 return node;
634}
635/* -->8-- */
636
637/* --8<-- tree_iterator_first */
638struct tree_node *
639tree_iterator_first(struct tree_iterator *it, struct tree_node *tree)
640{
641 stack_init(&it->stack);
642
643 tree_iterator_push_leftmost(&it->stack, tree);
644
645 return tree_iterator_next(it);
646}
647/* -->8-- */
648
649/* --8<-- tree_iterator_free */
650void
651tree_iterator_free(struct tree_iterator *it)
652{
653 stack_free(&it->stack);
654}
655/* -->8-- */
656
657/* --8<-- tree_preorder_iterator_next */
658struct tree_node *
659tree_preorder_iterator_next(struct tree_iterator *it)
660{
661 struct tree_node *node = NULL;
662
663 if ( stack_pop(&it->stack, &node) ) {
664 if ( node->right ) {
665 stack_push(&it->stack, node->right);
666 }
667 if ( node->left ) {
668 stack_push(&it->stack, node->left);
669 }
670 }
671
672 return node;
673}
674/* -->8-- */
675
676/* --8<-- tree_preorder_iterator_first */
677struct tree_node *
678tree_preorder_iterator_first(struct tree_iterator *it, struct tree_node *tree)
679{
680 stack_init(&it->stack);
681
682 if ( tree ) {
683 stack_push(&it->stack, tree);
684
685 return tree_preorder_iterator_next(it);
686 }
687 else {
688 return NULL;
689 }
690}
691/* -->8-- */
692
693/* ===== */
694
695void
696print(T data, void *cl)
697{
698 (void) cl;
699 printf("%d\n", data);
700}
701
702#include "treeutil.h"
703
704int
705main_(void)
706{
707 // Teste den Fall von mycodeschool
708
709 struct tree_node *tree = NULL;
710
711 tree = tree_insert(tree, 12);
712 tree = tree_insert(tree, 5);
713 tree = tree_insert(tree, 15);
714 tree = tree_insert(tree, 3);
715 tree = tree_insert(tree, 7);
716 tree = tree_insert(tree, 13);
717 tree = tree_insert(tree, 17);
718 tree = tree_insert(tree, 1);
719 tree = tree_insert(tree, 9);
720 tree = tree_insert(tree, 14);
721 tree = tree_insert(tree, 20);
722 tree = tree_insert(tree, 8);
723 tree = tree_insert(tree, 11);
724 tree = tree_insert(tree, 18);
725
726 tree = tree_remove(tree, 15);
727
728 if ( !tree_isBst(tree) ) {
729 fprintf(stderr, "Tree ist kein BST!!\n");
730 return EXIT_FAILURE;
731 }
732
733 show_tree(tree, 0, 0);
734
735 tree_clear(tree);
736
737 return EXIT_SUCCESS;
738}
739
740int
741main__(void)
742{
743 struct tree_node *tree = NULL;
744
745 tree = tree_insert(tree, 5);
746 tree = tree_insert(tree, 3);
747 tree = tree_insert(tree, 7);
748 tree = tree_insert(tree, 2);
749 tree = tree_insert(tree, 4);
750 tree = tree_insert(tree, 6);
751 tree = tree_insert(tree, 8);
752
753 tree = tree_remove(tree, 2);
754 tree = tree_remove(tree, 3);
755 tree = tree_remove(tree, 5);
756
757 if ( !tree_isBst(tree) ) {
758 fprintf(stderr, "Tree ist kein BST!!\n");
759 return EXIT_FAILURE;
760 }
761
762 show_tree(tree, 0, 0);
763
764 tree_clear(tree);
765
766 return EXIT_SUCCESS;
767}
768
769int
770main(void)
771{
772 struct tree_node *tree = NULL;
773
774 tree = tree_insert_it(tree, 10);
775 tree = tree_insert_it(tree, 5);
776 tree = tree_insert_it(tree, 20);
777 tree = tree_insert_it(tree, 1);
778 tree = tree_insert_it(tree, 7);
779 tree = tree_insert_it(tree, 15);
780 tree = tree_insert_it(tree, 18);
781
782 tree_apply_preorder(tree, print, NULL);
783 puts("postorder:");
784 tree_apply_postorder(tree, print, NULL);
785 puts("postorder_it:");
786 tree_apply_postorder_it(tree, print, NULL);
787 show_tree(tree, 0, 0);
788
789 puts("levelorder_it:");
790 tree_apply_levelorder_it(tree, print, NULL);
791
792 show_tree(tree, 0, 0);
793
794 struct tree_iterator it;
795 struct tree_node * node = tree_preorder_iterator_first(&it, tree);
796 while ( node ) {
797 fprintf(stdout, "%d\n", node->key);
798
799 node = tree_preorder_iterator_next(&it);
800 }
801 tree_iterator_free(&it);
802
803 tree_clear(tree);
804
805 return EXIT_SUCCESS;
806}
diff --git a/src/treeutil.h b/src/treeutil.h
new file mode 100644
index 0000000..76627c0
--- /dev/null
+++ b/src/treeutil.h
@@ -0,0 +1,51 @@
1// aux display and verification routines, helpful but not essential
2struct trunk {
3 struct trunk *prev;
4 const char * str;
5};
6
7static void
8show_trunks(struct trunk *p)
9{
10 if ( !p )
11 return;
12 show_trunks(p->prev);
13 printf("%s", p->str);
14}
15
16// this is very haphazzard
17static void
18show_tree(struct tree_node *root, struct trunk *prev, int is_left)
19{
20 if ( root == NULL )
21 return;
22
23 struct trunk this_disp = { prev, " " };
24 const char * prev_str = this_disp.str;
25 show_tree(root->right, &this_disp, 1);
26
27 if ( !prev )
28 this_disp.str = "---";
29 else if ( is_left ) {
30 this_disp.str = ".--";
31 prev_str = " |";
32 }
33 else {
34 this_disp.str = "`--";
35 prev->str = prev_str;
36 }
37
38 show_trunks(&this_disp);
39 if ( root->key >= 'A' && root->key <= 'Z' )
40 printf("%c\n", root->key);
41 else
42 printf("%d\n", root->key);
43
44 if ( prev )
45 prev->str = prev_str;
46 this_disp.str = " |";
47
48 show_tree(root->left, &this_disp, 0);
49 if ( !prev )
50 puts("");
51}
diff --git a/src/util.h b/src/util.h
new file mode 100644
index 0000000..7ede6fd
--- /dev/null
+++ b/src/util.h
@@ -0,0 +1,24 @@
1#pragma once
2
3#include <stdarg.h>
4#include <stdio.h>
5#include <stdlib.h>
6
7static void
8error(const char *msg, ...)
9{
10 va_list ap;
11
12 va_start(ap, msg);
13 fprintf(stderr, "Error: ");
14 vfprintf(stderr, msg, ap);
15 va_end(ap);
16 fprintf(stderr, "\n");
17 exit(EXIT_FAILURE);
18}
19
20#define ERROR(msg) error(msg " in \"%s()\" (%s:%d)", __func__, __FILE__, __LINE__)
21
22#ifndef NELEM
23# define NELEM(x) (sizeof(x) / sizeof(x[0])) /* NOLINT */
24#endif