Systemnahe Programmierung in C: Rot-Schwarz-Bäume |
|
1#ifndef ELEMENT_H__
2#define ELEMENT_H__ 1
3
4typedef int Element;
5
6extern int compare(Element e1,
7 Element e2);
8
9#endif
|
1#include "Element.h"
2
3int
4compare(Element e1, Element e2)
5{
6 return (e1 >= e2) - (e2 >= e1);
7}
|
1#ifndef SET_H__
2#define SET_H__
3
4/*--------------------*/
5
6#include "Element.h"
7
8typedef struct Node *Set;
9
10struct Node
11{
12 enum
13 { RED, BLACK } color;
14 Element info;
15 Set l;
16 Set r;
17};
18
19/*--------------------*/
20
21extern Set mkEmptySet(void);
22extern int isEmptySet(Set s);
23
24extern Set mkOneElemSet(Element e);
25extern Set insertElem(Element e, Set s);
26
27extern int isInSet(Element e, Set s);
28
29extern unsigned int card(Set s);
30
31extern unsigned int maxPathLength(Set
32 s);
33extern unsigned int minPathLength(Set
34 s);
35
36extern int invSetAsRedBlackTree(Set s);
37
38/*--------------------*/
39
40#endif
|
1#include "Set.h"
2
3#include <stdlib.h>
4#include <stdio.h>
5#include <assert.h>
6
7/*--------------------*/
8
9/* special empty node, marked as black */
10
11static struct Node finalNode = { BLACK };
12
13Set
14mkEmptySet(void)
15{
16 return &finalNode;
17}
18
19/* local optimization */
20
21#define mkEmptySet() (&finalNode)
22
23/*--------------------*/
24
25int
26isEmptySet(Set s)
27{
28 return s == &finalNode;
29}
30
31/* local optimization */
32
33#define isEmptySet(s) ((s) == &finalNode)
34
35/*--------------------*/
36
37/* auxiliary function: file scope */
38
39static Set
40mkNewRedNode(Element e)
41{
42 Set res = malloc(sizeof(*res));
43
44 if (!res)
45 {
46 perror
47 ("mkNewNode: malloc failed");
48 exit(1);
49 }
50
51 res->color = RED; /* every new node is red */
52 res->info = e;
53 res->l = mkEmptySet();
54 res->r = mkEmptySet();
55
56 return res;
57}
58
59/*--------------------*/
60
61Set
62mkOneElemSet(Element e)
63{
64 return insertElem(e, mkEmptySet());
65}
66
67/*--------------------*/
68
69int
70isInSet(Element e, Set s)
71{
72 if (isEmptySet(s))
73 return 0;
74
75 switch (compare(e, s->info))
76 {
77 case -1:
78 return isInSet(e, s->l);
79 case 0:
80 return 1;
81 case +1:
82 return isInSet(e, s->r);
83 }
84
85 assert(0);
86 return 0;
87}
88
89/*--------------------*/
90
91/* color predicates */
92
93#define isBlackNode(s) ((s)->color == BLACK)
94#define isRedNode(s) (! isBlackNode(s))
95
96static int
97hasRedChild(Set s)
98{
99 return
100 ! isEmptySet(s)
101 && (isRedNode(s->l)
102 ||
103 isRedNode(s->r));
104}
105
106/*--------------------*/
107
108/* reorganize tree */
109
110static Set
111balanceTrees(Set x, Set y, Set z,
112 Set b, Set c)
113{
114 x->r = b;
115 z->l = c;
116
117 y->l = x;
118 y->r = z;
119
120 x->color = BLACK;
121 z->color = BLACK;
122 y->color = RED;
123
124 return y;
125}
126
127/* check invariant */
128
129/* check balance in left subtree */
130
131static Set
132checkBalanceLeft(Set s)
133{
134 assert(!isEmptySet(s));
135
136 /* no balancing of trees with red root */
137
138 if (isRedNode(s))
139 return s;
140
141 if (isRedNode(s->l)
142 && isRedNode(s->l->l))
143 return balanceTrees(s->l->l,
144 s->l,
145 s,
146 s->l->l->r,
147 s->l->r);
148
149 if (isRedNode(s->l)
150 && isRedNode(s->l->r))
151 return balanceTrees(s->l,
152 s->l->r,
153 s,
154 s->l->r->l,
155 s->l->r->r);
156
157 return s;
158}
159
160/* check balance in right subtree */
161
162static Set
163checkBalanceRight(Set s)
164{
165 assert(!isEmptySet(s));
166
167 /* no balancing of trees with red root */
168
169 if (isRedNode(s))
170 return s;
171
172 if (isRedNode(s->r)
173 && isRedNode(s->r->l))
174 return balanceTrees(s,
175 s->r->l,
176 s->r,
177 s->r->l->l,
178 s->r->l->r);
179
180 if (isRedNode(s->r)
181 && isRedNode(s->r->r))
182 return balanceTrees(s,
183 s->r,
184 s->r->r,
185 s->r->l,
186 s->r->r->l);
187
188 return s;
189}
190
191/*--------------------*/
192
193static Set
194insertElem1(Element e, Set s)
195{
196 if (isEmptySet(s))
197 return mkNewRedNode(e);
198
199 switch (compare(e, s->info))
200 {
201 case -1:
202 s->l = insertElem1(e, s->l);
203
204 /* invariant is checked with left subtree */
205 return checkBalanceLeft(s);
206
207 case 0:
208 break;
209
210 case +1:
211 s->r = insertElem1(e, s->r);
212
213 /* invariant is checked with right subtree */
214 return checkBalanceRight(s);
215 }
216
217 return s;
218}
219
220/*--------------------*/
221
222Set
223insertElem(Element e, Set s)
224{
225 Set res = insertElem1(e, s);
226
227 /* the root is always black */
228
229 res->color = BLACK;
230
231 assert(invSetAsRedBlackTree(res));
232
233 return res;
234}
235
236/*--------------------*/
237
238static int
239lessThan(Set s, Element e)
240{
241 return
242 isEmptySet(s)
243 || (compare(s->info, e) == -1
244 && lessThan(s->r, e));
245
246}
247
248/*--------------------*/
249
250static int
251greaterThan(Set s, Element e)
252{
253 return
254 isEmptySet(s)
255 || (
256 compare(s->info, e) == +1
257 &&
258 greaterThan(s->l, e));
259}
260
261/*--------------------*/
262
263static int
264invSetAsBinTree(Set s)
265{
266 return
267 isEmptySet(s)
268 || (
269 lessThan(s->l, s->info)
270 &&
271 greaterThan(s->r, s->info)
272 &&
273 invSetAsBinTree(s->l)
274 &&
275 invSetAsBinTree(s->r));
276}
277
278/*--------------------*/
279
280static int
281invNoRedNodeHasRedChild(Set s)
282{
283 if (isEmptySet(s))
284 return 1;
285
286 return
287 (isBlackNode(s)
288 ||
289 ! hasRedChild(s)
290 )
291 &&
292 invNoRedNodeHasRedChild(s->l)
293 &&
294 invNoRedNodeHasRedChild(s->r);
295}
296
297/*--------------------*/
298
299static int
300noOfBlackNodes(Set s)
301{
302 if (isEmptySet(s))
303 return 1;
304
305 {
306 int nl = noOfBlackNodes(s->l);
307 int nr = noOfBlackNodes(s->r);
308
309 if (nl == nr && nl != -1)
310 return nl + isBlackNode(s);
311
312 /* invariant does not hold */
313 return -1;
314 }
315}
316
317/*--------------------*/
318
319int
320invSetAsRedBlackTree(Set s)
321{
322 return
323 invSetAsBinTree(s)
324 &&
325 invNoRedNodeHasRedChild(s)
326 &&
327 noOfBlackNodes(s) != -1;
328}
329
330/*--------------------*/
331
332unsigned int
333card(Set s)
334{
335 if (isEmptySet(s))
336 return 0;
337
338 return card(s->l) + 1 + card(s->r);
339}
340
341/*--------------------*/
342
343static unsigned int
344max(unsigned int i, unsigned int j)
345{
346 return i > j ? i : j;
347}
348
349/*--------------------*/
350
351static unsigned int
352min(unsigned int i, unsigned int j)
353{
354 return i < j ? i : j;
355}
356
357/*--------------------*/
358
359unsigned int
360maxPathLength(Set s)
361{
362 if (isEmptySet(s))
363 return 0;
364
365 return
366 1 + max(maxPathLength(s->l),
367 maxPathLength(s->r));
368}
369
370/*--------------------*/
371
372unsigned int
373minPathLength(Set s)
374{
375 if (isEmptySet(s))
376 return 0;
377
378 return
379 1 + min(minPathLength(s->l),
380 minPathLength(s->r));
381}
382
383/*--------------------*/
|
1#include <stdio.h>
2#include <assert.h>
3
4#include "Element.h"
5#include "Set.h"
6
7int
8main(int argc, char *argv[])
9{
10 unsigned int noOfElems = 1000;
11
12 if (argc == 2)
13 sscanf(argv[1], "%u", &noOfElems);
14
15 fprintf(stderr,
16 "%s %u %s",
17 "run red black trees with inserting",
18 noOfElems,
19 "elements in ascending order\n"
20 );
21
22 {
23 Set s = mkEmptySet();
24 unsigned int i;
25
26 for (i = 0; i < noOfElems; ++i)
27 {
28 s = insertElem((Element) i, s);
29 }
30
31 fprintf(stderr,
32 "card(s) = %u\n",
33 card(s));
34 fprintf(stderr,
35 "minPathLength(s) = %u\n",
36 minPathLength(s));
37 fprintf(stderr,
38 "maxPathLength(s) = %u\n",
39 maxPathLength(s));
40 }
41
42 return 0;
43}
|
Letzte Änderung: 19.12.2014 | © Prof. Dr. Uwe Schmidt |