2017-06-15 François Dumont <fdumont@gcc.gnu.org>
[official-gcc.git] / libstdc++-v3 / src / c++98 / tree.cc
blob0984b05e0af4a0dcb5885e3e70ec405f90c859a8
1 // RB tree utilities implementation -*- C++ -*-
3 // Copyright (C) 2003-2017 Free Software Foundation, Inc.
4 //
5 // This file is part of the GNU ISO C++ Library. This library is free
6 // software; you can redistribute it and/or modify it under the
7 // terms of the GNU General Public License as published by the
8 // Free Software Foundation; either version 3, or (at your option)
9 // any later version.
11 // This library is distributed in the hope that it will be useful,
12 // but WITHOUT ANY WARRANTY; without even the implied warranty of
13 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 // GNU General Public License for more details.
16 // Under Section 7 of GPL version 3, you are granted additional
17 // permissions described in the GCC Runtime Library Exception, version
18 // 3.1, as published by the Free Software Foundation.
20 // You should have received a copy of the GNU General Public License and
21 // a copy of the GCC Runtime Library Exception along with this program;
22 // see the files COPYING3 and COPYING.RUNTIME respectively. If not, see
23 // <http://www.gnu.org/licenses/>.
27 * Copyright (c) 1996,1997
28 * Silicon Graphics Computer Systems, Inc.
30 * Permission to use, copy, modify, distribute and sell this software
31 * and its documentation for any purpose is hereby granted without fee,
32 * provided that the above copyright notice appear in all copies and
33 * that both that copyright notice and this permission notice appear
34 * in supporting documentation. Silicon Graphics makes no
35 * representations about the suitability of this software for any
36 * purpose. It is provided "as is" without express or implied warranty.
39 * Copyright (c) 1994
40 * Hewlett-Packard Company
42 * Permission to use, copy, modify, distribute and sell this software
43 * and its documentation for any purpose is hereby granted without fee,
44 * provided that the above copyright notice appear in all copies and
45 * that both that copyright notice and this permission notice appear
46 * in supporting documentation. Hewlett-Packard Company makes no
47 * representations about the suitability of this software for any
48 * purpose. It is provided "as is" without express or implied warranty.
53 #include <bits/stl_tree.h>
55 namespace std _GLIBCXX_VISIBILITY(default)
57 _GLIBCXX_BEGIN_NAMESPACE_VERSION
59 static _Rb_tree_node_base*
60 local_Rb_tree_increment(_Rb_tree_node_base* __x) throw ()
62 if (__x->_M_right != 0)
64 __x = __x->_M_right;
65 while (__x->_M_left != 0)
66 __x = __x->_M_left;
68 else
70 _Rb_tree_node_base* __y = __x->_M_parent;
71 while (__x == __y->_M_right)
73 __x = __y;
74 __y = __y->_M_parent;
76 if (__x->_M_right != __y)
77 __x = __y;
79 return __x;
82 _Rb_tree_node_base*
83 _Rb_tree_increment(_Rb_tree_node_base* __x) throw ()
85 return local_Rb_tree_increment(__x);
88 const _Rb_tree_node_base*
89 _Rb_tree_increment(const _Rb_tree_node_base* __x) throw ()
91 return local_Rb_tree_increment(const_cast<_Rb_tree_node_base*>(__x));
94 static _Rb_tree_node_base*
95 local_Rb_tree_decrement(_Rb_tree_node_base* __x) throw ()
97 if (__x->_M_color == _S_red
98 && __x->_M_parent->_M_parent == __x)
99 __x = __x->_M_right;
100 else if (__x->_M_left != 0)
102 _Rb_tree_node_base* __y = __x->_M_left;
103 while (__y->_M_right != 0)
104 __y = __y->_M_right;
105 __x = __y;
107 else
109 _Rb_tree_node_base* __y = __x->_M_parent;
110 while (__x == __y->_M_left)
112 __x = __y;
113 __y = __y->_M_parent;
115 __x = __y;
117 return __x;
120 _Rb_tree_node_base*
121 _Rb_tree_decrement(_Rb_tree_node_base* __x) throw ()
123 return local_Rb_tree_decrement(__x);
126 const _Rb_tree_node_base*
127 _Rb_tree_decrement(const _Rb_tree_node_base* __x) throw ()
129 return local_Rb_tree_decrement(const_cast<_Rb_tree_node_base*>(__x));
132 static void
133 local_Rb_tree_rotate_left(_Rb_tree_node_base* const __x,
134 _Rb_tree_node_base*& __root)
136 _Rb_tree_node_base* const __y = __x->_M_right;
138 __x->_M_right = __y->_M_left;
139 if (__y->_M_left !=0)
140 __y->_M_left->_M_parent = __x;
141 __y->_M_parent = __x->_M_parent;
143 if (__x == __root)
144 __root = __y;
145 else if (__x == __x->_M_parent->_M_left)
146 __x->_M_parent->_M_left = __y;
147 else
148 __x->_M_parent->_M_right = __y;
149 __y->_M_left = __x;
150 __x->_M_parent = __y;
153 #if !_GLIBCXX_INLINE_VERSION
154 /* Static keyword was missing on _Rb_tree_rotate_left.
155 Export the symbol for backward compatibility until
156 next ABI change. */
157 void
158 _Rb_tree_rotate_left(_Rb_tree_node_base* const __x,
159 _Rb_tree_node_base*& __root)
160 { local_Rb_tree_rotate_left (__x, __root); }
161 #endif
163 static void
164 local_Rb_tree_rotate_right(_Rb_tree_node_base* const __x,
165 _Rb_tree_node_base*& __root)
167 _Rb_tree_node_base* const __y = __x->_M_left;
169 __x->_M_left = __y->_M_right;
170 if (__y->_M_right != 0)
171 __y->_M_right->_M_parent = __x;
172 __y->_M_parent = __x->_M_parent;
174 if (__x == __root)
175 __root = __y;
176 else if (__x == __x->_M_parent->_M_right)
177 __x->_M_parent->_M_right = __y;
178 else
179 __x->_M_parent->_M_left = __y;
180 __y->_M_right = __x;
181 __x->_M_parent = __y;
184 #if !_GLIBCXX_INLINE_VERSION
185 /* Static keyword was missing on _Rb_tree_rotate_right
186 Export the symbol for backward compatibility until
187 next ABI change. */
188 void
189 _Rb_tree_rotate_right(_Rb_tree_node_base* const __x,
190 _Rb_tree_node_base*& __root)
191 { local_Rb_tree_rotate_right (__x, __root); }
192 #endif
194 void
195 _Rb_tree_insert_and_rebalance(const bool __insert_left,
196 _Rb_tree_node_base* __x,
197 _Rb_tree_node_base* __p,
198 _Rb_tree_node_base& __header) throw ()
200 _Rb_tree_node_base *& __root = __header._M_parent;
202 // Initialize fields in new node to insert.
203 __x->_M_parent = __p;
204 __x->_M_left = 0;
205 __x->_M_right = 0;
206 __x->_M_color = _S_red;
208 // Insert.
209 // Make new node child of parent and maintain root, leftmost and
210 // rightmost nodes.
211 // N.B. First node is always inserted left.
212 if (__insert_left)
214 __p->_M_left = __x; // also makes leftmost = __x when __p == &__header
216 if (__p == &__header)
218 __header._M_parent = __x;
219 __header._M_right = __x;
221 else if (__p == __header._M_left)
222 __header._M_left = __x; // maintain leftmost pointing to min node
224 else
226 __p->_M_right = __x;
228 if (__p == __header._M_right)
229 __header._M_right = __x; // maintain rightmost pointing to max node
231 // Rebalance.
232 while (__x != __root
233 && __x->_M_parent->_M_color == _S_red)
235 _Rb_tree_node_base* const __xpp = __x->_M_parent->_M_parent;
237 if (__x->_M_parent == __xpp->_M_left)
239 _Rb_tree_node_base* const __y = __xpp->_M_right;
240 if (__y && __y->_M_color == _S_red)
242 __x->_M_parent->_M_color = _S_black;
243 __y->_M_color = _S_black;
244 __xpp->_M_color = _S_red;
245 __x = __xpp;
247 else
249 if (__x == __x->_M_parent->_M_right)
251 __x = __x->_M_parent;
252 local_Rb_tree_rotate_left(__x, __root);
254 __x->_M_parent->_M_color = _S_black;
255 __xpp->_M_color = _S_red;
256 local_Rb_tree_rotate_right(__xpp, __root);
259 else
261 _Rb_tree_node_base* const __y = __xpp->_M_left;
262 if (__y && __y->_M_color == _S_red)
264 __x->_M_parent->_M_color = _S_black;
265 __y->_M_color = _S_black;
266 __xpp->_M_color = _S_red;
267 __x = __xpp;
269 else
271 if (__x == __x->_M_parent->_M_left)
273 __x = __x->_M_parent;
274 local_Rb_tree_rotate_right(__x, __root);
276 __x->_M_parent->_M_color = _S_black;
277 __xpp->_M_color = _S_red;
278 local_Rb_tree_rotate_left(__xpp, __root);
282 __root->_M_color = _S_black;
285 _Rb_tree_node_base*
286 _Rb_tree_rebalance_for_erase(_Rb_tree_node_base* const __z,
287 _Rb_tree_node_base& __header) throw ()
289 _Rb_tree_node_base *& __root = __header._M_parent;
290 _Rb_tree_node_base *& __leftmost = __header._M_left;
291 _Rb_tree_node_base *& __rightmost = __header._M_right;
292 _Rb_tree_node_base* __y = __z;
293 _Rb_tree_node_base* __x = 0;
294 _Rb_tree_node_base* __x_parent = 0;
296 if (__y->_M_left == 0) // __z has at most one non-null child. y == z.
297 __x = __y->_M_right; // __x might be null.
298 else
299 if (__y->_M_right == 0) // __z has exactly one non-null child. y == z.
300 __x = __y->_M_left; // __x is not null.
301 else
303 // __z has two non-null children. Set __y to
304 __y = __y->_M_right; // __z's successor. __x might be null.
305 while (__y->_M_left != 0)
306 __y = __y->_M_left;
307 __x = __y->_M_right;
309 if (__y != __z)
311 // relink y in place of z. y is z's successor
312 __z->_M_left->_M_parent = __y;
313 __y->_M_left = __z->_M_left;
314 if (__y != __z->_M_right)
316 __x_parent = __y->_M_parent;
317 if (__x) __x->_M_parent = __y->_M_parent;
318 __y->_M_parent->_M_left = __x; // __y must be a child of _M_left
319 __y->_M_right = __z->_M_right;
320 __z->_M_right->_M_parent = __y;
322 else
323 __x_parent = __y;
324 if (__root == __z)
325 __root = __y;
326 else if (__z->_M_parent->_M_left == __z)
327 __z->_M_parent->_M_left = __y;
328 else
329 __z->_M_parent->_M_right = __y;
330 __y->_M_parent = __z->_M_parent;
331 std::swap(__y->_M_color, __z->_M_color);
332 __y = __z;
333 // __y now points to node to be actually deleted
335 else
336 { // __y == __z
337 __x_parent = __y->_M_parent;
338 if (__x)
339 __x->_M_parent = __y->_M_parent;
340 if (__root == __z)
341 __root = __x;
342 else
343 if (__z->_M_parent->_M_left == __z)
344 __z->_M_parent->_M_left = __x;
345 else
346 __z->_M_parent->_M_right = __x;
347 if (__leftmost == __z)
349 if (__z->_M_right == 0) // __z->_M_left must be null also
350 __leftmost = __z->_M_parent;
351 // makes __leftmost == _M_header if __z == __root
352 else
353 __leftmost = _Rb_tree_node_base::_S_minimum(__x);
355 if (__rightmost == __z)
357 if (__z->_M_left == 0) // __z->_M_right must be null also
358 __rightmost = __z->_M_parent;
359 // makes __rightmost == _M_header if __z == __root
360 else // __x == __z->_M_left
361 __rightmost = _Rb_tree_node_base::_S_maximum(__x);
364 if (__y->_M_color != _S_red)
366 while (__x != __root && (__x == 0 || __x->_M_color == _S_black))
367 if (__x == __x_parent->_M_left)
369 _Rb_tree_node_base* __w = __x_parent->_M_right;
370 if (__w->_M_color == _S_red)
372 __w->_M_color = _S_black;
373 __x_parent->_M_color = _S_red;
374 local_Rb_tree_rotate_left(__x_parent, __root);
375 __w = __x_parent->_M_right;
377 if ((__w->_M_left == 0 ||
378 __w->_M_left->_M_color == _S_black) &&
379 (__w->_M_right == 0 ||
380 __w->_M_right->_M_color == _S_black))
382 __w->_M_color = _S_red;
383 __x = __x_parent;
384 __x_parent = __x_parent->_M_parent;
386 else
388 if (__w->_M_right == 0
389 || __w->_M_right->_M_color == _S_black)
391 __w->_M_left->_M_color = _S_black;
392 __w->_M_color = _S_red;
393 local_Rb_tree_rotate_right(__w, __root);
394 __w = __x_parent->_M_right;
396 __w->_M_color = __x_parent->_M_color;
397 __x_parent->_M_color = _S_black;
398 if (__w->_M_right)
399 __w->_M_right->_M_color = _S_black;
400 local_Rb_tree_rotate_left(__x_parent, __root);
401 break;
404 else
406 // same as above, with _M_right <-> _M_left.
407 _Rb_tree_node_base* __w = __x_parent->_M_left;
408 if (__w->_M_color == _S_red)
410 __w->_M_color = _S_black;
411 __x_parent->_M_color = _S_red;
412 local_Rb_tree_rotate_right(__x_parent, __root);
413 __w = __x_parent->_M_left;
415 if ((__w->_M_right == 0 ||
416 __w->_M_right->_M_color == _S_black) &&
417 (__w->_M_left == 0 ||
418 __w->_M_left->_M_color == _S_black))
420 __w->_M_color = _S_red;
421 __x = __x_parent;
422 __x_parent = __x_parent->_M_parent;
424 else
426 if (__w->_M_left == 0 || __w->_M_left->_M_color == _S_black)
428 __w->_M_right->_M_color = _S_black;
429 __w->_M_color = _S_red;
430 local_Rb_tree_rotate_left(__w, __root);
431 __w = __x_parent->_M_left;
433 __w->_M_color = __x_parent->_M_color;
434 __x_parent->_M_color = _S_black;
435 if (__w->_M_left)
436 __w->_M_left->_M_color = _S_black;
437 local_Rb_tree_rotate_right(__x_parent, __root);
438 break;
441 if (__x) __x->_M_color = _S_black;
443 return __y;
446 unsigned int
447 _Rb_tree_black_count(const _Rb_tree_node_base* __node,
448 const _Rb_tree_node_base* __root) throw ()
450 if (__node == 0)
451 return 0;
452 unsigned int __sum = 0;
455 if (__node->_M_color == _S_black)
456 ++__sum;
457 if (__node == __root)
458 break;
459 __node = __node->_M_parent;
461 while (1);
462 return __sum;
465 _GLIBCXX_END_NAMESPACE_VERSION
466 } // namespace