Simplified rebalancing code extracting common operations to a local variable

This commit is contained in:
Ion Gaztañaga
2013-12-31 12:31:11 +01:00
parent 37b30ef5c7
commit 7093b464ca
2 changed files with 35 additions and 53 deletions

View File

@@ -364,13 +364,14 @@ class avltree_algorithms
node_ptr x(xnode), x_parent(xnode_parent); node_ptr x(xnode), x_parent(xnode_parent);
for (node_ptr root = NodeTraits::get_parent(header); x != root; root = NodeTraits::get_parent(header)) { for (node_ptr root = NodeTraits::get_parent(header); x != root; root = NodeTraits::get_parent(header)) {
const balance x_parent_balance = NodeTraits::get_balance(x_parent); const balance x_parent_balance = NodeTraits::get_balance(x_parent);
node_ptr const x_parent_left(NodeTraits::get_left(x_parent));
if(x_parent_balance == NodeTraits::zero()){ if(x_parent_balance == NodeTraits::zero()){
NodeTraits::set_balance(x_parent, NodeTraits::set_balance( x_parent
(x == NodeTraits::get_right(x_parent) ? NodeTraits::negative() : NodeTraits::positive())); , x == x_parent_left ? NodeTraits::positive() : NodeTraits::negative() );
break; // the height didn't change, let's stop here break; // the height didn't change, let's stop here
} }
else if(x_parent_balance == NodeTraits::negative()){ else if(x_parent_balance == NodeTraits::negative()){
if (x == NodeTraits::get_left(x_parent)) { if (x == x_parent_left) {
NodeTraits::set_balance(x_parent, NodeTraits::zero()); // balanced NodeTraits::set_balance(x_parent, NodeTraits::zero()); // balanced
x = x_parent; x = x_parent;
x_parent = NodeTraits::get_parent(x_parent); x_parent = NodeTraits::get_parent(x_parent);
@@ -378,7 +379,7 @@ class avltree_algorithms
else { else {
// x is right child // x is right child
// a is left child // a is left child
node_ptr a = NodeTraits::get_left(x_parent); node_ptr a = x_parent_left;
BOOST_INTRUSIVE_INVARIANT_ASSERT(a); BOOST_INTRUSIVE_INVARIANT_ASSERT(a);
if (NodeTraits::get_balance(a) == NodeTraits::positive()) { if (NodeTraits::get_balance(a) == NodeTraits::positive()) {
// a MUST have a right child // a MUST have a right child
@@ -441,38 +442,38 @@ class avltree_algorithms
NodeTraits::set_balance(x, NodeTraits::zero()); NodeTraits::set_balance(x, NodeTraits::zero());
// Rebalance. // Rebalance.
for(node_ptr root = NodeTraits::get_parent(header); x != root; root = NodeTraits::get_parent(header)){ for(node_ptr root = NodeTraits::get_parent(header); x != root; root = NodeTraits::get_parent(header)){
const balance x_parent_balance = NodeTraits::get_balance(NodeTraits::get_parent(x)); node_ptr const x_parent(NodeTraits::get_parent(x));
node_ptr const x_parent_left(NodeTraits::get_left(x_parent));
const balance x_parent_balance = NodeTraits::get_balance(x_parent);
if(x_parent_balance == NodeTraits::zero()){ if(x_parent_balance == NodeTraits::zero()){
// if x is left, parent will have parent->bal_factor = negative // if x is left, parent will have parent->bal_factor = negative
// else, parent->bal_factor = NodeTraits::positive() // else, parent->bal_factor = NodeTraits::positive()
NodeTraits::set_balance( NodeTraits::get_parent(x) NodeTraits::set_balance( x_parent, x == x_parent_left
, x == NodeTraits::get_left(NodeTraits::get_parent(x))
? NodeTraits::negative() : NodeTraits::positive() ); ? NodeTraits::negative() : NodeTraits::positive() );
x = NodeTraits::get_parent(x); x = x_parent;
} }
else if(x_parent_balance == NodeTraits::positive()){ else if(x_parent_balance == NodeTraits::positive()){
// if x is a left child, parent->bal_factor = zero // if x is a left child, parent->bal_factor = zero
if (x == NodeTraits::get_left(NodeTraits::get_parent(x))) if (x == x_parent_left)
NodeTraits::set_balance(NodeTraits::get_parent(x), NodeTraits::zero()); NodeTraits::set_balance(x_parent, NodeTraits::zero());
else{ // x is a right child, needs rebalancing else{ // x is a right child, needs rebalancing
if (NodeTraits::get_balance(x) == NodeTraits::negative()) if (NodeTraits::get_balance(x) == NodeTraits::negative())
rotate_right_left(NodeTraits::get_parent(x), header); rotate_right_left(x_parent, header);
else else
rotate_left(NodeTraits::get_parent(x), header); rotate_left(x_parent, header);
} }
break; break;
} }
else if(x_parent_balance == NodeTraits::negative()){ else if(x_parent_balance == NodeTraits::negative()){
// if x is a left child, needs rebalancing // if x is a left child, needs rebalancing
if (x == NodeTraits::get_left(NodeTraits::get_parent(x))) { if (x == x_parent_left) {
if (NodeTraits::get_balance(x) == NodeTraits::positive()) if (NodeTraits::get_balance(x) == NodeTraits::positive())
rotate_left_right(NodeTraits::get_parent(x), header); rotate_left_right(x_parent, header);
else else
rotate_right(NodeTraits::get_parent(x), header); rotate_right(x_parent, header);
} }
else else
NodeTraits::set_balance(NodeTraits::get_parent(x), NodeTraits::zero()); NodeTraits::set_balance(x_parent, NodeTraits::zero());
break; break;
} }
else{ else{
@@ -486,18 +487,20 @@ class avltree_algorithms
// balancing... // balancing...
const balance c_balance = NodeTraits::get_balance(c); const balance c_balance = NodeTraits::get_balance(c);
const balance zero_balance = NodeTraits::zero(); const balance zero_balance = NodeTraits::zero();
const balance posi_balance = NodeTraits::positive();
const balance nega_balance = NodeTraits::negative();
NodeTraits::set_balance(c, zero_balance); NodeTraits::set_balance(c, zero_balance);
if(c_balance == NodeTraits::negative()){ if(c_balance == nega_balance){
NodeTraits::set_balance(a, NodeTraits::positive()); NodeTraits::set_balance(a, posi_balance);
NodeTraits::set_balance(b, zero_balance); NodeTraits::set_balance(b, zero_balance);
} }
else if(c_balance == zero_balance){ else if(c_balance == zero_balance){
NodeTraits::set_balance(a, zero_balance); NodeTraits::set_balance(a, zero_balance);
NodeTraits::set_balance(b, zero_balance); NodeTraits::set_balance(b, zero_balance);
} }
else if(c_balance == NodeTraits::positive()){ else if(c_balance == posi_balance){
NodeTraits::set_balance(a, zero_balance); NodeTraits::set_balance(a, zero_balance);
NodeTraits::set_balance(b, NodeTraits::negative()); NodeTraits::set_balance(b, nega_balance);
} }
else{ else{
BOOST_INTRUSIVE_INVARIANT_ASSERT(false); // never reached BOOST_INTRUSIVE_INVARIANT_ASSERT(false); // never reached

View File

@@ -10,31 +10,6 @@
// See http://www.boost.org/libs/intrusive for documentation. // See http://www.boost.org/libs/intrusive for documentation.
// //
///////////////////////////////////////////////////////////////////////////// /////////////////////////////////////////////////////////////////////////////
// The internal implementation of red-black trees is based on that of SGI STL
// stl_tree.h file:
//
// Copyright (c) 1996,1997
// Silicon Graphics Computer Systems, Inc.
//
// Permission to use, copy, modify, distribute and sell this software
// and its documentation for any purpose is hereby granted without fee,
// provided that the above copyright notice appear in all copies and
// that both that copyright notice and this permission notice appear
// in supporting documentation. Silicon Graphics makes no
// representations about the suitability of this software for any
// purpose. It is provided "as is" without express or implied warranty.
//
//
// Copyright (c) 1994
// Hewlett-Packard Company
//
// Permission to use, copy, modify, distribute and sell this software
// and its documentation for any purpose is hereby granted without fee,
// provided that the above copyright notice appear in all copies and
// that both that copyright notice and this permission notice appear
// in supporting documentation. Hewlett-Packard Company makes no
// representations about the suitability of this software for any
// purpose. It is provided "as is" without express or implied warranty.
// //
// The tree destruction algorithm is based on Julienne Walker and The EC Team code: // The tree destruction algorithm is based on Julienne Walker and The EC Team code:
// //
@@ -421,14 +396,16 @@ class rbtree_algorithms
bstree_algo::rotate_left(x_parent, header); bstree_algo::rotate_left(x_parent, header);
w = NodeTraits::get_right(x_parent); w = NodeTraits::get_right(x_parent);
} }
if((!NodeTraits::get_left(w) || NodeTraits::get_color(NodeTraits::get_left(w)) == NodeTraits::black()) && node_ptr const w_left (NodeTraits::get_left(w));
(!NodeTraits::get_right(w) || NodeTraits::get_color(NodeTraits::get_right(w)) == NodeTraits::black())){ node_ptr const w_right(NodeTraits::get_right(w));
if((!w_left || NodeTraits::get_color(w_left) == NodeTraits::black()) &&
(!w_right || NodeTraits::get_color(w_right) == NodeTraits::black())){
NodeTraits::set_color(w, NodeTraits::red()); NodeTraits::set_color(w, NodeTraits::red());
x = x_parent; x = x_parent;
x_parent = NodeTraits::get_parent(x_parent); x_parent = NodeTraits::get_parent(x_parent);
} }
else { else {
if(!NodeTraits::get_right(w) || NodeTraits::get_color(NodeTraits::get_right(w)) == NodeTraits::black()){ if(!w_right || NodeTraits::get_color(w_right) == NodeTraits::black()){
NodeTraits::set_color(NodeTraits::get_left(w), NodeTraits::black()); NodeTraits::set_color(NodeTraits::get_left(w), NodeTraits::black());
NodeTraits::set_color(w, NodeTraits::red()); NodeTraits::set_color(w, NodeTraits::red());
bstree_algo::rotate_right(w, header); bstree_algo::rotate_right(w, header);
@@ -451,14 +428,16 @@ class rbtree_algorithms
bstree_algo::rotate_right(x_parent, header); bstree_algo::rotate_right(x_parent, header);
w = NodeTraits::get_left(x_parent); w = NodeTraits::get_left(x_parent);
} }
if((!NodeTraits::get_right(w) || NodeTraits::get_color(NodeTraits::get_right(w)) == NodeTraits::black()) && node_ptr const w_left (NodeTraits::get_left(w));
(!NodeTraits::get_left(w) || NodeTraits::get_color(NodeTraits::get_left(w)) == NodeTraits::black())){ node_ptr const w_right(NodeTraits::get_right(w));
if((!w_right || NodeTraits::get_color(w_right) == NodeTraits::black()) &&
(!w_left || NodeTraits::get_color(w_left) == NodeTraits::black())){
NodeTraits::set_color(w, NodeTraits::red()); NodeTraits::set_color(w, NodeTraits::red());
x = x_parent; x = x_parent;
x_parent = NodeTraits::get_parent(x_parent); x_parent = NodeTraits::get_parent(x_parent);
} }
else { else {
if(!NodeTraits::get_left(w) || NodeTraits::get_color(NodeTraits::get_left(w)) == NodeTraits::black()){ if(!w_left || NodeTraits::get_color(w_left) == NodeTraits::black()){
NodeTraits::set_color(NodeTraits::get_right(w), NodeTraits::black()); NodeTraits::set_color(NodeTraits::get_right(w), NodeTraits::black());
NodeTraits::set_color(w, NodeTraits::red()); NodeTraits::set_color(w, NodeTraits::red());
bstree_algo::rotate_left(w, header); bstree_algo::rotate_left(w, header);