/ src / tree.cc
tree.cc
  1  // RB tree utilities implementation -*- C++ -*-
  2  
  3  // Copyright (C) 2003, 2005 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, 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301,
 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  _GLIBCXX_BEGIN_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  
432  _GLIBCXX_END_NAMESPACE