source: NonGTP/Boost/boost/multi_index/detail/ord_index_node.hpp @ 857

Revision 857, 13.8 KB checked in by igarcia, 18 years ago (diff)
Line 
1/* Copyright 2003-2005 Joaquín M López Muñoz.
2 * Distributed under the Boost Software License, Version 1.0.
3 * (See accompanying file LICENSE_1_0.txt or copy at
4 * http://www.boost.org/LICENSE_1_0.txt)
5 *
6 * See http://www.boost.org/libs/multi_index for library home page.
7 *
8 * The internal implementation of red-black trees is based on that of SGI STL
9 * stl_tree.h file:
10 *
11 * Copyright (c) 1996,1997
12 * Silicon Graphics Computer Systems, Inc.
13 *
14 * Permission to use, copy, modify, distribute and sell this software
15 * and its documentation for any purpose is hereby granted without fee,
16 * provided that the above copyright notice appear in all copies and
17 * that both that copyright notice and this permission notice appear
18 * in supporting documentation.  Silicon Graphics makes no
19 * representations about the suitability of this software for any
20 * purpose.  It is provided "as is" without express or implied warranty.
21 *
22 *
23 * Copyright (c) 1994
24 * Hewlett-Packard Company
25 *
26 * Permission to use, copy, modify, distribute and sell this software
27 * and its documentation for any purpose is hereby granted without fee,
28 * provided that the above copyright notice appear in all copies and
29 * that both that copyright notice and this permission notice appear
30 * in supporting documentation.  Hewlett-Packard Company makes no
31 * representations about the suitability of this software for any
32 * purpose.  It is provided "as is" without express or implied warranty.
33 *
34 */
35
36#ifndef BOOST_MULTI_INDEX_DETAIL_ORD_INDEX_NODE_HPP
37#define BOOST_MULTI_INDEX_DETAIL_ORD_INDEX_NODE_HPP
38
39#if defined(_MSC_VER)&&(_MSC_VER>=1200)
40#pragma once
41#endif
42
43#include <algorithm>
44#include <cstddef>
45
46namespace boost{
47
48namespace multi_index{
49
50namespace detail{
51
52/* definition of red-black nodes for ordered_index */
53
54enum ordered_index_color{red=false,black=true};
55
56struct ordered_index_node_impl
57{
58  ordered_index_color&            color(){return color_;}
59  const ordered_index_color&      color()const{return color_;}
60  ordered_index_node_impl*&       parent(){return parent_;}
61  ordered_index_node_impl*const & parent()const{return parent_;}
62  ordered_index_node_impl*&       left(){return left_;}
63  ordered_index_node_impl*const & left()const{return left_;}
64  ordered_index_node_impl*&       right(){return right_;}
65  ordered_index_node_impl*const & right()const{return right_;}
66
67  /* interoperability with index_iterator */
68
69  static void increment(ordered_index_node_impl*& x)
70  {
71    if(x->right()){
72      x=x->right();
73      while(x->left())x=x->left();
74    }
75    else{
76      ordered_index_node_impl* y=x->parent();
77      while(x==y->right()){
78        x=y;
79        y=y->parent();
80      }
81      if(x->right()!=y)x=y;
82    }
83  }
84
85  static void decrement(ordered_index_node_impl*& x)
86  {
87    if(x->color()==red&&x->parent()->parent()==x){
88      x=x->right();
89    }
90    else if(x->left()){
91      ordered_index_node_impl* y=x->left();
92      while(y->right())y=y->right();
93      x=y;
94    }else{
95      ordered_index_node_impl* y=x->parent();
96      while(x==y->left()){
97        x=y;
98        y=y->parent();
99      }
100      x=y;
101    }
102  }
103
104  /* interoperability with index_proxy */
105
106  static ordered_index_node_impl* begin(ordered_index_node_impl* header)
107  {
108    return header->left();
109  }
110
111  static ordered_index_node_impl* end(ordered_index_node_impl* header)
112  {
113    return header;
114  }
115
116  /* algorithmic stuff */
117
118  static void rotate_left(
119    ordered_index_node_impl* x,ordered_index_node_impl*& root)
120  {
121    ordered_index_node_impl* y=x->right();
122    x->right()=y->left();
123    if(y->left())y->left()->parent()=x;
124    y->parent()=x->parent();
125   
126    if(x==root)                    root=y;
127    else if(x==x->parent()->left())x->parent()->left()=y;
128    else                           x->parent()->right()=y;
129    y->left()=x;
130    x->parent()=y;
131  }
132
133  static ordered_index_node_impl* minimum(ordered_index_node_impl* x)
134  {
135    while(x->left())x=x->left();
136    return x;
137  }
138
139  static ordered_index_node_impl* maximum(ordered_index_node_impl* x)
140  {
141    while(x->right())x=x->right();
142    return x;
143  }
144
145  static void rotate_right(
146    ordered_index_node_impl* x,ordered_index_node_impl*& root)
147  {
148    ordered_index_node_impl* y=x->left();
149    x->left()=y->right();
150    if(y->right())y->right()->parent()=x;
151    y->parent()=x->parent();
152
153    if(x==root)                     root=y;
154    else if(x==x->parent()->right())x->parent()->right()=y;
155    else                            x->parent()->left()=y;
156    y->right()=x;
157    x->parent()=y;
158  }
159
160  static void rebalance(
161    ordered_index_node_impl* x,ordered_index_node_impl*& root)
162  {
163    x->color()=red;
164    while(x!=root&&x->parent()->color()==red){
165      if(x->parent()==x->parent()->parent()->left()){
166        ordered_index_node_impl* y=x->parent()->parent()->right();
167        if(y&&y->color()==red){
168          x->parent()->color()=black;
169          y->color()=black;
170          x->parent()->parent()->color()=red;
171          x=x->parent()->parent();
172        }
173        else{
174          if(x==x->parent()->right()){
175            x=x->parent();
176            rotate_left(x,root);
177          }
178          x->parent()->color()=black;
179          x->parent()->parent()->color()=red;
180          rotate_right(x->parent()->parent(),root);
181        }
182      }
183      else{
184        ordered_index_node_impl* y=x->parent()->parent()->left();
185        if(y&&y->color()==red){
186          x->parent()->color()=black;
187          y->color()=black;
188          x->parent()->parent()->color()=red;
189          x=x->parent()->parent();
190        }
191        else{
192          if(x==x->parent()->left()){
193            x=x->parent();
194            rotate_right(x,root);
195          }
196          x->parent()->color()=black;
197          x->parent()->parent()->color()=red;
198          rotate_left(x->parent()->parent(),root);
199        }
200      }
201    }
202    root->color()=black;
203  }
204
205  static ordered_index_node_impl* rebalance_for_erase(
206    ordered_index_node_impl* z,ordered_index_node_impl*& root,
207    ordered_index_node_impl*& leftmost,ordered_index_node_impl*& rightmost)
208  {
209    ordered_index_node_impl* y=z;
210    ordered_index_node_impl* x=0;
211    ordered_index_node_impl* x_parent=0;
212    if(y->left()==0){        /* z has at most one non-null child. y==z. */
213      x=y->right();          /* x might be null */
214    }
215    else{
216      if(y->right()==0)  {     /* z has exactly one non-null child. y==z. */
217        x=y->left();           /* x is not null */
218      }
219      else{                    /* z has two non-null children.  Set y to */
220        y=y->right();          /*   z's successor.  x might be null.     */
221        while(y->left())y=y->left();
222        x=y->right();
223      }
224    }
225    if(y!=z){
226      z->left()->parent()=y;   /* relink y in place of z. y is z's successor */
227      y->left()=z->left();
228      if(y!=z->right()){
229        x_parent=y->parent();
230        if(x) x->parent()=y->parent();
231        y->parent()->left()=x; /* y must be a child of left */
232        y->right()=z->right();
233        z->right()->parent()=y;
234      }
235      else{
236        x_parent=y;
237      }
238
239      if(root==z)                    root=y;
240      else if(z->parent()->left()==z)z->parent()->left()=y;
241      else                           z->parent()->right()=y;
242      y->parent()=z->parent();
243      std::swap(y->color(),z->color());
244      y=z;                    /* y now points to node to be actually deleted */
245    }
246    else{                     /* y==z */
247      x_parent=y->parent();
248      if(x)x->parent()=y->parent();   
249      if(root==z){
250        root=x;
251      }
252      else{
253        if(z->parent()->left()==z)z->parent()->left()=x;
254        else                      z->parent()->right()=x;
255      }
256      if(leftmost==z){
257        if(z->right()==0){      /* z->left() must be null also */
258          leftmost=z->parent();
259        }
260        else{             
261          leftmost=minimum(x);  /* makes leftmost==header if z==root */
262        }
263      }
264      if(rightmost==z){
265        if(z->left()==0){       /* z->right() must be null also */
266          rightmost=z->parent();
267        }
268        else{                   /* x==z->left() */
269          rightmost=maximum(x); /* makes rightmost==header if z==root */
270        }
271      }
272    }
273    if(y->color()!=red){
274      while(x!=root&&(x==0 || x->color()==black)){
275        if(x==x_parent->left()){
276          ordered_index_node_impl* w=x_parent->right();
277          if(w->color()==red){
278            w->color()=black;
279            x_parent->color()=red;
280            rotate_left(x_parent,root);
281            w=x_parent->right();
282          }
283          if((w->left()==0||w->left()->color()==black) &&
284             (w->right()==0||w->right()->color()==black)){
285            w->color()=red;
286            x=x_parent;
287            x_parent=x_parent->parent();
288          }
289          else{
290            if(w->right()==0
291                || w->right()->color()==black){
292              if(w->left()) w->left()->color()=black;
293              w->color()=red;
294              rotate_right(w,root);
295              w=x_parent->right();
296            }
297            w->color()=x_parent->color();
298            x_parent->color()=black;
299            if(w->right())w->right()->color()=black;
300            rotate_left(x_parent,root);
301            break;
302          }
303        }
304        else{                   /* same as above,with right <-> left */
305          ordered_index_node_impl* w=x_parent->left();
306          if(w->color()==red){
307            w->color()=black;
308            x_parent->color()=red;
309            rotate_right(x_parent,root);
310            w=x_parent->left();
311          }
312          if((w->right()==0||w->right()->color()==black) &&
313             (w->left()==0||w->left()->color()==black)){
314            w->color()=red;
315            x=x_parent;
316            x_parent=x_parent->parent();
317          }
318          else{
319            if(w->left()==0||w->left()->color()==black){
320              if(w->right())w->right()->color()=black;
321              w->color()=red;
322              rotate_left(w,root);
323              w=x_parent->left();
324            }
325            w->color()=x_parent->color();
326            x_parent->color()=black;
327            if(w->left())w->left()->color()=black;
328            rotate_right(x_parent,root);
329            break;
330          }
331        }
332      }
333      if(x)x->color()=black;
334    }
335    return y;
336  }
337
338  static void restore(
339    ordered_index_node_impl* x,ordered_index_node_impl* prior,
340    ordered_index_node_impl* next,ordered_index_node_impl* header)
341  {
342    if(next->left()==0){
343      next->left()=x;
344      x->parent()=next;
345      if(next==header->left()){
346        header->left()=x;         /* maintain leftmost pointing to min node */
347      }
348    }
349    else if(x!=prior){            /* prior->right() must be null */
350      prior->right()=x;
351      x->parent()=prior;
352      if(prior==header->right()){
353        header->right()=x;        /* maintain rightmost pointing to max node */
354      }
355    }
356    else{
357      header->parent()=x;
358      header->left()=x;
359      header->right()=x;
360      x->parent()=header;
361    }
362    x->left()=0;
363    x->right()=0;
364    rebalance(x,header->parent());
365  }
366
367#if defined(BOOST_MULTI_INDEX_ENABLE_INVARIANT_CHECKING)
368  /* invariant stuff */
369
370  static std::size_t black_count(
371    ordered_index_node_impl* node,ordered_index_node_impl* root)
372  {
373    if(!node)return 0;
374    std::size_t sum=0;
375    for(;;){
376      if(node->color()==black)++sum;
377      if(node==root)break;
378      node=node->parent();
379    }
380    return sum;
381  }
382#endif
383
384private:
385  ordered_index_node_impl();
386
387  ordered_index_color      color_;
388  ordered_index_node_impl* parent_;
389  ordered_index_node_impl* left_;
390  ordered_index_node_impl* right_;
391};
392
393template<typename Super>
394struct ordered_index_node_trampoline:ordered_index_node_impl{};
395
396template<typename Super>
397struct ordered_index_node:Super,ordered_index_node_trampoline<Super>
398{
399  ordered_index_color&            color(){return impl_type::color();}
400  const ordered_index_color&      color()const{return impl_type::color();}
401  ordered_index_node_impl*&       parent(){return impl_type::parent();}
402  ordered_index_node_impl*const & parent()const{return impl_type::parent();}
403  ordered_index_node_impl*&       left(){return impl_type::left();}
404  ordered_index_node_impl*const & left()const{return impl_type::left();}
405  ordered_index_node_impl*&       right(){return impl_type::right();}
406  ordered_index_node_impl*const & right()const{return impl_type::right();}
407
408  ordered_index_node_impl* impl(){return static_cast<impl_type*>(this);}
409  const ordered_index_node_impl* impl()const
410    {return static_cast<const impl_type*>(this);}
411
412  static ordered_index_node* from_impl(ordered_index_node_impl *x)
413  {
414    return static_cast<ordered_index_node*>(static_cast<impl_type*>(x));
415  }
416 
417  static const ordered_index_node* from_impl(const ordered_index_node_impl* x)
418  {
419    return static_cast<const ordered_index_node*>(
420      static_cast<const impl_type*>(x));
421  }
422
423  /* interoperability with index_iterator */
424
425  static void increment(ordered_index_node*& x)
426  {
427    ordered_index_node_impl* xi=x->impl();
428    impl_type::increment(xi);
429    x=from_impl(xi);
430  }
431
432  static void decrement(ordered_index_node*& x)
433  {
434    ordered_index_node_impl* xi=x->impl();
435    impl_type::decrement(xi);
436    x=from_impl(xi);
437  }
438
439  /* interoperability with index_proxy */
440
441  static ordered_index_node* begin(ordered_index_node* header)
442  {
443    return from_impl(impl_type::begin(header->impl()));
444  }
445
446  static ordered_index_node* end(ordered_index_node* header)
447  {
448    return from_impl(impl_type::end(header->impl()));
449  }
450
451private:
452  typedef ordered_index_node_trampoline<Super> impl_type;
453};
454
455} /* namespace multi_index::detail */
456
457} /* namespace multi_index */
458
459} /* namespace boost */
460
461#endif
Note: See TracBrowser for help on using the repository browser.