OSDN Git Service

2004-11-02 Benjamin Kosnik <bkoz@redhat.com>
[pf3gnuchains/gcc-fork.git] / libstdc++-v3 / src / tree.cc
1 // RB tree utilities implementation -*- C++ -*-
2
3 // Copyright (C) 2003 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 2, or (at your option)
9 // any later version.
10
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.
15
16 // You should have received a copy of the GNU General Public License along
17 // with this library; see the file COPYING.  If not, write to the Free
18 // Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307,
19 // USA.
20
21 // As a special exception, you may use this file as part of a free software
22 // library without restriction.  Specifically, if other files instantiate
23 // templates or use macros or inline functions from this file, or you compile
24 // this file and link it with other files to produce an executable, this
25 // file does not by itself cause the resulting executable to be covered by
26 // the GNU General Public License.  This exception does not however
27 // invalidate any other reasons why the executable file might be covered by
28 // the GNU General Public License.
29
30 /*
31  *
32  * Copyright (c) 1996,1997
33  * Silicon Graphics Computer Systems, Inc.
34  *
35  * Permission to use, copy, modify, distribute and sell this software
36  * and its documentation for any purpose is hereby granted without fee,
37  * provided that the above copyright notice appear in all copies and
38  * that both that copyright notice and this permission notice appear
39  * in supporting documentation.  Silicon Graphics makes no
40  * representations about the suitability of this software for any
41  * purpose.  It is provided "as is" without express or implied warranty.
42  *
43  *
44  * Copyright (c) 1994
45  * Hewlett-Packard Company
46  *
47  * Permission to use, copy, modify, distribute and sell this software
48  * and its documentation for any purpose is hereby granted without fee,
49  * provided that the above copyright notice appear in all copies and
50  * that both that copyright notice and this permission notice appear
51  * in supporting documentation.  Hewlett-Packard Company makes no
52  * representations about the suitability of this software for any
53  * purpose.  It is provided "as is" without express or implied warranty.
54  *
55  *
56  */
57
58 #include <bits/stl_tree.h>
59
60 namespace std
61 {
62   _Rb_tree_node_base*
63   _Rb_tree_increment(_Rb_tree_node_base* __x)
64   {
65     if (__x->_M_right != 0) 
66       {
67         __x = __x->_M_right;
68         while (__x->_M_left != 0)
69           __x = __x->_M_left;
70       }
71     else 
72       {
73         _Rb_tree_node_base* __y = __x->_M_parent;
74         while (__x == __y->_M_right) 
75           {
76             __x = __y;
77             __y = __y->_M_parent;
78           }
79         if (__x->_M_right != __y)
80           __x = __y;
81       }
82     return __x;
83   }
84
85   const _Rb_tree_node_base*
86   _Rb_tree_increment(const _Rb_tree_node_base* __x)
87   {
88     return _Rb_tree_increment(const_cast<_Rb_tree_node_base*>(__x));
89   }
90
91   _Rb_tree_node_base*
92   _Rb_tree_decrement(_Rb_tree_node_base* __x)
93   {
94     if (__x->_M_color == _S_red 
95         && __x->_M_parent->_M_parent == __x)
96       __x = __x->_M_right;
97     else if (__x->_M_left != 0) 
98       {
99         _Rb_tree_node_base* __y = __x->_M_left;
100         while (__y->_M_right != 0)
101           __y = __y->_M_right;
102         __x = __y;
103       }
104     else 
105       {
106         _Rb_tree_node_base* __y = __x->_M_parent;
107         while (__x == __y->_M_left) 
108           {
109             __x = __y;
110             __y = __y->_M_parent;
111           }
112         __x = __y;
113       }
114     return __x;
115   }
116
117   const _Rb_tree_node_base*
118   _Rb_tree_decrement(const _Rb_tree_node_base* __x)
119   {
120     return _Rb_tree_decrement(const_cast<_Rb_tree_node_base*>(__x));
121   }
122
123   void 
124   _Rb_tree_rotate_left(_Rb_tree_node_base* const __x, 
125                        _Rb_tree_node_base*& __root)
126   {
127     _Rb_tree_node_base* const __y = __x->_M_right;
128
129     __x->_M_right = __y->_M_left;
130     if (__y->_M_left !=0)
131       __y->_M_left->_M_parent = __x;
132     __y->_M_parent = __x->_M_parent;
133     
134     if (__x == __root)
135       __root = __y;
136     else if (__x == __x->_M_parent->_M_left)
137       __x->_M_parent->_M_left = __y;
138     else
139       __x->_M_parent->_M_right = __y;
140     __y->_M_left = __x;
141     __x->_M_parent = __y;
142   }
143
144   void 
145   _Rb_tree_rotate_right(_Rb_tree_node_base* const __x, 
146                         _Rb_tree_node_base*& __root)
147   {
148     _Rb_tree_node_base* const __y = __x->_M_left;
149
150     __x->_M_left = __y->_M_right;
151     if (__y->_M_right != 0)
152       __y->_M_right->_M_parent = __x;
153     __y->_M_parent = __x->_M_parent;
154
155     if (__x == __root)
156       __root = __y;
157     else if (__x == __x->_M_parent->_M_right)
158       __x->_M_parent->_M_right = __y;
159     else
160       __x->_M_parent->_M_left = __y;
161     __y->_M_right = __x;
162     __x->_M_parent = __y;
163   }
164
165   void 
166   _Rb_tree_insert_and_rebalance(const bool          __insert_left,
167                                 _Rb_tree_node_base* __x,
168                                 _Rb_tree_node_base* __p,
169                                 _Rb_tree_node_base& __header)
170   {
171     _Rb_tree_node_base *& __root = __header._M_parent;
172
173     // Initialize fields in new node to insert.
174     __x->_M_parent = __p;
175     __x->_M_left = 0;
176     __x->_M_right = 0;
177     __x->_M_color = _S_red;
178
179     // Insert.
180     // Make new node child of parent and maintain root, leftmost and
181     // rightmost nodes.
182     // N.B. First node is always inserted left.
183     if (__insert_left)
184       {
185         __p->_M_left = __x; // also makes leftmost = __x when __p == &__header
186
187         if (__p == &__header)
188         {
189             __header._M_parent = __x;
190             __header._M_right = __x;
191         }
192         else if (__p == __header._M_left)
193           __header._M_left = __x; // maintain leftmost pointing to min node
194       }
195     else
196       {
197         __p->_M_right = __x;
198
199         if (__p == __header._M_right)
200           __header._M_right = __x; // maintain rightmost pointing to max node
201       }
202     // Rebalance.
203     while (__x != __root 
204            && __x->_M_parent->_M_color == _S_red) 
205       {
206         _Rb_tree_node_base* const __xpp = __x->_M_parent->_M_parent;
207
208         if (__x->_M_parent == __xpp->_M_left) 
209           {
210             _Rb_tree_node_base* const __y = __xpp->_M_right;
211             if (__y && __y->_M_color == _S_red) 
212               {
213                 __x->_M_parent->_M_color = _S_black;
214                 __y->_M_color = _S_black;
215                 __xpp->_M_color = _S_red;
216                 __x = __xpp;
217               }
218             else 
219               {
220                 if (__x == __x->_M_parent->_M_right) 
221                   {
222                     __x = __x->_M_parent;
223                     _Rb_tree_rotate_left(__x, __root);
224                   }
225                 __x->_M_parent->_M_color = _S_black;
226                 __xpp->_M_color = _S_red;
227                 _Rb_tree_rotate_right(__xpp, __root);
228               }
229           }
230         else 
231           {
232             _Rb_tree_node_base* const __y = __xpp->_M_left;
233             if (__y && __y->_M_color == _S_red) 
234               {
235                 __x->_M_parent->_M_color = _S_black;
236                 __y->_M_color = _S_black;
237                 __xpp->_M_color = _S_red;
238                 __x = __xpp;
239               }
240             else 
241               {
242                 if (__x == __x->_M_parent->_M_left) 
243                   {
244                     __x = __x->_M_parent;
245                     _Rb_tree_rotate_right(__x, __root);
246                   }
247                 __x->_M_parent->_M_color = _S_black;
248                 __xpp->_M_color = _S_red;
249                 _Rb_tree_rotate_left(__xpp, __root);
250               }
251           }
252       }
253     __root->_M_color = _S_black;
254   }
255
256   _Rb_tree_node_base*
257   _Rb_tree_rebalance_for_erase(_Rb_tree_node_base* const __z, 
258                                _Rb_tree_node_base& __header)
259   {
260     _Rb_tree_node_base *& __root = __header._M_parent;
261     _Rb_tree_node_base *& __leftmost = __header._M_left;
262     _Rb_tree_node_base *& __rightmost = __header._M_right;
263     _Rb_tree_node_base* __y = __z;
264     _Rb_tree_node_base* __x = 0;
265     _Rb_tree_node_base* __x_parent = 0;
266
267     if (__y->_M_left == 0)     // __z has at most one non-null child. y == z.
268       __x = __y->_M_right;     // __x might be null.
269     else
270       if (__y->_M_right == 0)  // __z has exactly one non-null child. y == z.
271         __x = __y->_M_left;    // __x is not null.
272       else 
273         {
274           // __z has two non-null children.  Set __y to
275           __y = __y->_M_right;   //   __z's successor.  __x might be null.
276           while (__y->_M_left != 0)
277             __y = __y->_M_left;
278           __x = __y->_M_right;
279         }
280     if (__y != __z) 
281       {
282         // relink y in place of z.  y is z's successor
283         __z->_M_left->_M_parent = __y; 
284         __y->_M_left = __z->_M_left;
285         if (__y != __z->_M_right) 
286           {
287             __x_parent = __y->_M_parent;
288             if (__x) __x->_M_parent = __y->_M_parent;
289             __y->_M_parent->_M_left = __x;   // __y must be a child of _M_left
290             __y->_M_right = __z->_M_right;
291             __z->_M_right->_M_parent = __y;
292           }
293         else
294           __x_parent = __y;  
295         if (__root == __z)
296           __root = __y;
297         else if (__z->_M_parent->_M_left == __z)
298           __z->_M_parent->_M_left = __y;
299         else 
300           __z->_M_parent->_M_right = __y;
301         __y->_M_parent = __z->_M_parent;
302         std::swap(__y->_M_color, __z->_M_color);
303         __y = __z;
304         // __y now points to node to be actually deleted
305       }
306     else 
307       {                        // __y == __z
308         __x_parent = __y->_M_parent;
309         if (__x) 
310           __x->_M_parent = __y->_M_parent;   
311         if (__root == __z)
312           __root = __x;
313         else 
314           if (__z->_M_parent->_M_left == __z)
315             __z->_M_parent->_M_left = __x;
316           else
317             __z->_M_parent->_M_right = __x;
318         if (__leftmost == __z) 
319           if (__z->_M_right == 0)        // __z->_M_left must be null also
320             __leftmost = __z->_M_parent;
321         // makes __leftmost == _M_header if __z == __root
322           else
323             __leftmost = _Rb_tree_node_base::_S_minimum(__x);
324         if (__rightmost == __z)  
325           if (__z->_M_left == 0)         // __z->_M_right must be null also
326             __rightmost = __z->_M_parent;  
327         // makes __rightmost == _M_header if __z == __root
328           else                      // __x == __z->_M_left
329             __rightmost = _Rb_tree_node_base::_S_maximum(__x);
330       }
331     if (__y->_M_color != _S_red) 
332       { 
333         while (__x != __root && (__x == 0 || __x->_M_color == _S_black))
334           if (__x == __x_parent->_M_left) 
335             {
336               _Rb_tree_node_base* __w = __x_parent->_M_right;
337               if (__w->_M_color == _S_red) 
338                 {
339                   __w->_M_color = _S_black;
340                   __x_parent->_M_color = _S_red;
341                   _Rb_tree_rotate_left(__x_parent, __root);
342                   __w = __x_parent->_M_right;
343                 }
344               if ((__w->_M_left == 0 || 
345                    __w->_M_left->_M_color == _S_black) &&
346                   (__w->_M_right == 0 || 
347                    __w->_M_right->_M_color == _S_black)) 
348                 {
349                   __w->_M_color = _S_red;
350                   __x = __x_parent;
351                   __x_parent = __x_parent->_M_parent;
352                 } 
353               else 
354                 {
355                   if (__w->_M_right == 0 
356                       || __w->_M_right->_M_color == _S_black) 
357                     {
358                       __w->_M_left->_M_color = _S_black;
359                       __w->_M_color = _S_red;
360                       _Rb_tree_rotate_right(__w, __root);
361                       __w = __x_parent->_M_right;
362                     }
363                   __w->_M_color = __x_parent->_M_color;
364                   __x_parent->_M_color = _S_black;
365                   if (__w->_M_right) 
366                     __w->_M_right->_M_color = _S_black;
367                   _Rb_tree_rotate_left(__x_parent, __root);
368                   break;
369                 }
370             } 
371           else 
372             {   
373               // same as above, with _M_right <-> _M_left.
374               _Rb_tree_node_base* __w = __x_parent->_M_left;
375               if (__w->_M_color == _S_red) 
376                 {
377                   __w->_M_color = _S_black;
378                   __x_parent->_M_color = _S_red;
379                   _Rb_tree_rotate_right(__x_parent, __root);
380                   __w = __x_parent->_M_left;
381                 }
382               if ((__w->_M_right == 0 || 
383                    __w->_M_right->_M_color == _S_black) &&
384                   (__w->_M_left == 0 || 
385                    __w->_M_left->_M_color == _S_black)) 
386                 {
387                   __w->_M_color = _S_red;
388                   __x = __x_parent;
389                   __x_parent = __x_parent->_M_parent;
390                 } 
391               else 
392                 {
393                   if (__w->_M_left == 0 || __w->_M_left->_M_color == _S_black) 
394                     {
395                       __w->_M_right->_M_color = _S_black;
396                       __w->_M_color = _S_red;
397                       _Rb_tree_rotate_left(__w, __root);
398                       __w = __x_parent->_M_left;
399                     }
400                   __w->_M_color = __x_parent->_M_color;
401                   __x_parent->_M_color = _S_black;
402                   if (__w->_M_left) 
403                     __w->_M_left->_M_color = _S_black;
404                   _Rb_tree_rotate_right(__x_parent, __root);
405                   break;
406                 }
407             }
408         if (__x) __x->_M_color = _S_black;
409       }
410     return __y;
411   }
412
413   unsigned int
414   _Rb_tree_black_count(const _Rb_tree_node_base* __node,
415                        const _Rb_tree_node_base* __root)
416   {
417     if (__node == 0)
418       return 0;
419     unsigned int __sum = 0;
420     do 
421       {
422         if (__node->_M_color == _S_black) 
423           ++__sum;
424         if (__node == __root) 
425           break;
426         __node = __node->_M_parent;
427       } 
428     while (1);
429     return __sum;
430   }
431 } // namespace std