forked from boostorg/intrusive
Optimized tree-rebalancing code to avoid redundant pointer updates.
This commit is contained in:
@@ -3797,6 +3797,8 @@ to be inserted in intrusive containers are allocated using `std::vector` or `std
|
||||
* Fixed bugs:
|
||||
* [@https://svn.boost.org/trac/boost/ticket/9332 #9332: ['"has_member_function_callable_with.hpp compile error on msvc-12.0"]].
|
||||
|
||||
* Optimized tree rebalancing code to avoid redundant assignments.
|
||||
|
||||
[endsect]
|
||||
|
||||
[section:release_notes_boost_1_55_00 Boost 1.55 Release]
|
||||
|
@@ -49,15 +49,6 @@ struct avltree_node_cloner
|
||||
}
|
||||
};
|
||||
|
||||
template<class NodeTraits>
|
||||
struct avltree_erase_fixup
|
||||
{
|
||||
typedef typename NodeTraits::node_ptr node_ptr;
|
||||
|
||||
void operator()(const node_ptr & to_erase, const node_ptr & successor)
|
||||
{ NodeTraits::set_balance(successor, NodeTraits::get_balance(to_erase)); }
|
||||
};
|
||||
|
||||
/// @endcond
|
||||
|
||||
//! avltree_algorithms is configured with a NodeTraits class, which encapsulates the
|
||||
@@ -225,7 +216,10 @@ class avltree_algorithms
|
||||
static node_ptr erase(const node_ptr & header, const node_ptr & z)
|
||||
{
|
||||
typename bstree_algo::data_for_rebalance info;
|
||||
bstree_algo::erase(header, z, avltree_erase_fixup<NodeTraits>(), info);
|
||||
bstree_algo::erase(header, z, info);
|
||||
if(info.y != z){
|
||||
NodeTraits::set_balance(info.y, NodeTraits::get_balance(z));
|
||||
}
|
||||
//Rebalance avltree
|
||||
rebalance_after_erasure(header, info.x, info.x_parent);
|
||||
return z;
|
||||
@@ -358,41 +352,92 @@ class avltree_algorithms
|
||||
|
||||
|
||||
/// @cond
|
||||
static bool verify(const node_ptr &header)
|
||||
{
|
||||
std::size_t height;
|
||||
std::size_t count;
|
||||
return verify_recursion(NodeTraits::get_parent(header), count, height);
|
||||
}
|
||||
|
||||
private:
|
||||
|
||||
static void rebalance_after_erasure(const node_ptr & header, const node_ptr & xnode, const node_ptr & xnode_parent)
|
||||
static bool verify_recursion(node_ptr n, std::size_t &count, std::size_t &height)
|
||||
{
|
||||
if (!n){
|
||||
count = 0;
|
||||
height = 0;
|
||||
return true;
|
||||
}
|
||||
std::size_t leftcount, rightcount;
|
||||
std::size_t leftheight, rightheight;
|
||||
if(!verify_recursion(NodeTraits::get_left (n), leftcount, leftheight) ||
|
||||
!verify_recursion(NodeTraits::get_right(n), rightcount, rightheight) ){
|
||||
return false;
|
||||
}
|
||||
count = 1u + leftcount + rightcount;
|
||||
height = 1u + (leftheight > rightheight ? leftheight : rightheight);
|
||||
|
||||
//If equal height, balance must be zero
|
||||
if(rightheight == leftheight){
|
||||
if(NodeTraits::get_balance(n) != NodeTraits::zero()){
|
||||
BOOST_ASSERT(0);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
//If right is taller than left, then the difference must be at least 1 and the balance positive
|
||||
else if(rightheight > leftheight){
|
||||
if(rightheight - leftheight > 1 ){
|
||||
BOOST_ASSERT(0);
|
||||
return false;
|
||||
}
|
||||
else if(NodeTraits::get_balance(n) != NodeTraits::positive()){
|
||||
BOOST_ASSERT(0);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
//If left is taller than right, then the difference must be at least 1 and the balance negative
|
||||
else{
|
||||
if(leftheight - rightheight > 1 ){
|
||||
BOOST_ASSERT(0);
|
||||
return false;
|
||||
}
|
||||
else if(NodeTraits::get_balance(n) != NodeTraits::negative()){
|
||||
BOOST_ASSERT(0);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
static void rebalance_after_erasure(const node_ptr & header, node_ptr x, node_ptr x_parent)
|
||||
{
|
||||
node_ptr x(xnode), x_parent(xnode_parent);
|
||||
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);
|
||||
node_ptr const x_parent_left(NodeTraits::get_left(x_parent));
|
||||
//Don't cache x_is_leftchild or similar because x can be null and
|
||||
//equal to both x_parent_left and x_parent_right
|
||||
const node_ptr x_parent_left (NodeTraits::get_left(x_parent));
|
||||
const node_ptr x_parent_right(NodeTraits::get_right(x_parent));
|
||||
|
||||
if(x_parent_balance == NodeTraits::zero()){
|
||||
NodeTraits::set_balance( x_parent
|
||||
, x == x_parent_left ? NodeTraits::positive() : NodeTraits::negative() );
|
||||
NodeTraits::set_balance( x_parent, x == x_parent_right ? NodeTraits::negative() : NodeTraits::positive() );
|
||||
break; // the height didn't change, let's stop here
|
||||
}
|
||||
else if(x_parent_balance == NodeTraits::negative()){
|
||||
if (x == x_parent_left) {
|
||||
if (x == x_parent_left) { ////x is left child or x and sibling are null
|
||||
NodeTraits::set_balance(x_parent, NodeTraits::zero()); // balanced
|
||||
x = x_parent;
|
||||
x_parent = NodeTraits::get_parent(x_parent);
|
||||
}
|
||||
else {
|
||||
// x is right child
|
||||
// a is left child
|
||||
node_ptr a = x_parent_left;
|
||||
BOOST_INTRUSIVE_INVARIANT_ASSERT(a);
|
||||
if (NodeTraits::get_balance(a) == NodeTraits::positive()) {
|
||||
// a MUST have a right child
|
||||
BOOST_INTRUSIVE_INVARIANT_ASSERT(NodeTraits::get_right(a));
|
||||
rotate_left_right(x_parent, header);
|
||||
x = NodeTraits::get_parent(x_parent);
|
||||
x_parent = NodeTraits::get_parent(x);
|
||||
// x is right child (x_parent_left is the left child)
|
||||
BOOST_INTRUSIVE_INVARIANT_ASSERT(x_parent_left);
|
||||
if (NodeTraits::get_balance(x_parent_left) == NodeTraits::positive()) {
|
||||
// x_parent_left MUST have a right child
|
||||
BOOST_INTRUSIVE_INVARIANT_ASSERT(NodeTraits::get_right(x_parent_left));
|
||||
x = avl_rotate_left_right(x_parent, x_parent_left, header);
|
||||
}
|
||||
else {
|
||||
rotate_right(x_parent, header);
|
||||
x = NodeTraits::get_parent(x_parent);
|
||||
x_parent = NodeTraits::get_parent(x);
|
||||
avl_rotate_right(x_parent, x_parent_left, header);
|
||||
x = x_parent_left;
|
||||
}
|
||||
|
||||
// if changed from negative to NodeTraits::positive(), no need to check above
|
||||
@@ -402,28 +447,22 @@ class avltree_algorithms
|
||||
}
|
||||
}
|
||||
else if(x_parent_balance == NodeTraits::positive()){
|
||||
if (x == NodeTraits::get_right(x_parent)) {
|
||||
if (x == x_parent_right) { //x is right child or x and sibling are null
|
||||
NodeTraits::set_balance(x_parent, NodeTraits::zero()); // balanced
|
||||
x = x_parent;
|
||||
x_parent = NodeTraits::get_parent(x_parent);
|
||||
}
|
||||
else {
|
||||
// x is left child
|
||||
// a is right child
|
||||
node_ptr a = NodeTraits::get_right(x_parent);
|
||||
BOOST_INTRUSIVE_INVARIANT_ASSERT(a);
|
||||
if (NodeTraits::get_balance(a) == NodeTraits::negative()) {
|
||||
// a MUST have then a left child
|
||||
BOOST_INTRUSIVE_INVARIANT_ASSERT(NodeTraits::get_left(a));
|
||||
rotate_right_left(x_parent, header);
|
||||
|
||||
x = NodeTraits::get_parent(x_parent);
|
||||
x_parent = NodeTraits::get_parent(x);
|
||||
// x is left child (x_parent_right is the right child)
|
||||
const node_ptr x_parent_right(NodeTraits::get_right(x_parent));
|
||||
BOOST_INTRUSIVE_INVARIANT_ASSERT(x_parent_right);
|
||||
if (NodeTraits::get_balance(x_parent_right) == NodeTraits::negative()) {
|
||||
// x_parent_right MUST have then a left child
|
||||
BOOST_INTRUSIVE_INVARIANT_ASSERT(NodeTraits::get_left(x_parent_right));
|
||||
x = avl_rotate_right_left(x_parent, x_parent_right, header);
|
||||
}
|
||||
else {
|
||||
rotate_left(x_parent, header);
|
||||
x = NodeTraits::get_parent(x_parent);
|
||||
x_parent = NodeTraits::get_parent(x);
|
||||
avl_rotate_left(x_parent, x_parent_right, header);
|
||||
x = x_parent_right;
|
||||
}
|
||||
// if changed from NodeTraits::positive() to negative, no need to check above
|
||||
if (NodeTraits::get_balance(x) == NodeTraits::negative()){
|
||||
@@ -434,44 +473,44 @@ class avltree_algorithms
|
||||
else{
|
||||
BOOST_INTRUSIVE_INVARIANT_ASSERT(false); // never reached
|
||||
}
|
||||
x_parent = NodeTraits::get_parent(x);
|
||||
}
|
||||
}
|
||||
|
||||
static void rebalance_after_insertion(const node_ptr & header, const node_ptr & xnode)
|
||||
static void rebalance_after_insertion(const node_ptr & header, node_ptr x)
|
||||
{
|
||||
node_ptr x(xnode);
|
||||
NodeTraits::set_balance(x, NodeTraits::zero());
|
||||
// Rebalance.
|
||||
for(node_ptr root = NodeTraits::get_parent(header); x != root; root = NodeTraits::get_parent(header)){
|
||||
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);
|
||||
const bool x_is_leftchild(x == x_parent_left);
|
||||
if(x_parent_balance == NodeTraits::zero()){
|
||||
// if x is left, parent will have parent->bal_factor = negative
|
||||
// else, parent->bal_factor = NodeTraits::positive()
|
||||
NodeTraits::set_balance( x_parent, x == x_parent_left
|
||||
? NodeTraits::negative() : NodeTraits::positive() );
|
||||
NodeTraits::set_balance( x_parent, x_is_leftchild ? NodeTraits::negative() : NodeTraits::positive() );
|
||||
x = x_parent;
|
||||
}
|
||||
else if(x_parent_balance == NodeTraits::positive()){
|
||||
// if x is a left child, parent->bal_factor = zero
|
||||
if (x == x_parent_left)
|
||||
if (x_is_leftchild)
|
||||
NodeTraits::set_balance(x_parent, NodeTraits::zero());
|
||||
else{ // x is a right child, needs rebalancing
|
||||
if (NodeTraits::get_balance(x) == NodeTraits::negative())
|
||||
rotate_right_left(x_parent, header);
|
||||
avl_rotate_right_left(x_parent, x, header);
|
||||
else
|
||||
rotate_left(x_parent, header);
|
||||
avl_rotate_left(x_parent, x, header);
|
||||
}
|
||||
break;
|
||||
}
|
||||
else if(x_parent_balance == NodeTraits::negative()){
|
||||
// if x is a left child, needs rebalancing
|
||||
if (x == x_parent_left) {
|
||||
if (x_is_leftchild) {
|
||||
if (NodeTraits::get_balance(x) == NodeTraits::positive())
|
||||
rotate_left_right(x_parent, header);
|
||||
avl_rotate_left_right(x_parent, x, header);
|
||||
else
|
||||
rotate_right(x_parent, header);
|
||||
avl_rotate_right(x_parent, x, header);
|
||||
}
|
||||
else
|
||||
NodeTraits::set_balance(x_parent, NodeTraits::zero());
|
||||
@@ -508,8 +547,8 @@ class avltree_algorithms
|
||||
}
|
||||
}
|
||||
|
||||
static void rotate_left_right(const node_ptr a, const node_ptr & hdr)
|
||||
{
|
||||
static node_ptr avl_rotate_left_right(const node_ptr a, const node_ptr a_oldleft, const node_ptr & hdr)
|
||||
{ // [note: 'a_oldleft' is 'b']
|
||||
// | | //
|
||||
// a(-2) c //
|
||||
// / \ / \ //
|
||||
@@ -517,16 +556,19 @@ class avltree_algorithms
|
||||
// (pos)b [g] b a //
|
||||
// / \ / \ / \ //
|
||||
// [d] c [d] e f [g] //
|
||||
// / \ //
|
||||
// e f //
|
||||
node_ptr b = NodeTraits::get_left(a), c = NodeTraits::get_right(b);
|
||||
bstree_algo::rotate_left(b, hdr);
|
||||
bstree_algo::rotate_right(a, hdr);
|
||||
left_right_balancing(a, b, c);
|
||||
// / \ //
|
||||
// e f //
|
||||
const node_ptr c = NodeTraits::get_right(a_oldleft);
|
||||
bstree_algo::rotate_left_no_parent_fix(a_oldleft, c);
|
||||
//No need to link c with a [NodeTraits::set_parent(c, a) + NodeTraits::set_left(a, c)]
|
||||
//as c is not root and another rotation is coming
|
||||
bstree_algo::rotate_right(a, c, NodeTraits::get_parent(a), hdr);
|
||||
left_right_balancing(a, a_oldleft, c);
|
||||
return c;
|
||||
}
|
||||
|
||||
static void rotate_right_left(const node_ptr a, const node_ptr & hdr)
|
||||
{
|
||||
static node_ptr avl_rotate_right_left(const node_ptr a, const node_ptr a_oldright, const node_ptr & hdr)
|
||||
{ // [note: 'a_oldright' is 'b']
|
||||
// | | //
|
||||
// a(pos) c //
|
||||
// / \ / \ //
|
||||
@@ -536,41 +578,42 @@ class avltree_algorithms
|
||||
// c [g] [d] e f [g] //
|
||||
// / \ //
|
||||
// e f //
|
||||
node_ptr b = NodeTraits::get_right(a), c = NodeTraits::get_left(b);
|
||||
bstree_algo::rotate_right(b, hdr);
|
||||
bstree_algo::rotate_left(a, hdr);
|
||||
left_right_balancing(b, a, c);
|
||||
const node_ptr c (NodeTraits::get_left(a_oldright));
|
||||
bstree_algo::rotate_right_no_parent_fix(a_oldright, c);
|
||||
//No need to link c with a [NodeTraits::set_parent(c, a) + NodeTraits::set_right(a, c)]
|
||||
//as c is not root and another rotation is coming.
|
||||
bstree_algo::rotate_left(a, c, NodeTraits::get_parent(a), hdr);
|
||||
left_right_balancing(a_oldright, a, c);
|
||||
return c;
|
||||
}
|
||||
|
||||
static void rotate_left(const node_ptr x, const node_ptr & hdr)
|
||||
static void avl_rotate_left(const node_ptr &x, const node_ptr &x_oldright, const node_ptr & hdr)
|
||||
{
|
||||
const node_ptr y = NodeTraits::get_right(x);
|
||||
bstree_algo::rotate_left(x, hdr);
|
||||
bstree_algo::rotate_left(x, x_oldright, NodeTraits::get_parent(x), hdr);
|
||||
|
||||
// reset the balancing factor
|
||||
if (NodeTraits::get_balance(y) == NodeTraits::positive()) {
|
||||
if (NodeTraits::get_balance(x_oldright) == NodeTraits::positive()) {
|
||||
NodeTraits::set_balance(x, NodeTraits::zero());
|
||||
NodeTraits::set_balance(y, NodeTraits::zero());
|
||||
NodeTraits::set_balance(x_oldright, NodeTraits::zero());
|
||||
}
|
||||
else { // this doesn't happen during insertions
|
||||
NodeTraits::set_balance(x, NodeTraits::positive());
|
||||
NodeTraits::set_balance(y, NodeTraits::negative());
|
||||
NodeTraits::set_balance(x_oldright, NodeTraits::negative());
|
||||
}
|
||||
}
|
||||
|
||||
static void rotate_right(const node_ptr x, const node_ptr & hdr)
|
||||
static void avl_rotate_right(const node_ptr &x, const node_ptr &x_oldleft, const node_ptr & hdr)
|
||||
{
|
||||
const node_ptr y = NodeTraits::get_left(x);
|
||||
bstree_algo::rotate_right(x, hdr);
|
||||
bstree_algo::rotate_right(x, x_oldleft, NodeTraits::get_parent(x), hdr);
|
||||
|
||||
// reset the balancing factor
|
||||
if (NodeTraits::get_balance(y) == NodeTraits::negative()) {
|
||||
if (NodeTraits::get_balance(x_oldleft) == NodeTraits::negative()) {
|
||||
NodeTraits::set_balance(x, NodeTraits::zero());
|
||||
NodeTraits::set_balance(y, NodeTraits::zero());
|
||||
NodeTraits::set_balance(x_oldleft, NodeTraits::zero());
|
||||
}
|
||||
else { // this doesn't happen during insertions
|
||||
NodeTraits::set_balance(x, NodeTraits::negative());
|
||||
NodeTraits::set_balance(y, NodeTraits::positive());
|
||||
NodeTraits::set_balance(x_oldleft, NodeTraits::positive());
|
||||
}
|
||||
}
|
||||
|
||||
|
@@ -549,7 +549,7 @@ class bstree_algorithms
|
||||
//! <b>Complexity</b>: Logarithmic to the size of the subtree.
|
||||
//!
|
||||
//! <b>Throws</b>: Nothing.
|
||||
static node_ptr minimum (node_ptr node)
|
||||
static node_ptr minimum(node_ptr node)
|
||||
{
|
||||
for(node_ptr p_left = NodeTraits::get_left(node)
|
||||
;p_left
|
||||
@@ -1062,16 +1062,12 @@ class bstree_algorithms
|
||||
//Since we've found the upper bound there is no other value with the same key if:
|
||||
// - There is no previous node
|
||||
// - The previous node is less than the key
|
||||
if(!prev || comp(prev, key)){
|
||||
const bool not_present = !prev || comp(prev, key);
|
||||
if(not_present){
|
||||
commit_data.link_left = left_child;
|
||||
commit_data.node = y;
|
||||
return std::pair<node_ptr, bool>(node_ptr(), true);
|
||||
}
|
||||
//If the previous value was not less than key, it means that it's equal
|
||||
//(because we've checked the upper bound)
|
||||
else{
|
||||
return std::pair<node_ptr, bool>(prev, false);
|
||||
}
|
||||
return std::pair<node_ptr, bool>(prev, not_present);
|
||||
}
|
||||
|
||||
//! <b>Requires</b>: "header" must be the header node of a tree.
|
||||
@@ -1362,7 +1358,7 @@ class bstree_algorithms
|
||||
static void erase(const node_ptr & header, const node_ptr & z)
|
||||
{
|
||||
data_for_rebalance ignored;
|
||||
erase_impl(header, z, ignored);
|
||||
erase(header, z, ignored);
|
||||
}
|
||||
|
||||
//! <b>Requires</b>: node is a tree node but not the header.
|
||||
@@ -1447,6 +1443,88 @@ class bstree_algorithms
|
||||
}
|
||||
|
||||
protected:
|
||||
static void erase(const node_ptr & header, const node_ptr & z, data_for_rebalance &info)
|
||||
{
|
||||
node_ptr y(z);
|
||||
node_ptr x;
|
||||
const node_ptr z_left(NodeTraits::get_left(z));
|
||||
const node_ptr z_right(NodeTraits::get_right(z));
|
||||
|
||||
if(!z_left){
|
||||
x = z_right; // x might be null.
|
||||
}
|
||||
else if(!z_right){ // z has exactly one non-null child. y == z.
|
||||
x = z_left; // x is not null.
|
||||
BOOST_ASSERT(x);
|
||||
}
|
||||
else{ //make y != z
|
||||
// y = find z's successor
|
||||
y = bstree_algorithms::minimum(z_right);
|
||||
x = NodeTraits::get_right(y); // x might be null.
|
||||
}
|
||||
|
||||
node_ptr x_parent;
|
||||
const node_ptr z_parent(NodeTraits::get_parent(z));
|
||||
const bool z_is_leftchild(NodeTraits::get_left(z_parent) == z);
|
||||
|
||||
if(y != z){ //has two children and y is the minimum of z
|
||||
//y is z's successor and it has a null left child.
|
||||
//x is the right child of y (it can be null)
|
||||
//Relink y in place of z and link x with y's old parent
|
||||
NodeTraits::set_parent(z_left, y);
|
||||
NodeTraits::set_left(y, z_left);
|
||||
if(y != z_right){
|
||||
//Link y with the right tree of z
|
||||
NodeTraits::set_right(y, z_right);
|
||||
NodeTraits::set_parent(z_right, y);
|
||||
//Link x with y's old parent (y must be a left child)
|
||||
x_parent = NodeTraits::get_parent(y);
|
||||
BOOST_ASSERT(NodeTraits::get_left(x_parent) == y);
|
||||
if(x)
|
||||
NodeTraits::set_parent(x, x_parent);
|
||||
//Since y was the successor and not the right child of z, it must be a left child
|
||||
NodeTraits::set_left(x_parent, x);
|
||||
}
|
||||
else{ //y was the right child of y so no need to fix x's position
|
||||
x_parent = y;
|
||||
}
|
||||
NodeTraits::set_parent(y, z_parent);
|
||||
bstree_algorithms::set_child(header, y, z_parent, z_is_leftchild);
|
||||
}
|
||||
else { // z has zero or one child, x is one child (it can be null)
|
||||
//Just link x to z's parent
|
||||
x_parent = z_parent;
|
||||
if(x)
|
||||
NodeTraits::set_parent(x, z_parent);
|
||||
bstree_algorithms::set_child(header, x, z_parent, z_is_leftchild);
|
||||
|
||||
//Now update leftmost/rightmost in case z was one of them
|
||||
if(NodeTraits::get_left(header) == z){
|
||||
//z_left must be null because z is the leftmost
|
||||
BOOST_ASSERT(!z_left);
|
||||
NodeTraits::set_left(header, !z_right ?
|
||||
z_parent : // makes leftmost == header if z == root
|
||||
bstree_algorithms::minimum(z_right));
|
||||
}
|
||||
if(NodeTraits::get_right(header) == z){
|
||||
//z_right must be null because z is the rightmost
|
||||
BOOST_ASSERT(!z_right);
|
||||
NodeTraits::set_right(header, !z_left ?
|
||||
z_parent : // makes rightmost == header if z == root
|
||||
bstree_algorithms::maximum(z_left));
|
||||
}
|
||||
}
|
||||
|
||||
//If z had 0/1 child, y == z and one of its children (and maybe null)
|
||||
//If z had 2 children, y is the successor of z and x is the right child of y
|
||||
info.x = x;
|
||||
info.y = y;
|
||||
//If z had 0/1 child, x_parent is the new parent of the old right child of y (z's successor)
|
||||
//If z had 2 children, x_parent is the new parent of y (z_parent)
|
||||
BOOST_ASSERT(!x || NodeTraits::get_parent(x) == x_parent);
|
||||
info.x_parent = x_parent;
|
||||
}
|
||||
|
||||
//! <b>Requires</b>: node is a node of the tree but it's not the header.
|
||||
//!
|
||||
//! <b>Effects</b>: Returns the number of nodes of the subtree.
|
||||
@@ -1510,83 +1588,6 @@ class bstree_algorithms
|
||||
static bool is_right_child(const node_ptr & p)
|
||||
{ return NodeTraits::get_right(NodeTraits::get_parent(p)) == p; }
|
||||
|
||||
template<class F>
|
||||
static void erase(const node_ptr & header, const node_ptr & z, F z_and_successor_fixup, data_for_rebalance &info)
|
||||
{
|
||||
erase_impl(header, z, info);
|
||||
if(info.y != z){
|
||||
z_and_successor_fixup(z, info.y);
|
||||
}
|
||||
}
|
||||
|
||||
//Fix header and own's parent data when replacing x with own, providing own's old data with parent
|
||||
static void replace_own_impl(const node_ptr & own, const node_ptr & x, const node_ptr & header, const node_ptr & own_parent, bool own_was_left)
|
||||
{
|
||||
if(NodeTraits::get_parent(header) == own)
|
||||
NodeTraits::set_parent(header, x);
|
||||
else if(own_was_left)
|
||||
NodeTraits::set_left(own_parent, x);
|
||||
else
|
||||
NodeTraits::set_right(own_parent, x);
|
||||
}
|
||||
|
||||
//Fix header and own's parent data when replacing x with own, supposing own
|
||||
//links with its parent are still ok
|
||||
static void replace_own(const node_ptr & own, const node_ptr & x, const node_ptr & header)
|
||||
{
|
||||
node_ptr own_parent(NodeTraits::get_parent(own));
|
||||
bool own_is_left(NodeTraits::get_left(own_parent) == own);
|
||||
replace_own_impl(own, x, header, own_parent, own_is_left);
|
||||
}
|
||||
|
||||
// rotate parent p to left (no header and p's parent fixup)
|
||||
static node_ptr rotate_left(const node_ptr & p)
|
||||
{
|
||||
node_ptr x(NodeTraits::get_right(p));
|
||||
node_ptr x_left(NodeTraits::get_left(x));
|
||||
NodeTraits::set_right(p, x_left);
|
||||
if(x_left){
|
||||
NodeTraits::set_parent(x_left, p);
|
||||
}
|
||||
NodeTraits::set_left(x, p);
|
||||
NodeTraits::set_parent(p, x);
|
||||
return x;
|
||||
}
|
||||
|
||||
// rotate parent p to left (with header and p's parent fixup)
|
||||
static void rotate_left(const node_ptr & p, const node_ptr & header)
|
||||
{
|
||||
bool p_was_left(is_left_child(p));
|
||||
node_ptr p_old_parent(NodeTraits::get_parent(p));
|
||||
node_ptr x(rotate_left(p));
|
||||
NodeTraits::set_parent(x, p_old_parent);
|
||||
replace_own_impl(p, x, header, p_old_parent, p_was_left);
|
||||
}
|
||||
|
||||
// rotate parent p to right (no header and p's parent fixup)
|
||||
static node_ptr rotate_right(const node_ptr & p)
|
||||
{
|
||||
node_ptr x(NodeTraits::get_left(p));
|
||||
node_ptr x_right(NodeTraits::get_right(x));
|
||||
NodeTraits::set_left(p, x_right);
|
||||
if(x_right){
|
||||
NodeTraits::set_parent(x_right, p);
|
||||
}
|
||||
NodeTraits::set_right(x, p);
|
||||
NodeTraits::set_parent(p, x);
|
||||
return x;
|
||||
}
|
||||
|
||||
// rotate parent p to right (with header and p's parent fixup)
|
||||
static void rotate_right(const node_ptr & p, const node_ptr & header)
|
||||
{
|
||||
bool p_was_left(is_left_child(p));
|
||||
node_ptr p_old_parent(NodeTraits::get_parent(p));
|
||||
node_ptr x(rotate_right(p));
|
||||
NodeTraits::set_parent(x, p_old_parent);
|
||||
replace_own_impl(p, x, header, p_old_parent, p_was_left);
|
||||
}
|
||||
|
||||
static void insert_before_check
|
||||
(const node_ptr &header, const node_ptr & pos
|
||||
, insert_commit_data &commit_data
|
||||
@@ -1668,12 +1669,40 @@ class bstree_algorithms
|
||||
template<class NodePtrCompare>
|
||||
static void insert_equal_upper_bound_check
|
||||
(const node_ptr & h, const node_ptr & new_node, NodePtrCompare comp, insert_commit_data & commit_data, std::size_t *pdepth = 0)
|
||||
{ insert_equal_check_impl(true, h, new_node, comp, commit_data, pdepth); }
|
||||
{
|
||||
std::size_t depth = 0;
|
||||
node_ptr y(h);
|
||||
node_ptr x(NodeTraits::get_parent(y));
|
||||
|
||||
while(x){
|
||||
++depth;
|
||||
y = x;
|
||||
x = comp(new_node, x) ?
|
||||
NodeTraits::get_left(x) : NodeTraits::get_right(x);
|
||||
}
|
||||
if(pdepth) *pdepth = depth;
|
||||
commit_data.link_left = (y == h) || comp(new_node, y);
|
||||
commit_data.node = y;
|
||||
}
|
||||
|
||||
template<class NodePtrCompare>
|
||||
static void insert_equal_lower_bound_check
|
||||
(const node_ptr & h, const node_ptr & new_node, NodePtrCompare comp, insert_commit_data & commit_data, std::size_t *pdepth = 0)
|
||||
{ insert_equal_check_impl(false, h, new_node, comp, commit_data, pdepth); }
|
||||
{
|
||||
std::size_t depth = 0;
|
||||
node_ptr y(h);
|
||||
node_ptr x(NodeTraits::get_parent(y));
|
||||
|
||||
while(x){
|
||||
++depth;
|
||||
y = x;
|
||||
x = !comp(x, new_node) ?
|
||||
NodeTraits::get_left(x) : NodeTraits::get_right(x);
|
||||
}
|
||||
if(pdepth) *pdepth = depth;
|
||||
commit_data.link_left = (y == h) || !comp(y, new_node);
|
||||
commit_data.node = y;
|
||||
}
|
||||
|
||||
static void insert_commit
|
||||
(const node_ptr & header, const node_ptr & new_node, const insert_commit_data &commit_data)
|
||||
@@ -1701,7 +1730,61 @@ class bstree_algorithms
|
||||
NodeTraits::set_left(new_node, node_ptr());
|
||||
}
|
||||
|
||||
//Fix header and own's parent data when replacing x with own, providing own's old data with parent
|
||||
static void set_child(const node_ptr & header, const node_ptr & new_child, const node_ptr & new_parent, const bool link_left)
|
||||
{
|
||||
if(new_parent == header)
|
||||
NodeTraits::set_parent(header, new_child);
|
||||
else if(link_left)
|
||||
NodeTraits::set_left(new_parent, new_child);
|
||||
else
|
||||
NodeTraits::set_right(new_parent, new_child);
|
||||
}
|
||||
|
||||
// rotate p to left (no header and p's parent fixup)
|
||||
static void rotate_left_no_parent_fix(const node_ptr & p, const node_ptr &p_right)
|
||||
{
|
||||
node_ptr p_right_left(NodeTraits::get_left(p_right));
|
||||
NodeTraits::set_right(p, p_right_left);
|
||||
if(p_right_left){
|
||||
NodeTraits::set_parent(p_right_left, p);
|
||||
}
|
||||
NodeTraits::set_left(p_right, p);
|
||||
NodeTraits::set_parent(p, p_right);
|
||||
}
|
||||
|
||||
// rotate p to left (with header and p's parent fixup)
|
||||
static void rotate_left(const node_ptr & p, const node_ptr & p_right, const node_ptr & p_parent, const node_ptr & header)
|
||||
{
|
||||
const bool p_was_left(NodeTraits::get_left(p_parent) == p);
|
||||
rotate_left_no_parent_fix(p, p_right);
|
||||
NodeTraits::set_parent(p_right, p_parent);
|
||||
set_child(header, p_right, p_parent, p_was_left);
|
||||
}
|
||||
|
||||
// rotate p to right (no header and p's parent fixup)
|
||||
static void rotate_right_no_parent_fix(const node_ptr & p, const node_ptr &p_left)
|
||||
{
|
||||
node_ptr p_left_right(NodeTraits::get_right(p_left));
|
||||
NodeTraits::set_left(p, p_left_right);
|
||||
if(p_left_right){
|
||||
NodeTraits::set_parent(p_left_right, p);
|
||||
}
|
||||
NodeTraits::set_right(p_left, p);
|
||||
NodeTraits::set_parent(p, p_left);
|
||||
}
|
||||
|
||||
// rotate p to right (with header and p's parent fixup)
|
||||
static void rotate_right(const node_ptr & p, const node_ptr & p_left, const node_ptr & p_parent, const node_ptr & header)
|
||||
{
|
||||
const bool p_was_left(NodeTraits::get_left(p_parent) == p);
|
||||
rotate_right_no_parent_fix(p, p_left);
|
||||
NodeTraits::set_parent(p_left, p_parent);
|
||||
set_child(header, p_left, p_parent, p_was_left);
|
||||
}
|
||||
|
||||
private:
|
||||
|
||||
static void subtree_to_vine(node_ptr vine_tail, std::size_t &size)
|
||||
{
|
||||
//Inspired by LibAVL:
|
||||
@@ -1913,98 +1996,6 @@ class bstree_algorithms
|
||||
}
|
||||
return y;
|
||||
}
|
||||
|
||||
|
||||
template<class NodePtrCompare>
|
||||
static void insert_equal_check_impl
|
||||
(bool upper, const node_ptr & h, const node_ptr & new_node, NodePtrCompare comp, insert_commit_data & commit_data, std::size_t *pdepth = 0)
|
||||
{
|
||||
std::size_t depth = 0;
|
||||
node_ptr y(h);
|
||||
node_ptr x(NodeTraits::get_parent(y));
|
||||
bool link_left;
|
||||
|
||||
if(upper){
|
||||
while(x){
|
||||
++depth;
|
||||
y = x;
|
||||
x = comp(new_node, x) ?
|
||||
NodeTraits::get_left(x) : NodeTraits::get_right(x);
|
||||
}
|
||||
link_left = (y == h) || comp(new_node, y);
|
||||
}
|
||||
else{
|
||||
while(x){
|
||||
++depth;
|
||||
y = x;
|
||||
x = !comp(x, new_node) ?
|
||||
NodeTraits::get_left(x) : NodeTraits::get_right(x);
|
||||
}
|
||||
link_left = (y == h) || !comp(y, new_node);
|
||||
}
|
||||
|
||||
commit_data.link_left = link_left;
|
||||
commit_data.node = y;
|
||||
if(pdepth) *pdepth = depth;
|
||||
}
|
||||
|
||||
static void erase_impl(const node_ptr & header, const node_ptr & z, data_for_rebalance &info)
|
||||
{
|
||||
node_ptr y(z);
|
||||
node_ptr x;
|
||||
node_ptr x_parent = node_ptr();
|
||||
node_ptr z_left(NodeTraits::get_left(z));
|
||||
node_ptr z_right(NodeTraits::get_right(z));
|
||||
if(!z_left){
|
||||
x = z_right; // x might be null.
|
||||
}
|
||||
else if(!z_right){ // z has exactly one non-null child. y == z.
|
||||
x = z_left; // x is not null.
|
||||
}
|
||||
else{
|
||||
// find z's successor
|
||||
y = bstree_algorithms::minimum (z_right);
|
||||
x = NodeTraits::get_right(y); // x might be null.
|
||||
}
|
||||
|
||||
if(y != z){
|
||||
// relink y in place of z. y is z's successor
|
||||
NodeTraits::set_parent(NodeTraits::get_left(z), y);
|
||||
NodeTraits::set_left(y, NodeTraits::get_left(z));
|
||||
if(y != NodeTraits::get_right(z)){
|
||||
x_parent = NodeTraits::get_parent(y);
|
||||
if(x)
|
||||
NodeTraits::set_parent(x, x_parent);
|
||||
NodeTraits::set_left(x_parent, x); // y must be a child of left_
|
||||
NodeTraits::set_right(y, NodeTraits::get_right(z));
|
||||
NodeTraits::set_parent(NodeTraits::get_right(z), y);
|
||||
}
|
||||
else
|
||||
x_parent = y;
|
||||
bstree_algorithms::replace_own (z, y, header);
|
||||
NodeTraits::set_parent(y, NodeTraits::get_parent(z));
|
||||
}
|
||||
else { // y == z --> z has only one child, or void
|
||||
x_parent = NodeTraits::get_parent(z);
|
||||
if(x)
|
||||
NodeTraits::set_parent(x, x_parent);
|
||||
bstree_algorithms::replace_own (z, x, header);
|
||||
if(NodeTraits::get_left(header) == z){
|
||||
NodeTraits::set_left(header, !NodeTraits::get_right(z) ? // z->get_left() must be null also
|
||||
NodeTraits::get_parent(z) : // makes leftmost == header if z == root
|
||||
bstree_algorithms::minimum (x));
|
||||
}
|
||||
if(NodeTraits::get_right(header) == z){
|
||||
NodeTraits::set_right(header, !NodeTraits::get_left(z) ? // z->get_right() must be null also
|
||||
NodeTraits::get_parent(z) : // makes rightmost == header if z == root
|
||||
bstree_algorithms::maximum(x));
|
||||
}
|
||||
}
|
||||
|
||||
info.x = x;
|
||||
info.x_parent = x_parent;
|
||||
info.y = y;
|
||||
}
|
||||
};
|
||||
|
||||
/// @cond
|
||||
|
@@ -57,21 +57,6 @@ struct rbtree_node_cloner
|
||||
}
|
||||
};
|
||||
|
||||
template<class NodeTraits>
|
||||
struct rbtree_erase_fixup
|
||||
{
|
||||
typedef typename NodeTraits::node_ptr node_ptr;
|
||||
typedef typename NodeTraits::color color;
|
||||
|
||||
void operator()(const node_ptr & to_erase, const node_ptr & successor)
|
||||
{
|
||||
//Swap color of y and z
|
||||
color tmp(NodeTraits::get_color(successor));
|
||||
NodeTraits::set_color(successor, NodeTraits::get_color(to_erase));
|
||||
NodeTraits::set_color(to_erase, tmp);
|
||||
}
|
||||
};
|
||||
|
||||
#endif //#ifndef BOOST_INTRUSIVE_DOXYGEN_INVOKED
|
||||
|
||||
//! rbtree_algorithms provides basic algorithms to manipulate
|
||||
@@ -245,10 +230,18 @@ class rbtree_algorithms
|
||||
static node_ptr erase(const node_ptr & header, const node_ptr & z)
|
||||
{
|
||||
typename bstree_algo::data_for_rebalance info;
|
||||
bstree_algo::erase(header, z, rbtree_erase_fixup<NodeTraits>(), info);
|
||||
bstree_algo::erase(header, z, info);
|
||||
|
||||
//Rebalance rbtree
|
||||
if(NodeTraits::get_color(z) != NodeTraits::red()){
|
||||
color new_z_color;
|
||||
if(info.y != z){
|
||||
new_z_color = NodeTraits::get_color(info.y);
|
||||
NodeTraits::set_color(info.y, NodeTraits::get_color(z));
|
||||
}
|
||||
else{
|
||||
new_z_color = NodeTraits::get_color(z);
|
||||
}
|
||||
//Rebalance rbtree if needed
|
||||
if(new_z_color != NodeTraits::red()){
|
||||
rebalance_after_erasure(header, info.x, info.x_parent);
|
||||
}
|
||||
return z;
|
||||
@@ -387,14 +380,20 @@ class rbtree_algorithms
|
||||
|
||||
static void rebalance_after_erasure(const node_ptr & header, node_ptr x, node_ptr x_parent)
|
||||
{
|
||||
while(x != NodeTraits::get_parent(header) && (!x || NodeTraits::get_color(x) == NodeTraits::black())){
|
||||
if(x == NodeTraits::get_left(x_parent)){
|
||||
while(1){
|
||||
if(x_parent == header || (x && NodeTraits::get_color(x) != NodeTraits::black())){
|
||||
break;
|
||||
}
|
||||
//Don't cache x_is_leftchild or similar because x can be null and
|
||||
//equal to both x_parent_left and x_parent_right
|
||||
const node_ptr x_parent_left(NodeTraits::get_left(x_parent));
|
||||
if(x == x_parent_left){ //x is left child
|
||||
node_ptr w = NodeTraits::get_right(x_parent);
|
||||
BOOST_ASSERT(w);
|
||||
if(NodeTraits::get_color(w) == NodeTraits::red()){
|
||||
NodeTraits::set_color(w, NodeTraits::black());
|
||||
NodeTraits::set_color(x_parent, NodeTraits::red());
|
||||
bstree_algo::rotate_left(x_parent, header);
|
||||
bstree_algo::rotate_left(x_parent, w, NodeTraits::get_parent(x_parent), header);
|
||||
w = NodeTraits::get_right(x_parent);
|
||||
}
|
||||
node_ptr const w_left (NodeTraits::get_left(w));
|
||||
@@ -407,26 +406,27 @@ class rbtree_algorithms
|
||||
}
|
||||
else {
|
||||
if(!w_right || NodeTraits::get_color(w_right) == NodeTraits::black()){
|
||||
NodeTraits::set_color(NodeTraits::get_left(w), NodeTraits::black());
|
||||
NodeTraits::set_color(w_left, NodeTraits::black());
|
||||
NodeTraits::set_color(w, NodeTraits::red());
|
||||
bstree_algo::rotate_right(w, header);
|
||||
bstree_algo::rotate_right(w, w_left, NodeTraits::get_parent(w), header);
|
||||
w = NodeTraits::get_right(x_parent);
|
||||
}
|
||||
NodeTraits::set_color(w, NodeTraits::get_color(x_parent));
|
||||
NodeTraits::set_color(x_parent, NodeTraits::black());
|
||||
if(NodeTraits::get_right(w))
|
||||
NodeTraits::set_color(NodeTraits::get_right(w), NodeTraits::black());
|
||||
bstree_algo::rotate_left(x_parent, header);
|
||||
const node_ptr new_wright(NodeTraits::get_right(w));
|
||||
if(new_wright)
|
||||
NodeTraits::set_color(new_wright, NodeTraits::black());
|
||||
bstree_algo::rotate_left(x_parent, NodeTraits::get_right(x_parent), NodeTraits::get_parent(x_parent), header);
|
||||
break;
|
||||
}
|
||||
}
|
||||
else {
|
||||
// same as above, with right_ <-> left_.
|
||||
node_ptr w = NodeTraits::get_left(x_parent);
|
||||
node_ptr w = x_parent_left;
|
||||
if(NodeTraits::get_color(w) == NodeTraits::red()){
|
||||
NodeTraits::set_color(w, NodeTraits::black());
|
||||
NodeTraits::set_color(x_parent, NodeTraits::red());
|
||||
bstree_algo::rotate_right(x_parent, header);
|
||||
bstree_algo::rotate_right(x_parent, w, NodeTraits::get_parent(x_parent), header);
|
||||
w = NodeTraits::get_left(x_parent);
|
||||
}
|
||||
node_ptr const w_left (NodeTraits::get_left(w));
|
||||
@@ -439,16 +439,17 @@ class rbtree_algorithms
|
||||
}
|
||||
else {
|
||||
if(!w_left || NodeTraits::get_color(w_left) == NodeTraits::black()){
|
||||
NodeTraits::set_color(NodeTraits::get_right(w), NodeTraits::black());
|
||||
NodeTraits::set_color(w_right, NodeTraits::black());
|
||||
NodeTraits::set_color(w, NodeTraits::red());
|
||||
bstree_algo::rotate_left(w, header);
|
||||
bstree_algo::rotate_left(w, w_right, NodeTraits::get_parent(w), header);
|
||||
w = NodeTraits::get_left(x_parent);
|
||||
}
|
||||
NodeTraits::set_color(w, NodeTraits::get_color(x_parent));
|
||||
NodeTraits::set_color(x_parent, NodeTraits::black());
|
||||
if(NodeTraits::get_left(w))
|
||||
NodeTraits::set_color(NodeTraits::get_left(w), NodeTraits::black());
|
||||
bstree_algo::rotate_right(x_parent, header);
|
||||
const node_ptr new_wleft(NodeTraits::get_left(w));
|
||||
if(new_wleft)
|
||||
NodeTraits::set_color(new_wleft, NodeTraits::black());
|
||||
bstree_algo::rotate_right(x_parent, NodeTraits::get_left(x_parent), NodeTraits::get_parent(x_parent), header);
|
||||
break;
|
||||
}
|
||||
}
|
||||
@@ -460,48 +461,49 @@ class rbtree_algorithms
|
||||
static void rebalance_after_insertion(const node_ptr & header, node_ptr p)
|
||||
{
|
||||
NodeTraits::set_color(p, NodeTraits::red());
|
||||
while(p != NodeTraits::get_parent(header) && NodeTraits::get_color(NodeTraits::get_parent(p)) == NodeTraits::red()){
|
||||
while(1){
|
||||
node_ptr p_parent(NodeTraits::get_parent(p));
|
||||
node_ptr p_parent_parent(NodeTraits::get_parent(p_parent));
|
||||
if(bstree_algo::is_left_child(p_parent)){
|
||||
node_ptr x = NodeTraits::get_right(p_parent_parent);
|
||||
if(x && NodeTraits::get_color(x) == NodeTraits::red()){
|
||||
NodeTraits::set_color(p_parent, NodeTraits::black());
|
||||
NodeTraits::set_color(p_parent_parent, NodeTraits::red());
|
||||
NodeTraits::set_color(x, NodeTraits::black());
|
||||
p = p_parent_parent;
|
||||
}
|
||||
else {
|
||||
if(!bstree_algo::is_left_child(p)){
|
||||
p = p_parent;
|
||||
bstree_algo::rotate_left(p, header);
|
||||
}
|
||||
node_ptr new_p_parent(NodeTraits::get_parent(p));
|
||||
node_ptr new_p_parent_parent(NodeTraits::get_parent(new_p_parent));
|
||||
NodeTraits::set_color(new_p_parent, NodeTraits::black());
|
||||
NodeTraits::set_color(new_p_parent_parent, NodeTraits::red());
|
||||
bstree_algo::rotate_right(new_p_parent_parent, header);
|
||||
}
|
||||
const node_ptr p_grandparent(NodeTraits::get_parent(p_parent));
|
||||
if(p_parent == header || NodeTraits::get_color(p_parent) == NodeTraits::black() || p_grandparent == header){
|
||||
break;
|
||||
}
|
||||
else{
|
||||
node_ptr x = NodeTraits::get_left(p_parent_parent);
|
||||
if(x && NodeTraits::get_color(x) == NodeTraits::red()){
|
||||
NodeTraits::set_color(p_parent, NodeTraits::black());
|
||||
NodeTraits::set_color(p_parent_parent, NodeTraits::red());
|
||||
NodeTraits::set_color(x, NodeTraits::black());
|
||||
p = p_parent_parent;
|
||||
}
|
||||
else{
|
||||
if(bstree_algo::is_left_child(p)){
|
||||
p = p_parent;
|
||||
bstree_algo::rotate_right(p, header);
|
||||
|
||||
NodeTraits::set_color(p_grandparent, NodeTraits::red());
|
||||
node_ptr const p_grandparent_left (NodeTraits::get_left (p_grandparent));
|
||||
bool const p_parent_is_left_child = p_parent == p_grandparent_left;
|
||||
node_ptr const x(p_parent_is_left_child ? NodeTraits::get_right(p_grandparent) : p_grandparent_left);
|
||||
|
||||
if(x && NodeTraits::get_color(x) == NodeTraits::red()){
|
||||
NodeTraits::set_color(x, NodeTraits::black());
|
||||
NodeTraits::set_color(p_parent, NodeTraits::black());
|
||||
p = p_grandparent;
|
||||
}
|
||||
else{ //Final step
|
||||
const bool p_is_left_child(NodeTraits::get_left(p_parent) == p);
|
||||
if(p_parent_is_left_child){ //p_parent is left child
|
||||
if(!p_is_left_child){ //p is right child
|
||||
bstree_algo::rotate_left_no_parent_fix(p_parent, p);
|
||||
//No need to link p and p_grandparent:
|
||||
// [NodeTraits::set_parent(p, p_grandparent) + NodeTraits::set_left(p_grandparent, p)]
|
||||
//as p_grandparent is not the header, another rotation is coming and p_parent
|
||||
//will be the left child of p_grandparent
|
||||
p_parent = p;
|
||||
}
|
||||
node_ptr new_p_parent(NodeTraits::get_parent(p));
|
||||
node_ptr new_p_parent_parent(NodeTraits::get_parent(new_p_parent));
|
||||
NodeTraits::set_color(new_p_parent, NodeTraits::black());
|
||||
NodeTraits::set_color(new_p_parent_parent, NodeTraits::red());
|
||||
bstree_algo::rotate_left(new_p_parent_parent, header);
|
||||
bstree_algo::rotate_right(p_grandparent, p_parent, NodeTraits::get_parent(p_grandparent), header);
|
||||
}
|
||||
else{ //p_parent is right child
|
||||
if(p_is_left_child){ //p is left child
|
||||
bstree_algo::rotate_right_no_parent_fix(p_parent, p);
|
||||
//No need to link p and p_grandparent:
|
||||
// [NodeTraits::set_parent(p, p_grandparent) + NodeTraits::set_right(p_grandparent, p)]
|
||||
//as p_grandparent is not the header, another rotation is coming and p_parent
|
||||
//will be the right child of p_grandparent
|
||||
p_parent = p;
|
||||
}
|
||||
bstree_algo::rotate_left(p_grandparent, p_parent, NodeTraits::get_parent(p_grandparent), header);
|
||||
}
|
||||
NodeTraits::set_color(p_parent, NodeTraits::black());
|
||||
break;
|
||||
}
|
||||
}
|
||||
NodeTraits::set_color(NodeTraits::get_parent(header), NodeTraits::black());
|
||||
|
@@ -576,8 +576,8 @@ class splaytree_algorithms
|
||||
if(!t_left)
|
||||
break;
|
||||
if(comp(key, t_left)){
|
||||
commit.t_ = bstree_algo::rotate_right(commit.t_);
|
||||
|
||||
bstree_algo::rotate_right_no_parent_fix(commit.t_, t_left);
|
||||
commit.t_ = t_left;
|
||||
if( !NodeTraits::get_left(commit.t_) )
|
||||
break;
|
||||
link_right(commit.t_, commit.r_);
|
||||
@@ -597,8 +597,8 @@ class splaytree_algorithms
|
||||
break;
|
||||
|
||||
if(comp(t_right, key)){
|
||||
commit.t_ = bstree_algo::rotate_left( commit.t_ );
|
||||
|
||||
bstree_algo::rotate_left_no_parent_fix(commit.t_, t_right);
|
||||
commit.t_ = t_right;
|
||||
if( !NodeTraits::get_right(commit.t_) )
|
||||
break;
|
||||
link_left(commit.t_, commit.l_);
|
||||
|
@@ -110,16 +110,17 @@ class treap_algorithms
|
||||
|
||||
static void rotate_up_n(const node_ptr header, const node_ptr p, std::size_t n)
|
||||
{
|
||||
for( node_ptr p_parent = NodeTraits::get_parent(p)
|
||||
; n--
|
||||
; p_parent = NodeTraits::get_parent(p)){
|
||||
//Check if left child
|
||||
if(p == NodeTraits::get_left(p_parent)){
|
||||
bstree_algo::rotate_right(p_parent, header);
|
||||
node_ptr p_parent(NodeTraits::get_parent(p));
|
||||
node_ptr p_grandparent(NodeTraits::get_parent(p_parent));
|
||||
while(n--){
|
||||
if(p == NodeTraits::get_left(p_parent)){ //p is left child
|
||||
bstree_algo::rotate_right(p_parent, p, p_grandparent, header);
|
||||
}
|
||||
else{ //Right child
|
||||
bstree_algo::rotate_left(p_parent, header);
|
||||
else{ //p is right child
|
||||
bstree_algo::rotate_left(p_parent, p, p_grandparent, header);
|
||||
}
|
||||
p_parent = p_grandparent;
|
||||
p_grandparent = NodeTraits::get_parent(p_parent);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -526,7 +527,7 @@ class treap_algorithms
|
||||
(const node_ptr & header, const node_ptr & new_node, const insert_commit_data &commit_data)
|
||||
{
|
||||
bstree_algo::insert_unique_commit(header, new_node, commit_data);
|
||||
rebalance_after_insertion_commit(header, new_node, commit_data.rotations);
|
||||
rotate_up_n(header, new_node, commit_data.rotations);
|
||||
}
|
||||
|
||||
#ifdef BOOST_INTRUSIVE_DOXYGEN_INVOKED
|
||||
@@ -547,11 +548,12 @@ class treap_algorithms
|
||||
node_ptr z_left = NodeTraits::get_left(z);
|
||||
node_ptr z_right = NodeTraits::get_right(z);
|
||||
while(z_left || z_right){
|
||||
const node_ptr z_parent(NodeTraits::get_parent(z));
|
||||
if(!z_right || (z_left && pcomp(z_left, z_right))){
|
||||
bstree_algo::rotate_right(z, header);
|
||||
bstree_algo::rotate_right(z, z_left, z_parent, header);
|
||||
}
|
||||
else{
|
||||
bstree_algo::rotate_left(z, header);
|
||||
bstree_algo::rotate_left(z, z_right, z_parent, header);
|
||||
}
|
||||
++n;
|
||||
z_left = NodeTraits::get_left(z);
|
||||
@@ -567,10 +569,9 @@ class treap_algorithms
|
||||
rebalance_after_insertion_check(h, commit_data.node, new_node, pcomp, commit_data.rotations);
|
||||
//No-throw
|
||||
bstree_algo::insert_unique_commit(h, new_node, commit_data);
|
||||
rebalance_after_insertion_commit(h, new_node, commit_data.rotations);
|
||||
rotate_up_n(h, new_node, commit_data.rotations);
|
||||
}
|
||||
|
||||
|
||||
template<class Key, class KeyNodePriorityCompare>
|
||||
static void rebalance_after_insertion_check
|
||||
(const const_node_ptr &header, const const_node_ptr & up, const Key &k
|
||||
@@ -587,22 +588,6 @@ class treap_algorithms
|
||||
num_rotations = n;
|
||||
}
|
||||
|
||||
static void rebalance_after_insertion_commit(const node_ptr & header, const node_ptr & p, std::size_t n)
|
||||
{
|
||||
// Now execute n rotations
|
||||
for( node_ptr p_parent = NodeTraits::get_parent(p)
|
||||
; n--
|
||||
; p_parent = NodeTraits::get_parent(p)){
|
||||
//Check if left child
|
||||
if(p == NodeTraits::get_left(p_parent)){
|
||||
bstree_algo::rotate_right(p_parent, header);
|
||||
}
|
||||
else{ //Right child
|
||||
bstree_algo::rotate_left(p_parent, header);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
template<class NodePtrPriorityCompare>
|
||||
static bool check_invariant(const const_node_ptr & header, NodePtrPriorityCompare pcomp)
|
||||
{
|
||||
|
Reference in New Issue
Block a user