rev |
line source |
keir@19684
|
1 /*
|
keir@19684
|
2 Red Black Trees
|
keir@19684
|
3 (C) 1999 Andrea Arcangeli <andrea@suse.de>
|
keir@19684
|
4 (C) 2002 David Woodhouse <dwmw2@infradead.org>
|
keir@19684
|
5
|
keir@19684
|
6 This program is free software; you can redistribute it and/or modify
|
keir@19684
|
7 it under the terms of the GNU General Public License as published by
|
keir@19684
|
8 the Free Software Foundation; either version 2 of the License, or
|
keir@19684
|
9 (at your option) any later version.
|
keir@19684
|
10
|
keir@19684
|
11 This program is distributed in the hope that it will be useful,
|
keir@19684
|
12 but WITHOUT ANY WARRANTY; without even the implied warranty of
|
keir@19684
|
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
keir@19684
|
14 GNU General Public License for more details.
|
keir@19684
|
15
|
keir@19684
|
16 You should have received a copy of the GNU General Public License
|
keir@19684
|
17 along with this program; if not, write to the Free Software
|
keir@19684
|
18 Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
keir@19684
|
19
|
keir@19684
|
20 linux/lib/rbtree.c
|
keir@19684
|
21 */
|
keir@19684
|
22
|
keir@19684
|
23 #include <xen/config.h>
|
keir@19684
|
24 #include <xen/types.h>
|
keir@19684
|
25 #include <xen/rbtree.h>
|
keir@19684
|
26
|
keir@19684
|
27 static void __rb_rotate_left(struct rb_node *node, struct rb_root *root)
|
keir@19684
|
28 {
|
keir@19684
|
29 struct rb_node *right = node->rb_right;
|
keir@19684
|
30 struct rb_node *parent = rb_parent(node);
|
keir@19684
|
31
|
keir@19684
|
32 if ((node->rb_right = right->rb_left))
|
keir@19684
|
33 rb_set_parent(right->rb_left, node);
|
keir@19684
|
34 right->rb_left = node;
|
keir@19684
|
35
|
keir@19684
|
36 rb_set_parent(right, parent);
|
keir@19684
|
37
|
keir@19684
|
38 if (parent)
|
keir@19684
|
39 {
|
keir@19684
|
40 if (node == parent->rb_left)
|
keir@19684
|
41 parent->rb_left = right;
|
keir@19684
|
42 else
|
keir@19684
|
43 parent->rb_right = right;
|
keir@19684
|
44 }
|
keir@19684
|
45 else
|
keir@19684
|
46 root->rb_node = right;
|
keir@19684
|
47 rb_set_parent(node, right);
|
keir@19684
|
48 }
|
keir@19684
|
49
|
keir@19684
|
50 static void __rb_rotate_right(struct rb_node *node, struct rb_root *root)
|
keir@19684
|
51 {
|
keir@19684
|
52 struct rb_node *left = node->rb_left;
|
keir@19684
|
53 struct rb_node *parent = rb_parent(node);
|
keir@19684
|
54
|
keir@19684
|
55 if ((node->rb_left = left->rb_right))
|
keir@19684
|
56 rb_set_parent(left->rb_right, node);
|
keir@19684
|
57 left->rb_right = node;
|
keir@19684
|
58
|
keir@19684
|
59 rb_set_parent(left, parent);
|
keir@19684
|
60
|
keir@19684
|
61 if (parent)
|
keir@19684
|
62 {
|
keir@19684
|
63 if (node == parent->rb_right)
|
keir@19684
|
64 parent->rb_right = left;
|
keir@19684
|
65 else
|
keir@19684
|
66 parent->rb_left = left;
|
keir@19684
|
67 }
|
keir@19684
|
68 else
|
keir@19684
|
69 root->rb_node = left;
|
keir@19684
|
70 rb_set_parent(node, left);
|
keir@19684
|
71 }
|
keir@19684
|
72
|
keir@19684
|
73 void rb_insert_color(struct rb_node *node, struct rb_root *root)
|
keir@19684
|
74 {
|
keir@19684
|
75 struct rb_node *parent, *gparent;
|
keir@19684
|
76
|
keir@19684
|
77 while ((parent = rb_parent(node)) && rb_is_red(parent))
|
keir@19684
|
78 {
|
keir@19684
|
79 gparent = rb_parent(parent);
|
keir@19684
|
80
|
keir@19684
|
81 if (parent == gparent->rb_left)
|
keir@19684
|
82 {
|
keir@19684
|
83 {
|
keir@19684
|
84 register struct rb_node *uncle = gparent->rb_right;
|
keir@19684
|
85 if (uncle && rb_is_red(uncle))
|
keir@19684
|
86 {
|
keir@19684
|
87 rb_set_black(uncle);
|
keir@19684
|
88 rb_set_black(parent);
|
keir@19684
|
89 rb_set_red(gparent);
|
keir@19684
|
90 node = gparent;
|
keir@19684
|
91 continue;
|
keir@19684
|
92 }
|
keir@19684
|
93 }
|
keir@19684
|
94
|
keir@19684
|
95 if (parent->rb_right == node)
|
keir@19684
|
96 {
|
keir@19684
|
97 register struct rb_node *tmp;
|
keir@19684
|
98 __rb_rotate_left(parent, root);
|
keir@19684
|
99 tmp = parent;
|
keir@19684
|
100 parent = node;
|
keir@19684
|
101 node = tmp;
|
keir@19684
|
102 }
|
keir@19684
|
103
|
keir@19684
|
104 rb_set_black(parent);
|
keir@19684
|
105 rb_set_red(gparent);
|
keir@19684
|
106 __rb_rotate_right(gparent, root);
|
keir@19684
|
107 } else {
|
keir@19684
|
108 {
|
keir@19684
|
109 register struct rb_node *uncle = gparent->rb_left;
|
keir@19684
|
110 if (uncle && rb_is_red(uncle))
|
keir@19684
|
111 {
|
keir@19684
|
112 rb_set_black(uncle);
|
keir@19684
|
113 rb_set_black(parent);
|
keir@19684
|
114 rb_set_red(gparent);
|
keir@19684
|
115 node = gparent;
|
keir@19684
|
116 continue;
|
keir@19684
|
117 }
|
keir@19684
|
118 }
|
keir@19684
|
119
|
keir@19684
|
120 if (parent->rb_left == node)
|
keir@19684
|
121 {
|
keir@19684
|
122 register struct rb_node *tmp;
|
keir@19684
|
123 __rb_rotate_right(parent, root);
|
keir@19684
|
124 tmp = parent;
|
keir@19684
|
125 parent = node;
|
keir@19684
|
126 node = tmp;
|
keir@19684
|
127 }
|
keir@19684
|
128
|
keir@19684
|
129 rb_set_black(parent);
|
keir@19684
|
130 rb_set_red(gparent);
|
keir@19684
|
131 __rb_rotate_left(gparent, root);
|
keir@19684
|
132 }
|
keir@19684
|
133 }
|
keir@19684
|
134
|
keir@19684
|
135 rb_set_black(root->rb_node);
|
keir@19684
|
136 }
|
keir@19684
|
137 EXPORT_SYMBOL(rb_insert_color);
|
keir@19684
|
138
|
keir@19684
|
139 static void __rb_erase_color(struct rb_node *node, struct rb_node *parent,
|
keir@19684
|
140 struct rb_root *root)
|
keir@19684
|
141 {
|
keir@19684
|
142 struct rb_node *other;
|
keir@19684
|
143
|
keir@19684
|
144 while ((!node || rb_is_black(node)) && node != root->rb_node)
|
keir@19684
|
145 {
|
keir@19684
|
146 if (parent->rb_left == node)
|
keir@19684
|
147 {
|
keir@19684
|
148 other = parent->rb_right;
|
keir@19684
|
149 if (rb_is_red(other))
|
keir@19684
|
150 {
|
keir@19684
|
151 rb_set_black(other);
|
keir@19684
|
152 rb_set_red(parent);
|
keir@19684
|
153 __rb_rotate_left(parent, root);
|
keir@19684
|
154 other = parent->rb_right;
|
keir@19684
|
155 }
|
keir@19684
|
156 if ((!other->rb_left || rb_is_black(other->rb_left)) &&
|
keir@19684
|
157 (!other->rb_right || rb_is_black(other->rb_right)))
|
keir@19684
|
158 {
|
keir@19684
|
159 rb_set_red(other);
|
keir@19684
|
160 node = parent;
|
keir@19684
|
161 parent = rb_parent(node);
|
keir@19684
|
162 }
|
keir@19684
|
163 else
|
keir@19684
|
164 {
|
keir@19684
|
165 if (!other->rb_right || rb_is_black(other->rb_right))
|
keir@19684
|
166 {
|
keir@19684
|
167 struct rb_node *o_left;
|
keir@19684
|
168 if ((o_left = other->rb_left))
|
keir@19684
|
169 rb_set_black(o_left);
|
keir@19684
|
170 rb_set_red(other);
|
keir@19684
|
171 __rb_rotate_right(other, root);
|
keir@19684
|
172 other = parent->rb_right;
|
keir@19684
|
173 }
|
keir@19684
|
174 rb_set_color(other, rb_color(parent));
|
keir@19684
|
175 rb_set_black(parent);
|
keir@19684
|
176 if (other->rb_right)
|
keir@19684
|
177 rb_set_black(other->rb_right);
|
keir@19684
|
178 __rb_rotate_left(parent, root);
|
keir@19684
|
179 node = root->rb_node;
|
keir@19684
|
180 break;
|
keir@19684
|
181 }
|
keir@19684
|
182 }
|
keir@19684
|
183 else
|
keir@19684
|
184 {
|
keir@19684
|
185 other = parent->rb_left;
|
keir@19684
|
186 if (rb_is_red(other))
|
keir@19684
|
187 {
|
keir@19684
|
188 rb_set_black(other);
|
keir@19684
|
189 rb_set_red(parent);
|
keir@19684
|
190 __rb_rotate_right(parent, root);
|
keir@19684
|
191 other = parent->rb_left;
|
keir@19684
|
192 }
|
keir@19684
|
193 if ((!other->rb_left || rb_is_black(other->rb_left)) &&
|
keir@19684
|
194 (!other->rb_right || rb_is_black(other->rb_right)))
|
keir@19684
|
195 {
|
keir@19684
|
196 rb_set_red(other);
|
keir@19684
|
197 node = parent;
|
keir@19684
|
198 parent = rb_parent(node);
|
keir@19684
|
199 }
|
keir@19684
|
200 else
|
keir@19684
|
201 {
|
keir@19684
|
202 if (!other->rb_left || rb_is_black(other->rb_left))
|
keir@19684
|
203 {
|
keir@19684
|
204 register struct rb_node *o_right;
|
keir@19684
|
205 if ((o_right = other->rb_right))
|
keir@19684
|
206 rb_set_black(o_right);
|
keir@19684
|
207 rb_set_red(other);
|
keir@19684
|
208 __rb_rotate_left(other, root);
|
keir@19684
|
209 other = parent->rb_left;
|
keir@19684
|
210 }
|
keir@19684
|
211 rb_set_color(other, rb_color(parent));
|
keir@19684
|
212 rb_set_black(parent);
|
keir@19684
|
213 if (other->rb_left)
|
keir@19684
|
214 rb_set_black(other->rb_left);
|
keir@19684
|
215 __rb_rotate_right(parent, root);
|
keir@19684
|
216 node = root->rb_node;
|
keir@19684
|
217 break;
|
keir@19684
|
218 }
|
keir@19684
|
219 }
|
keir@19684
|
220 }
|
keir@19684
|
221 if (node)
|
keir@19684
|
222 rb_set_black(node);
|
keir@19684
|
223 }
|
keir@19684
|
224
|
keir@19684
|
225 void rb_erase(struct rb_node *node, struct rb_root *root)
|
keir@19684
|
226 {
|
keir@19684
|
227 struct rb_node *child, *parent;
|
keir@19684
|
228 int color;
|
keir@19684
|
229
|
keir@19684
|
230 if (!node->rb_left)
|
keir@19684
|
231 child = node->rb_right;
|
keir@19684
|
232 else if (!node->rb_right)
|
keir@19684
|
233 child = node->rb_left;
|
keir@19684
|
234 else
|
keir@19684
|
235 {
|
keir@19684
|
236 struct rb_node *old = node, *left;
|
keir@19684
|
237
|
keir@19684
|
238 node = node->rb_right;
|
keir@19684
|
239 while ((left = node->rb_left) != NULL)
|
keir@19684
|
240 node = left;
|
keir@19684
|
241 child = node->rb_right;
|
keir@19684
|
242 parent = rb_parent(node);
|
keir@19684
|
243 color = rb_color(node);
|
keir@19684
|
244
|
keir@19684
|
245 if (child)
|
keir@19684
|
246 rb_set_parent(child, parent);
|
keir@19684
|
247 if (parent == old) {
|
keir@19684
|
248 parent->rb_right = child;
|
keir@19684
|
249 parent = node;
|
keir@19684
|
250 } else
|
keir@19684
|
251 parent->rb_left = child;
|
keir@19684
|
252
|
keir@19684
|
253 node->rb_parent_color = old->rb_parent_color;
|
keir@19684
|
254 node->rb_right = old->rb_right;
|
keir@19684
|
255 node->rb_left = old->rb_left;
|
keir@19684
|
256
|
keir@19684
|
257 if (rb_parent(old))
|
keir@19684
|
258 {
|
keir@19684
|
259 if (rb_parent(old)->rb_left == old)
|
keir@19684
|
260 rb_parent(old)->rb_left = node;
|
keir@19684
|
261 else
|
keir@19684
|
262 rb_parent(old)->rb_right = node;
|
keir@19684
|
263 } else
|
keir@19684
|
264 root->rb_node = node;
|
keir@19684
|
265
|
keir@19684
|
266 rb_set_parent(old->rb_left, node);
|
keir@19684
|
267 if (old->rb_right)
|
keir@19684
|
268 rb_set_parent(old->rb_right, node);
|
keir@19684
|
269 goto color;
|
keir@19684
|
270 }
|
keir@19684
|
271
|
keir@19684
|
272 parent = rb_parent(node);
|
keir@19684
|
273 color = rb_color(node);
|
keir@19684
|
274
|
keir@19684
|
275 if (child)
|
keir@19684
|
276 rb_set_parent(child, parent);
|
keir@19684
|
277 if (parent)
|
keir@19684
|
278 {
|
keir@19684
|
279 if (parent->rb_left == node)
|
keir@19684
|
280 parent->rb_left = child;
|
keir@19684
|
281 else
|
keir@19684
|
282 parent->rb_right = child;
|
keir@19684
|
283 }
|
keir@19684
|
284 else
|
keir@19684
|
285 root->rb_node = child;
|
keir@19684
|
286
|
keir@19684
|
287 color:
|
keir@19684
|
288 if (color == RB_BLACK)
|
keir@19684
|
289 __rb_erase_color(child, parent, root);
|
keir@19684
|
290 }
|
keir@19684
|
291 EXPORT_SYMBOL(rb_erase);
|
keir@19684
|
292
|
keir@19684
|
293 /*
|
keir@19684
|
294 * This function returns the first node (in sort order) of the tree.
|
keir@19684
|
295 */
|
keir@19684
|
296 struct rb_node *rb_first(struct rb_root *root)
|
keir@19684
|
297 {
|
keir@19684
|
298 struct rb_node *n;
|
keir@19684
|
299
|
keir@19684
|
300 n = root->rb_node;
|
keir@19684
|
301 if (!n)
|
keir@19684
|
302 return NULL;
|
keir@19684
|
303 while (n->rb_left)
|
keir@19684
|
304 n = n->rb_left;
|
keir@19684
|
305 return n;
|
keir@19684
|
306 }
|
keir@19684
|
307 EXPORT_SYMBOL(rb_first);
|
keir@19684
|
308
|
keir@19684
|
309 struct rb_node *rb_last(struct rb_root *root)
|
keir@19684
|
310 {
|
keir@19684
|
311 struct rb_node *n;
|
keir@19684
|
312
|
keir@19684
|
313 n = root->rb_node;
|
keir@19684
|
314 if (!n)
|
keir@19684
|
315 return NULL;
|
keir@19684
|
316 while (n->rb_right)
|
keir@19684
|
317 n = n->rb_right;
|
keir@19684
|
318 return n;
|
keir@19684
|
319 }
|
keir@19684
|
320 EXPORT_SYMBOL(rb_last);
|
keir@19684
|
321
|
keir@19684
|
322 struct rb_node *rb_next(struct rb_node *node)
|
keir@19684
|
323 {
|
keir@19684
|
324 struct rb_node *parent;
|
keir@19684
|
325
|
keir@19684
|
326 if (rb_parent(node) == node)
|
keir@19684
|
327 return NULL;
|
keir@19684
|
328
|
keir@19684
|
329 /* If we have a right-hand child, go down and then left as far
|
keir@19684
|
330 as we can. */
|
keir@19684
|
331 if (node->rb_right) {
|
keir@19684
|
332 node = node->rb_right;
|
keir@19684
|
333 while (node->rb_left)
|
keir@19684
|
334 node=node->rb_left;
|
keir@19684
|
335 return node;
|
keir@19684
|
336 }
|
keir@19684
|
337
|
keir@19684
|
338 /* No right-hand children. Everything down and left is
|
keir@19684
|
339 smaller than us, so any 'next' node must be in the general
|
keir@19684
|
340 direction of our parent. Go up the tree; any time the
|
keir@19684
|
341 ancestor is a right-hand child of its parent, keep going
|
keir@19684
|
342 up. First time it's a left-hand child of its parent, said
|
keir@19684
|
343 parent is our 'next' node. */
|
keir@19684
|
344 while ((parent = rb_parent(node)) && node == parent->rb_right)
|
keir@19684
|
345 node = parent;
|
keir@19684
|
346
|
keir@19684
|
347 return parent;
|
keir@19684
|
348 }
|
keir@19684
|
349 EXPORT_SYMBOL(rb_next);
|
keir@19684
|
350
|
keir@19684
|
351 struct rb_node *rb_prev(struct rb_node *node)
|
keir@19684
|
352 {
|
keir@19684
|
353 struct rb_node *parent;
|
keir@19684
|
354
|
keir@19684
|
355 if (rb_parent(node) == node)
|
keir@19684
|
356 return NULL;
|
keir@19684
|
357
|
keir@19684
|
358 /* If we have a left-hand child, go down and then right as far
|
keir@19684
|
359 as we can. */
|
keir@19684
|
360 if (node->rb_left) {
|
keir@19684
|
361 node = node->rb_left;
|
keir@19684
|
362 while (node->rb_right)
|
keir@19684
|
363 node=node->rb_right;
|
keir@19684
|
364 return node;
|
keir@19684
|
365 }
|
keir@19684
|
366
|
keir@19684
|
367 /* No left-hand children. Go up till we find an ancestor which
|
keir@19684
|
368 is a right-hand child of its parent */
|
keir@19684
|
369 while ((parent = rb_parent(node)) && node == parent->rb_left)
|
keir@19684
|
370 node = parent;
|
keir@19684
|
371
|
keir@19684
|
372 return parent;
|
keir@19684
|
373 }
|
keir@19684
|
374 EXPORT_SYMBOL(rb_prev);
|
keir@19684
|
375
|
keir@19684
|
376 void rb_replace_node(struct rb_node *victim, struct rb_node *new,
|
keir@19684
|
377 struct rb_root *root)
|
keir@19684
|
378 {
|
keir@19684
|
379 struct rb_node *parent = rb_parent(victim);
|
keir@19684
|
380
|
keir@19684
|
381 /* Set the surrounding nodes to point to the replacement */
|
keir@19684
|
382 if (parent) {
|
keir@19684
|
383 if (victim == parent->rb_left)
|
keir@19684
|
384 parent->rb_left = new;
|
keir@19684
|
385 else
|
keir@19684
|
386 parent->rb_right = new;
|
keir@19684
|
387 } else {
|
keir@19684
|
388 root->rb_node = new;
|
keir@19684
|
389 }
|
keir@19684
|
390 if (victim->rb_left)
|
keir@19684
|
391 rb_set_parent(victim->rb_left, new);
|
keir@19684
|
392 if (victim->rb_right)
|
keir@19684
|
393 rb_set_parent(victim->rb_right, new);
|
keir@19684
|
394
|
keir@19684
|
395 /* Copy the pointers/colour from the victim to the replacement */
|
keir@19684
|
396 *new = *victim;
|
keir@19684
|
397 }
|
keir@19684
|
398 EXPORT_SYMBOL(rb_replace_node);
|