Open Model Railroad Network (OpenMRN)
Loading...
Searching...
No Matches
tree.hxx
1
/* $NetBSD: tree.h,v 1.8 2004/03/28 19:38:30 provos Exp $ */
2
/* $OpenBSD: tree.h,v 1.7 2002/10/17 21:51:54 art Exp $ */
3
/* $FreeBSD: src/sys/sys/tree.h,v 1.7 2007/12/28 07:03:26 jasone Exp $ */
4
5
/*-
6
* Copyright 2002 Niels Provos <provos@citi.umich.edu>
7
* All rights reserved.
8
*
9
* Redistribution and use in source and binary forms, with or without
10
* modification, are permitted provided that the following conditions
11
* are met:
12
* 1. Redistributions of source code must retain the above copyright
13
* notice, this list of conditions and the following disclaimer.
14
* 2. Redistributions in binary form must reproduce the above copyright
15
* notice, this list of conditions and the following disclaimer in the
16
* documentation and/or other materials provided with the distribution.
17
*
18
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
19
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
20
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
21
* IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
22
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
23
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
24
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
25
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
26
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
27
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
28
*/
29
30
#ifndef _SYS_TREE_H_
31
#define _SYS_TREE_H_
32
33
/*
34
* This file defines data structures for different types of trees:
35
* splay trees and red-black trees.
36
*
37
* A splay tree is a self-organizing data structure. Every operation
38
* on the tree causes a splay to happen. The splay moves the requested
39
* node to the root of the tree and partly rebalances it.
40
*
41
* This has the benefit that request locality causes faster lookups as
42
* the requested nodes move to the top of the tree. On the other hand,
43
* every lookup causes memory writes.
44
*
45
* The Balance Theorem bounds the total access time for m operations
46
* and n inserts on an initially empty tree as O((m + n)lg n). The
47
* amortized cost for a sequence of m accesses to a splay tree is O(lg n);
48
*
49
* A red-black tree is a binary search tree with the node color as an
50
* extra attribute. It fulfills a set of conditions:
51
* - every search path from the root to a leaf consists of the
52
* same number of black nodes,
53
* - each red node (except for the root) has a black parent,
54
* - each leaf node is black.
55
*
56
* Every operation on a red-black tree is bounded as O(lg n).
57
* The maximum height of a red-black tree is 2lg (n+1).
58
*/
59
60
#define SPLAY_HEAD(name, type) \
61
struct name { \
62
struct type *sph_root;
/* root of the tree */
\
63
}
64
65
#define SPLAY_INITIALIZER(root) \
66
{ NULL }
67
68
#define SPLAY_INIT(root) do { \
69
(root)->sph_root = NULL; \
70
} while (
/*CONSTCOND*/
0)
71
72
#define SPLAY_ENTRY(type) \
73
struct { \
74
struct type *spe_left;
/* left element */
\
75
struct type *spe_right;
/* right element */
\
76
}
77
78
#define SPLAY_LEFT(elm, field) (elm)->field.spe_left
79
#define SPLAY_RIGHT(elm, field) (elm)->field.spe_right
80
#define SPLAY_ROOT(head) (head)->sph_root
81
#define SPLAY_EMPTY(head) (SPLAY_ROOT(head) == NULL)
82
83
/* SPLAY_ROTATE_{LEFT,RIGHT} expect that tmp hold SPLAY_{RIGHT,LEFT} */
84
#define SPLAY_ROTATE_RIGHT(head, tmp, field) do { \
85
SPLAY_LEFT((head)->sph_root, field) = SPLAY_RIGHT(tmp, field); \
86
SPLAY_RIGHT(tmp, field) = (head)->sph_root; \
87
(head)->sph_root = tmp; \
88
} while (
/*CONSTCOND*/
0)
89
90
#define SPLAY_ROTATE_LEFT(head, tmp, field) do { \
91
SPLAY_RIGHT((head)->sph_root, field) = SPLAY_LEFT(tmp, field); \
92
SPLAY_LEFT(tmp, field) = (head)->sph_root; \
93
(head)->sph_root = tmp; \
94
} while (
/*CONSTCOND*/
0)
95
96
#define SPLAY_LINKLEFT(head, tmp, field) do { \
97
SPLAY_LEFT(tmp, field) = (head)->sph_root; \
98
tmp = (head)->sph_root; \
99
(head)->sph_root = SPLAY_LEFT((head)->sph_root, field); \
100
} while (
/*CONSTCOND*/
0)
101
102
#define SPLAY_LINKRIGHT(head, tmp, field) do { \
103
SPLAY_RIGHT(tmp, field) = (head)->sph_root; \
104
tmp = (head)->sph_root; \
105
(head)->sph_root = SPLAY_RIGHT((head)->sph_root, field); \
106
} while (
/*CONSTCOND*/
0)
107
108
#define SPLAY_ASSEMBLE(head, node, left, right, field) do { \
109
SPLAY_RIGHT(left, field) = SPLAY_LEFT((head)->sph_root, field); \
110
SPLAY_LEFT(right, field) = SPLAY_RIGHT((head)->sph_root, field);\
111
SPLAY_LEFT((head)->sph_root, field) = SPLAY_RIGHT(node, field); \
112
SPLAY_RIGHT((head)->sph_root, field) = SPLAY_LEFT(node, field); \
113
} while (
/*CONSTCOND*/
0)
114
115
/* Generates prototypes and inline functions */
116
117
#define SPLAY_PROTOTYPE(name, type, field, cmp) \
118
void name##_SPLAY(struct name *, struct type *); \
119
void name##_SPLAY_MINMAX(struct name *, int); \
120
struct type *name##_SPLAY_INSERT(struct name *, struct type *); \
121
struct type *name##_SPLAY_REMOVE(struct name *, struct type *); \
122
\
123
/* Finds the node with the same key as elm */
\
124
static __inline struct type * \
125
name##_SPLAY_FIND(struct name *head, struct type *elm) \
126
{ \
127
if (SPLAY_EMPTY(head)) \
128
return(NULL); \
129
name##_SPLAY(head, elm); \
130
if ((cmp)(elm, (head)->sph_root) == 0) \
131
return (head->sph_root); \
132
return (NULL); \
133
} \
134
\
135
static __inline struct type * \
136
name##_SPLAY_NEXT(struct name *head, struct type *elm) \
137
{ \
138
name##_SPLAY(head, elm); \
139
if (SPLAY_RIGHT(elm, field) != NULL) { \
140
elm = SPLAY_RIGHT(elm, field); \
141
while (SPLAY_LEFT(elm, field) != NULL) { \
142
elm = SPLAY_LEFT(elm, field); \
143
} \
144
} else \
145
elm = NULL; \
146
return (elm); \
147
} \
148
\
149
static __inline struct type * \
150
name##_SPLAY_MIN_MAX(struct name *head, int val) \
151
{ \
152
name##_SPLAY_MINMAX(head, val); \
153
return (SPLAY_ROOT(head)); \
154
}
155
156
/* Main splay operation.
157
* Moves node close to the key of elm to top
158
*/
159
#define SPLAY_GENERATE(name, type, field, cmp) \
160
struct type * \
161
name##_SPLAY_INSERT(struct name *head, struct type *elm) \
162
{ \
163
if (SPLAY_EMPTY(head)) { \
164
SPLAY_LEFT(elm, field) = SPLAY_RIGHT(elm, field) = NULL; \
165
} else { \
166
int __comp; \
167
name##_SPLAY(head, elm); \
168
__comp = (cmp)(elm, (head)->sph_root); \
169
if(__comp < 0) { \
170
SPLAY_LEFT(elm, field) = SPLAY_LEFT((head)->sph_root, field);\
171
SPLAY_RIGHT(elm, field) = (head)->sph_root; \
172
SPLAY_LEFT((head)->sph_root, field) = NULL; \
173
} else if (__comp > 0) { \
174
SPLAY_RIGHT(elm, field) = SPLAY_RIGHT((head)->sph_root, field);\
175
SPLAY_LEFT(elm, field) = (head)->sph_root; \
176
SPLAY_RIGHT((head)->sph_root, field) = NULL; \
177
} else \
178
return ((head)->sph_root); \
179
} \
180
(head)->sph_root = (elm); \
181
return (NULL); \
182
} \
183
\
184
struct type * \
185
name##_SPLAY_REMOVE(struct name *head, struct type *elm) \
186
{ \
187
struct type *__tmp; \
188
if (SPLAY_EMPTY(head)) \
189
return (NULL); \
190
name##_SPLAY(head, elm); \
191
if ((cmp)(elm, (head)->sph_root) == 0) { \
192
if (SPLAY_LEFT((head)->sph_root, field) == NULL) { \
193
(head)->sph_root = SPLAY_RIGHT((head)->sph_root, field);\
194
} else { \
195
__tmp = SPLAY_RIGHT((head)->sph_root, field); \
196
(head)->sph_root = SPLAY_LEFT((head)->sph_root, field);\
197
name##_SPLAY(head, elm); \
198
SPLAY_RIGHT((head)->sph_root, field) = __tmp; \
199
} \
200
return (elm); \
201
} \
202
return (NULL); \
203
} \
204
\
205
void \
206
name##_SPLAY(struct name *head, struct type *elm) \
207
{ \
208
struct type __node, *__left, *__right, *__tmp; \
209
int __comp; \
210
\
211
SPLAY_LEFT(&__node, field) = SPLAY_RIGHT(&__node, field) = NULL;\
212
__left = __right = &__node; \
213
\
214
while ((__comp = (cmp)(elm, (head)->sph_root)) != 0) { \
215
if (__comp < 0) { \
216
__tmp = SPLAY_LEFT((head)->sph_root, field); \
217
if (__tmp == NULL) \
218
break; \
219
if ((cmp)(elm, __tmp) < 0){ \
220
SPLAY_ROTATE_RIGHT(head, __tmp, field); \
221
if (SPLAY_LEFT((head)->sph_root, field) == NULL)\
222
break; \
223
} \
224
SPLAY_LINKLEFT(head, __right, field); \
225
} else if (__comp > 0) { \
226
__tmp = SPLAY_RIGHT((head)->sph_root, field); \
227
if (__tmp == NULL) \
228
break; \
229
if ((cmp)(elm, __tmp) > 0){ \
230
SPLAY_ROTATE_LEFT(head, __tmp, field); \
231
if (SPLAY_RIGHT((head)->sph_root, field) == NULL)\
232
break; \
233
} \
234
SPLAY_LINKRIGHT(head, __left, field); \
235
} \
236
} \
237
SPLAY_ASSEMBLE(head, &__node, __left, __right, field); \
238
} \
239
\
240
/* Splay with either the minimum or the maximum element \
241
* Used to find minimum or maximum element in tree. \
242
*/
\
243
void name##_SPLAY_MINMAX(struct name *head, int __comp) \
244
{ \
245
struct type __node, *__left, *__right, *__tmp; \
246
\
247
SPLAY_LEFT(&__node, field) = SPLAY_RIGHT(&__node, field) = NULL;\
248
__left = __right = &__node; \
249
\
250
while (1) { \
251
if (__comp < 0) { \
252
__tmp = SPLAY_LEFT((head)->sph_root, field); \
253
if (__tmp == NULL) \
254
break; \
255
if (__comp < 0){ \
256
SPLAY_ROTATE_RIGHT(head, __tmp, field); \
257
if (SPLAY_LEFT((head)->sph_root, field) == NULL)\
258
break; \
259
} \
260
SPLAY_LINKLEFT(head, __right, field); \
261
} else if (__comp > 0) { \
262
__tmp = SPLAY_RIGHT((head)->sph_root, field); \
263
if (__tmp == NULL) \
264
break; \
265
if (__comp > 0) { \
266
SPLAY_ROTATE_LEFT(head, __tmp, field); \
267
if (SPLAY_RIGHT((head)->sph_root, field) == NULL)\
268
break; \
269
} \
270
SPLAY_LINKRIGHT(head, __left, field); \
271
} \
272
} \
273
SPLAY_ASSEMBLE(head, &__node, __left, __right, field); \
274
}
275
276
#define SPLAY_NEGINF -1
277
#define SPLAY_INF 1
278
279
#define SPLAY_INSERT(name, x, y) name##_SPLAY_INSERT(x, y)
280
#define SPLAY_REMOVE(name, x, y) name##_SPLAY_REMOVE(x, y)
281
#define SPLAY_FIND(name, x, y) name##_SPLAY_FIND(x, y)
282
#define SPLAY_NEXT(name, x, y) name##_SPLAY_NEXT(x, y)
283
#define SPLAY_MIN(name, x) (SPLAY_EMPTY(x) ? NULL \
284
: name##_SPLAY_MIN_MAX(x, SPLAY_NEGINF))
285
#define SPLAY_MAX(name, x) (SPLAY_EMPTY(x) ? NULL \
286
: name##_SPLAY_MIN_MAX(x, SPLAY_INF))
287
288
#define SPLAY_FOREACH(x, name, head) \
289
for ((x) = SPLAY_MIN(name, head); \
290
(x) != NULL; \
291
(x) = SPLAY_NEXT(name, head, x))
292
293
/* Macros that define a red-black tree */
294
#define RB_HEAD(name, type) \
295
struct name { \
296
struct type *rbh_root;
/* root of the tree */
\
297
}
298
299
#define RB_INITIALIZER(root) \
300
{ NULL }
301
302
#define RB_INIT(root) do { \
303
(root)->rbh_root = NULL; \
304
} while (
/*CONSTCOND*/
0)
305
306
#define RB_BLACK 0
307
#define RB_RED 1
308
#define RB_ENTRY(type) \
309
struct { \
310
struct type *rbe_left;
/* left element */
\
311
struct type *rbe_right;
/* right element */
\
312
struct type *rbe_parent;
/* parent element */
\
313
int rbe_color;
/* node color */
\
314
}
315
316
#define RB_LEFT(elm, field) (elm)->field.rbe_left
317
#define RB_RIGHT(elm, field) (elm)->field.rbe_right
318
#define RB_PARENT(elm, field) (elm)->field.rbe_parent
319
#define RB_COLOR(elm, field) (elm)->field.rbe_color
320
#define RB_ROOT(head) (head)->rbh_root
321
#define RB_EMPTY(head) (RB_ROOT(head) == NULL)
322
323
#define RB_SET(elm, parent, field) do { \
324
RB_PARENT(elm, field) = parent; \
325
RB_LEFT(elm, field) = RB_RIGHT(elm, field) = NULL; \
326
RB_COLOR(elm, field) = RB_RED; \
327
} while (
/*CONSTCOND*/
0)
328
329
#define RB_SET_BLACKRED(black, red, field) do { \
330
RB_COLOR(black, field) = RB_BLACK; \
331
RB_COLOR(red, field) = RB_RED; \
332
} while (
/*CONSTCOND*/
0)
333
334
#ifndef RB_AUGMENT
335
#define RB_AUGMENT(x) do {} while (0)
336
#endif
337
338
#define RB_ROTATE_LEFT(head, elm, tmp, field) do { \
339
(tmp) = RB_RIGHT(elm, field); \
340
if ((RB_RIGHT(elm, field) = RB_LEFT(tmp, field)) != NULL) { \
341
RB_PARENT(RB_LEFT(tmp, field), field) = (elm); \
342
} \
343
RB_AUGMENT(elm); \
344
if ((RB_PARENT(tmp, field) = RB_PARENT(elm, field)) != NULL) { \
345
if ((elm) == RB_LEFT(RB_PARENT(elm, field), field)) \
346
RB_LEFT(RB_PARENT(elm, field), field) = (tmp); \
347
else \
348
RB_RIGHT(RB_PARENT(elm, field), field) = (tmp); \
349
} else \
350
(head)->rbh_root = (tmp); \
351
RB_LEFT(tmp, field) = (elm); \
352
RB_PARENT(elm, field) = (tmp); \
353
RB_AUGMENT(tmp); \
354
if ((RB_PARENT(tmp, field))) \
355
RB_AUGMENT(RB_PARENT(tmp, field)); \
356
} while (
/*CONSTCOND*/
0)
357
358
#define RB_ROTATE_RIGHT(head, elm, tmp, field) do { \
359
(tmp) = RB_LEFT(elm, field); \
360
if ((RB_LEFT(elm, field) = RB_RIGHT(tmp, field)) != NULL) { \
361
RB_PARENT(RB_RIGHT(tmp, field), field) = (elm); \
362
} \
363
RB_AUGMENT(elm); \
364
if ((RB_PARENT(tmp, field) = RB_PARENT(elm, field)) != NULL) { \
365
if ((elm) == RB_LEFT(RB_PARENT(elm, field), field)) \
366
RB_LEFT(RB_PARENT(elm, field), field) = (tmp); \
367
else \
368
RB_RIGHT(RB_PARENT(elm, field), field) = (tmp); \
369
} else \
370
(head)->rbh_root = (tmp); \
371
RB_RIGHT(tmp, field) = (elm); \
372
RB_PARENT(elm, field) = (tmp); \
373
RB_AUGMENT(tmp); \
374
if ((RB_PARENT(tmp, field))) \
375
RB_AUGMENT(RB_PARENT(tmp, field)); \
376
} while (
/*CONSTCOND*/
0)
377
378
/* Generates prototypes and inline functions */
379
#define RB_PROTOTYPE(name, type, field, cmp) \
380
RB_PROTOTYPE_INTERNAL(name, type, field, cmp,)
381
#define RB_PROTOTYPE_STATIC(name, type, field, cmp) \
382
RB_PROTOTYPE_INTERNAL(name, type, field, cmp, __unused static)
383
#define RB_PROTOTYPE_INTERNAL(name, type, field, cmp, attr) \
384
attr void name##_RB_INSERT_COLOR(struct name *, struct type *); \
385
attr void name##_RB_REMOVE_COLOR(struct name *, struct type *, struct type *);\
386
attr struct type *name##_RB_REMOVE(struct name *, struct type *) __attribute__ ((unused)); \
387
attr struct type *name##_RB_INSERT(struct name *, struct type *); \
388
attr struct type *name##_RB_FIND(struct name *, struct type *); \
389
attr struct type *name##_RB_NFIND(struct name *, struct type *) __attribute__ ((unused)); \
390
attr struct type *name##_RB_NEXT(struct type *) __attribute__ ((unused)); \
391
attr struct type *name##_RB_PREV(struct type *) __attribute__ ((unused)); \
392
attr struct type *name##_RB_MINMAX(struct name *, int) __attribute__ ((unused)); \
393
\
394
395
/* Main rb operation.
396
* Moves node close to the key of elm to top
397
*/
398
#define RB_GENERATE(name, type, field, cmp) \
399
RB_GENERATE_INTERNAL(name, type, field, cmp,)
400
#define RB_GENERATE_STATIC(name, type, field, cmp) \
401
RB_GENERATE_INTERNAL(name, type, field, cmp, static)
402
#define RB_GENERATE_INTERNAL(name, type, field, cmp, attr) \
403
attr void \
404
name##_RB_INSERT_COLOR(struct name *head, struct type *elm) \
405
{ \
406
struct type *parent, *gparent, *tmp; \
407
while ((parent = RB_PARENT(elm, field)) != NULL && \
408
RB_COLOR(parent, field) == RB_RED) { \
409
gparent = RB_PARENT(parent, field); \
410
if (parent == RB_LEFT(gparent, field)) { \
411
tmp = RB_RIGHT(gparent, field); \
412
if (tmp && RB_COLOR(tmp, field) == RB_RED) { \
413
RB_COLOR(tmp, field) = RB_BLACK; \
414
RB_SET_BLACKRED(parent, gparent, field);\
415
elm = gparent; \
416
continue; \
417
} \
418
if (RB_RIGHT(parent, field) == elm) { \
419
RB_ROTATE_LEFT(head, parent, tmp, field);\
420
tmp = parent; \
421
parent = elm; \
422
elm = tmp; \
423
} \
424
RB_SET_BLACKRED(parent, gparent, field); \
425
RB_ROTATE_RIGHT(head, gparent, tmp, field); \
426
} else { \
427
tmp = RB_LEFT(gparent, field); \
428
if (tmp && RB_COLOR(tmp, field) == RB_RED) { \
429
RB_COLOR(tmp, field) = RB_BLACK; \
430
RB_SET_BLACKRED(parent, gparent, field);\
431
elm = gparent; \
432
continue; \
433
} \
434
if (RB_LEFT(parent, field) == elm) { \
435
RB_ROTATE_RIGHT(head, parent, tmp, field);\
436
tmp = parent; \
437
parent = elm; \
438
elm = tmp; \
439
} \
440
RB_SET_BLACKRED(parent, gparent, field); \
441
RB_ROTATE_LEFT(head, gparent, tmp, field); \
442
} \
443
} \
444
RB_COLOR(head->rbh_root, field) = RB_BLACK; \
445
} \
446
\
447
attr void \
448
name##_RB_REMOVE_COLOR(struct name *head, struct type *parent, struct type *elm) \
449
{ \
450
struct type *tmp; \
451
while ((elm == NULL || RB_COLOR(elm, field) == RB_BLACK) && \
452
elm != RB_ROOT(head)) { \
453
if (RB_LEFT(parent, field) == elm) { \
454
tmp = RB_RIGHT(parent, field); \
455
if (RB_COLOR(tmp, field) == RB_RED) { \
456
RB_SET_BLACKRED(tmp, parent, field); \
457
RB_ROTATE_LEFT(head, parent, tmp, field);\
458
tmp = RB_RIGHT(parent, field); \
459
} \
460
if ((RB_LEFT(tmp, field) == NULL || \
461
RB_COLOR(RB_LEFT(tmp, field), field) == RB_BLACK) &&\
462
(RB_RIGHT(tmp, field) == NULL || \
463
RB_COLOR(RB_RIGHT(tmp, field), field) == RB_BLACK)) {\
464
RB_COLOR(tmp, field) = RB_RED; \
465
elm = parent; \
466
parent = RB_PARENT(elm, field); \
467
} else { \
468
if (RB_RIGHT(tmp, field) == NULL || \
469
RB_COLOR(RB_RIGHT(tmp, field), field) == RB_BLACK) {\
470
struct type *oleft; \
471
if ((oleft = RB_LEFT(tmp, field)) \
472
!= NULL) \
473
RB_COLOR(oleft, field) = RB_BLACK;\
474
RB_COLOR(tmp, field) = RB_RED; \
475
RB_ROTATE_RIGHT(head, tmp, oleft, field);\
476
tmp = RB_RIGHT(parent, field); \
477
} \
478
RB_COLOR(tmp, field) = RB_COLOR(parent, field);\
479
RB_COLOR(parent, field) = RB_BLACK; \
480
if (RB_RIGHT(tmp, field)) \
481
RB_COLOR(RB_RIGHT(tmp, field), field) = RB_BLACK;\
482
RB_ROTATE_LEFT(head, parent, tmp, field);\
483
elm = RB_ROOT(head); \
484
break; \
485
} \
486
} else { \
487
tmp = RB_LEFT(parent, field); \
488
if (RB_COLOR(tmp, field) == RB_RED) { \
489
RB_SET_BLACKRED(tmp, parent, field); \
490
RB_ROTATE_RIGHT(head, parent, tmp, field);\
491
tmp = RB_LEFT(parent, field); \
492
} \
493
if ((RB_LEFT(tmp, field) == NULL || \
494
RB_COLOR(RB_LEFT(tmp, field), field) == RB_BLACK) &&\
495
(RB_RIGHT(tmp, field) == NULL || \
496
RB_COLOR(RB_RIGHT(tmp, field), field) == RB_BLACK)) {\
497
RB_COLOR(tmp, field) = RB_RED; \
498
elm = parent; \
499
parent = RB_PARENT(elm, field); \
500
} else { \
501
if (RB_LEFT(tmp, field) == NULL || \
502
RB_COLOR(RB_LEFT(tmp, field), field) == RB_BLACK) {\
503
struct type *oright; \
504
if ((oright = RB_RIGHT(tmp, field)) \
505
!= NULL) \
506
RB_COLOR(oright, field) = RB_BLACK;\
507
RB_COLOR(tmp, field) = RB_RED; \
508
RB_ROTATE_LEFT(head, tmp, oright, field);\
509
tmp = RB_LEFT(parent, field); \
510
} \
511
RB_COLOR(tmp, field) = RB_COLOR(parent, field);\
512
RB_COLOR(parent, field) = RB_BLACK; \
513
if (RB_LEFT(tmp, field)) \
514
RB_COLOR(RB_LEFT(tmp, field), field) = RB_BLACK;\
515
RB_ROTATE_RIGHT(head, parent, tmp, field);\
516
elm = RB_ROOT(head); \
517
break; \
518
} \
519
} \
520
} \
521
if (elm) \
522
RB_COLOR(elm, field) = RB_BLACK; \
523
} \
524
\
525
attr struct type * \
526
name##_RB_REMOVE(struct name *head, struct type *elm) \
527
{ \
528
struct type *child, *parent, *old = elm; \
529
int color; \
530
if (RB_LEFT(elm, field) == NULL) \
531
child = RB_RIGHT(elm, field); \
532
else if (RB_RIGHT(elm, field) == NULL) \
533
child = RB_LEFT(elm, field); \
534
else { \
535
struct type *left; \
536
elm = RB_RIGHT(elm, field); \
537
while ((left = RB_LEFT(elm, field)) != NULL) \
538
elm = left; \
539
child = RB_RIGHT(elm, field); \
540
parent = RB_PARENT(elm, field); \
541
color = RB_COLOR(elm, field); \
542
if (child) \
543
RB_PARENT(child, field) = parent; \
544
if (parent) { \
545
if (RB_LEFT(parent, field) == elm) \
546
RB_LEFT(parent, field) = child; \
547
else \
548
RB_RIGHT(parent, field) = child; \
549
RB_AUGMENT(parent); \
550
} else \
551
RB_ROOT(head) = child; \
552
if (RB_PARENT(elm, field) == old) \
553
parent = elm; \
554
(elm)->field = (old)->field; \
555
if (RB_PARENT(old, field)) { \
556
if (RB_LEFT(RB_PARENT(old, field), field) == old)\
557
RB_LEFT(RB_PARENT(old, field), field) = elm;\
558
else \
559
RB_RIGHT(RB_PARENT(old, field), field) = elm;\
560
RB_AUGMENT(RB_PARENT(old, field)); \
561
} else \
562
RB_ROOT(head) = elm; \
563
RB_PARENT(RB_LEFT(old, field), field) = elm; \
564
if (RB_RIGHT(old, field)) \
565
RB_PARENT(RB_RIGHT(old, field), field) = elm; \
566
if (parent) { \
567
left = parent; \
568
do { \
569
RB_AUGMENT(left); \
570
} while ((left = RB_PARENT(left, field)) != NULL); \
571
} \
572
goto color; \
573
} \
574
parent = RB_PARENT(elm, field); \
575
color = RB_COLOR(elm, field); \
576
if (child) \
577
RB_PARENT(child, field) = parent; \
578
if (parent) { \
579
if (RB_LEFT(parent, field) == elm) \
580
RB_LEFT(parent, field) = child; \
581
else \
582
RB_RIGHT(parent, field) = child; \
583
RB_AUGMENT(parent); \
584
} else \
585
RB_ROOT(head) = child; \
586
color: \
587
if (color == RB_BLACK) \
588
name##_RB_REMOVE_COLOR(head, parent, child); \
589
return (old); \
590
} \
591
\
592
/* Inserts a node into the RB tree */
\
593
attr struct type * \
594
name##_RB_INSERT(struct name *head, struct type *elm) \
595
{ \
596
struct type *tmp; \
597
struct type *parent = NULL; \
598
int64_t comp = 0; \
599
tmp = RB_ROOT(head); \
600
while (tmp) { \
601
parent = tmp; \
602
comp = (cmp)(elm, parent); \
603
if (comp < 0) \
604
tmp = RB_LEFT(tmp, field); \
605
else if (comp > 0) \
606
tmp = RB_RIGHT(tmp, field); \
607
else \
608
return (tmp); \
609
} \
610
RB_SET(elm, parent, field); \
611
if (parent != NULL) { \
612
if (comp < 0) \
613
RB_LEFT(parent, field) = elm; \
614
else \
615
RB_RIGHT(parent, field) = elm; \
616
RB_AUGMENT(parent); \
617
} else \
618
RB_ROOT(head) = elm; \
619
name##_RB_INSERT_COLOR(head, elm); \
620
return (NULL); \
621
} \
622
\
623
/* Finds the node with the same key as elm */
\
624
attr struct type * \
625
name##_RB_FIND(struct name *head, struct type *elm) \
626
{ \
627
struct type *tmp = RB_ROOT(head); \
628
int64_t comp; \
629
while (tmp) { \
630
comp = cmp(elm, tmp); \
631
if (comp < 0) \
632
tmp = RB_LEFT(tmp, field); \
633
else if (comp > 0) \
634
tmp = RB_RIGHT(tmp, field); \
635
else \
636
return (tmp); \
637
} \
638
return (NULL); \
639
} \
640
\
641
/* Finds the first node greater than or equal to the search key */
\
642
attr struct type * \
643
name##_RB_NFIND(struct name *head, struct type *elm) \
644
{ \
645
struct type *tmp = RB_ROOT(head); \
646
struct type *res = NULL; \
647
int64_t comp; \
648
while (tmp) { \
649
comp = cmp(elm, tmp); \
650
if (comp < 0) { \
651
res = tmp; \
652
tmp = RB_LEFT(tmp, field); \
653
} \
654
else if (comp > 0) \
655
tmp = RB_RIGHT(tmp, field); \
656
else \
657
return (tmp); \
658
} \
659
return (res); \
660
} \
661
\
662
/* ARGSUSED */
\
663
attr struct type * \
664
name##_RB_NEXT(struct type *elm) \
665
{ \
666
if (RB_RIGHT(elm, field)) { \
667
elm = RB_RIGHT(elm, field); \
668
while (RB_LEFT(elm, field)) \
669
elm = RB_LEFT(elm, field); \
670
} else { \
671
if (RB_PARENT(elm, field) && \
672
(elm == RB_LEFT(RB_PARENT(elm, field), field))) \
673
elm = RB_PARENT(elm, field); \
674
else { \
675
while (RB_PARENT(elm, field) && \
676
(elm == RB_RIGHT(RB_PARENT(elm, field), field)))\
677
elm = RB_PARENT(elm, field); \
678
elm = RB_PARENT(elm, field); \
679
} \
680
} \
681
return (elm); \
682
} \
683
\
684
/* ARGSUSED */
\
685
attr struct type * \
686
name##_RB_PREV(struct type *elm) \
687
{ \
688
if (RB_LEFT(elm, field)) { \
689
elm = RB_LEFT(elm, field); \
690
while (RB_RIGHT(elm, field)) \
691
elm = RB_RIGHT(elm, field); \
692
} else { \
693
if (RB_PARENT(elm, field) && \
694
(elm == RB_RIGHT(RB_PARENT(elm, field), field))) \
695
elm = RB_PARENT(elm, field); \
696
else { \
697
while (RB_PARENT(elm, field) && \
698
(elm == RB_LEFT(RB_PARENT(elm, field), field)))\
699
elm = RB_PARENT(elm, field); \
700
elm = RB_PARENT(elm, field); \
701
} \
702
} \
703
return (elm); \
704
} \
705
\
706
attr struct type * \
707
name##_RB_MINMAX(struct name *head, int val) \
708
{ \
709
struct type *tmp = RB_ROOT(head); \
710
struct type *parent = NULL; \
711
while (tmp) { \
712
parent = tmp; \
713
if (val < 0) \
714
tmp = RB_LEFT(tmp, field); \
715
else \
716
tmp = RB_RIGHT(tmp, field); \
717
} \
718
return (parent); \
719
}
720
721
#define RB_NEGINF -1
722
#define RB_INF 1
723
724
#define RB_INSERT(name, x, y) name##_RB_INSERT(x, y)
725
#define RB_REMOVE(name, x, y) name##_RB_REMOVE(x, y)
726
#define RB_FIND(name, x, y) name##_RB_FIND(x, y)
727
#define RB_NFIND(name, x, y) name##_RB_NFIND(x, y)
728
#define RB_NEXT(name, x, y) name##_RB_NEXT(y)
729
#define RB_PREV(name, x, y) name##_RB_PREV(y)
730
#define RB_MIN(name, x) name##_RB_MINMAX(x, RB_NEGINF)
731
#define RB_MAX(name, x) name##_RB_MINMAX(x, RB_INF)
732
733
#define RB_FOREACH(x, name, head) \
734
for ((x) = RB_MIN(name, head); \
735
(x) != NULL; \
736
(x) = name##_RB_NEXT(x))
737
738
#define RB_FOREACH_REVERSE(x, name, head) \
739
for ((x) = RB_MAX(name, head); \
740
(x) != NULL; \
741
(x) = name##_RB_PREV(x))
742
743
#endif
/* _SYS_TREE_H_ */
include
sys
tree.hxx
Generated on Sun Feb 2 2025 21:18:13 for Open Model Railroad Network (OpenMRN) by
1.9.8