1 // RB tree utilities implementation -*- C++ -*-
3 // Copyright (C) 2003-2017 Free Software Foundation, Inc.
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)
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.
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)
65 while (__x
->_M_left
!= 0)
70 _Rb_tree_node_base
* __y
= __x
->_M_parent
;
71 while (__x
== __y
->_M_right
)
76 if (__x
->_M_right
!= __y
)
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
)
100 else if (__x
->_M_left
!= 0)
102 _Rb_tree_node_base
* __y
= __x
->_M_left
;
103 while (__y
->_M_right
!= 0)
109 _Rb_tree_node_base
* __y
= __x
->_M_parent
;
110 while (__x
== __y
->_M_left
)
113 __y
= __y
->_M_parent
;
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
));
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
;
145 else if (__x
== __x
->_M_parent
->_M_left
)
146 __x
->_M_parent
->_M_left
= __y
;
148 __x
->_M_parent
->_M_right
= __y
;
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
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
); }
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
;
176 else if (__x
== __x
->_M_parent
->_M_right
)
177 __x
->_M_parent
->_M_right
= __y
;
179 __x
->_M_parent
->_M_left
= __y
;
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
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
); }
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
;
206 __x
->_M_color
= _S_red
;
209 // Make new node child of parent and maintain root, leftmost and
211 // N.B. First node is always inserted 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
228 if (__p
== __header
._M_right
)
229 __header
._M_right
= __x
; // maintain rightmost pointing to max node
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
;
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
);
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
;
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
;
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.
299 if (__y
->_M_right
== 0) // __z has exactly one non-null child. y == z.
300 __x
= __y
->_M_left
; // __x is not null.
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)
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
;
326 else if (__z
->_M_parent
->_M_left
== __z
)
327 __z
->_M_parent
->_M_left
= __y
;
329 __z
->_M_parent
->_M_right
= __y
;
330 __y
->_M_parent
= __z
->_M_parent
;
331 std::swap(__y
->_M_color
, __z
->_M_color
);
333 // __y now points to node to be actually deleted
337 __x_parent
= __y
->_M_parent
;
339 __x
->_M_parent
= __y
->_M_parent
;
343 if (__z
->_M_parent
->_M_left
== __z
)
344 __z
->_M_parent
->_M_left
= __x
;
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
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
;
384 __x_parent
= __x_parent
->_M_parent
;
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
;
399 __w
->_M_right
->_M_color
= _S_black
;
400 local_Rb_tree_rotate_left(__x_parent
, __root
);
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
;
422 __x_parent
= __x_parent
->_M_parent
;
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
;
436 __w
->_M_left
->_M_color
= _S_black
;
437 local_Rb_tree_rotate_right(__x_parent
, __root
);
441 if (__x
) __x
->_M_color
= _S_black
;
447 _Rb_tree_black_count(const _Rb_tree_node_base
* __node
,
448 const _Rb_tree_node_base
* __root
) throw ()
452 unsigned int __sum
= 0;
455 if (__node
->_M_color
== _S_black
)
457 if (__node
== __root
)
459 __node
= __node
->_M_parent
;
465 _GLIBCXX_END_NAMESPACE_VERSION