Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
freebsd
GitHub Repository: freebsd/pkg
Path: blob/main/external/include/tree.h
2065 views
1
/* tree.h -- AVL trees (in the spirit of BSD's 'queue.h') -*- C -*- */
2
3
/* Copyright (c) 2005 Ian Piumarta
4
*
5
* All rights reserved.
6
*
7
* Permission is hereby granted, free of charge, to any person obtaining a copy
8
* of this software and associated documentation files (the 'Software'), to deal
9
* in the Software without restriction, including without limitation the rights
10
* to use, copy, modify, merge, publish, distribute, and/or sell copies of the
11
* Software, and to permit persons to whom the Software is furnished to do so,
12
* provided that the above copyright notice(s) and this permission notice appear
13
* in all copies of the Software and that both the above copyright notice(s) and
14
* this permission notice appear in supporting documentation.
15
*
16
* THE SOFTWARE IS PROVIDED 'AS IS'. USE ENTIRELY AT YOUR OWN RISK.
17
*/
18
19
/* This file defines an AVL balanced binary tree [Georgii M. Adelson-Velskii and
20
* Evgenii M. Landis, 'An algorithm for the organization of information',
21
* Doklady Akademii Nauk SSSR, 146:263-266, 1962 (Russian). Also in Myron
22
* J. Ricci (trans.), Soviet Math, 3:1259-1263, 1962 (English)].
23
*
24
* An AVL tree is headed by pointers to the root node and to a function defining
25
* the ordering relation between nodes. Each node contains an arbitrary payload
26
* plus three fields per tree entry: the depth of the subtree for which it forms
27
* the root and two pointers to child nodes (singly-linked for minimum space, at
28
* the expense of direct access to the parent node given a pointer to one of the
29
* children). The tree is rebalanced after every insertion or removal. The
30
* tree may be traversed in two directions: forward (in-order left-to-right) and
31
* reverse (in-order, right-to-left).
32
*
33
* Because of the recursive nature of many of the operations on trees it is
34
* necessary to define a number of helper functions for each type of tree node.
35
* The macro TREE_DEFINE(node_tag, entry_name) defines these functions with
36
* unique names according to the node_tag. This macro should be invoked,
37
* thereby defining the necessary functions, once per node tag in the program.
38
*
39
* For details on the use of these macros, see the tree(3) manual page.
40
*/
41
42
#ifndef __tree_h
43
#define __tree_h
44
45
46
#define TREE_DELTA_MAX 1
47
48
#define TREE_ENTRY(type) \
49
struct { \
50
struct type *avl_left; \
51
struct type *avl_right; \
52
int avl_height; \
53
}
54
55
#define TREE_HEAD(name, type) \
56
struct name { \
57
struct type *th_root; \
58
int (*th_cmp)(struct type *lhs, struct type *rhs); \
59
}
60
61
#define TREE_INITIALIZER(cmp) { 0, cmp }
62
63
#define TREE_DELTA(self, field) \
64
(( (((self)->field.avl_left) ? (self)->field.avl_left->field.avl_height : 0)) \
65
- (((self)->field.avl_right) ? (self)->field.avl_right->field.avl_height : 0))
66
67
/* Recursion prevents the following from being defined as macros. */
68
69
#define TREE_DEFINE(node, field) \
70
\
71
struct node *TREE_BALANCE_##node##_##field(struct node *); \
72
\
73
struct node *TREE_ROTL_##node##_##field(struct node *self) \
74
{ \
75
struct node *r= self->field.avl_right; \
76
self->field.avl_right= r->field.avl_left; \
77
r->field.avl_left= TREE_BALANCE_##node##_##field(self); \
78
return TREE_BALANCE_##node##_##field(r); \
79
} \
80
\
81
struct node *TREE_ROTR_##node##_##field(struct node *self) \
82
{ \
83
struct node *l= self->field.avl_left; \
84
self->field.avl_left= l->field.avl_right; \
85
l->field.avl_right= TREE_BALANCE_##node##_##field(self); \
86
return TREE_BALANCE_##node##_##field(l); \
87
} \
88
\
89
struct node *TREE_BALANCE_##node##_##field(struct node *self) \
90
{ \
91
int delta= TREE_DELTA(self, field); \
92
\
93
if (delta < -TREE_DELTA_MAX) \
94
{ \
95
if (TREE_DELTA(self->field.avl_right, field) > 0) \
96
self->field.avl_right= TREE_ROTR_##node##_##field(self->field.avl_right); \
97
return TREE_ROTL_##node##_##field(self); \
98
} \
99
else if (delta > TREE_DELTA_MAX) \
100
{ \
101
if (TREE_DELTA(self->field.avl_left, field) < 0) \
102
self->field.avl_left= TREE_ROTL_##node##_##field(self->field.avl_left); \
103
return TREE_ROTR_##node##_##field(self); \
104
} \
105
self->field.avl_height= 0; \
106
if (self->field.avl_left && (self->field.avl_left->field.avl_height > self->field.avl_height)) \
107
self->field.avl_height= self->field.avl_left->field.avl_height; \
108
if (self->field.avl_right && (self->field.avl_right->field.avl_height > self->field.avl_height)) \
109
self->field.avl_height= self->field.avl_right->field.avl_height; \
110
self->field.avl_height += 1; \
111
return self; \
112
} \
113
\
114
struct node *TREE_INSERT_##node##_##field \
115
(struct node *self, struct node *elm, int (*compare)(struct node *lhs, struct node *rhs)) \
116
{ \
117
if (!self) \
118
return elm; \
119
if (compare(elm, self) < 0) \
120
self->field.avl_left= TREE_INSERT_##node##_##field(self->field.avl_left, elm, compare); \
121
else \
122
self->field.avl_right= TREE_INSERT_##node##_##field(self->field.avl_right, elm, compare); \
123
return TREE_BALANCE_##node##_##field(self); \
124
} \
125
\
126
struct node *TREE_FIND_##node##_##field \
127
(struct node *self, struct node *elm, int (*compare)(struct node *lhs, struct node *rhs)) \
128
{ \
129
if (!self) \
130
return 0; \
131
if (compare(elm, self) == 0) \
132
return self; \
133
if (compare(elm, self) < 0) \
134
return TREE_FIND_##node##_##field(self->field.avl_left, elm, compare); \
135
else \
136
return TREE_FIND_##node##_##field(self->field.avl_right, elm, compare); \
137
} \
138
\
139
struct node *TREE_MOVE_RIGHT_##node##_##field(struct node *self, struct node *rhs) \
140
{ \
141
if (!self) \
142
return rhs; \
143
self->field.avl_right= TREE_MOVE_RIGHT_##node##_##field(self->field.avl_right, rhs); \
144
return TREE_BALANCE_##node##_##field(self); \
145
} \
146
\
147
struct node *TREE_REMOVE_##node##_##field \
148
(struct node *self, struct node *elm, int (*compare)(struct node *lhs, struct node *rhs)) \
149
{ \
150
if (!self) return 0; \
151
\
152
if (compare(elm, self) == 0) \
153
{ \
154
struct node *tmp= TREE_MOVE_RIGHT_##node##_##field(self->field.avl_left, self->field.avl_right); \
155
self->field.avl_left= 0; \
156
self->field.avl_right= 0; \
157
return tmp; \
158
} \
159
if (compare(elm, self) < 0) \
160
self->field.avl_left= TREE_REMOVE_##node##_##field(self->field.avl_left, elm, compare); \
161
else \
162
self->field.avl_right= TREE_REMOVE_##node##_##field(self->field.avl_right, elm, compare); \
163
return TREE_BALANCE_##node##_##field(self); \
164
} \
165
\
166
void TREE_FORWARD_APPLY_ALL_##node##_##field \
167
(struct node *self, void (*function)(struct node *node, void *data), void *data) \
168
{ \
169
if (self) \
170
{ \
171
TREE_FORWARD_APPLY_ALL_##node##_##field(self->field.avl_left, function, data); \
172
function(self, data); \
173
TREE_FORWARD_APPLY_ALL_##node##_##field(self->field.avl_right, function, data); \
174
} \
175
} \
176
\
177
void TREE_REVERSE_APPLY_ALL_##node##_##field \
178
(struct node *self, void (*function)(struct node *node, void *data), void *data) \
179
{ \
180
if (self) \
181
{ \
182
TREE_REVERSE_APPLY_ALL_##node##_##field(self->field.avl_right, function, data); \
183
function(self, data); \
184
TREE_REVERSE_APPLY_ALL_##node##_##field(self->field.avl_left, function, data); \
185
} \
186
}
187
188
#define TREE_INSERT(head, node, field, elm) \
189
((head)->th_root= TREE_INSERT_##node##_##field((head)->th_root, (elm), (head)->th_cmp))
190
191
#define TREE_FIND(head, node, field, elm) \
192
(TREE_FIND_##node##_##field((head)->th_root, (elm), (head)->th_cmp))
193
194
#define TREE_REMOVE(head, node, field, elm) \
195
((head)->th_root= TREE_REMOVE_##node##_##field((head)->th_root, (elm), (head)->th_cmp))
196
197
#define TREE_DEPTH(head, field) \
198
((head)->th_root->field.avl_height)
199
200
#define TREE_FORWARD_APPLY(head, node, field, function, data) \
201
TREE_FORWARD_APPLY_ALL_##node##_##field((head)->th_root, function, data)
202
203
#define TREE_REVERSE_APPLY(head, node, field, function, data) \
204
TREE_REVERSE_APPLY_ALL_##node##_##field((head)->th_root, function, data)
205
206
#define TREE_INIT(head, cmp) do { \
207
(head)->th_root= 0; \
208
(head)->th_cmp= (cmp); \
209
} while (0)
210
211
212
#endif /* __tree_h */
213
214