Additional checks for red-black trees, make sure root is black and the number of black nodes is equal in the left and right subtrees.

This commit is contained in:
Ion Gaztañaga
2015-02-01 23:14:27 +01:00
parent 10cb0bd206
commit ccd980d1f4

View File

@ -23,10 +23,6 @@
#ifndef BOOST_INTRUSIVE_RBTREE_ALGORITHMS_HPP
#define BOOST_INTRUSIVE_RBTREE_ALGORITHMS_HPP
#if defined(BOOST_HAS_PRAGMA_ONCE)
# pragma once
#endif
#include <boost/intrusive/detail/config_begin.hpp>
#include <boost/intrusive/intrusive_fwd.hpp>
@ -37,6 +33,10 @@
#include <boost/intrusive/bstree_algorithms.hpp>
#include <boost/intrusive/detail/ebo_functor_holder.hpp>
#if defined(BOOST_HAS_PRAGMA_ONCE)
# pragma once
#endif
namespace boost {
namespace intrusive {
@ -72,8 +72,14 @@ struct rbtree_node_checker
typedef ValueTraits value_traits;
typedef typename value_traits::node_traits node_traits;
typedef typename node_traits::const_node_ptr const_node_ptr;
typedef typename node_traits::node_ptr node_ptr;
typedef typename base_checker_t::return_type return_type;
struct return_type
: public base_checker_t::return_type
{
return_type() : black_count_(0) {}
std::size_t black_count_;
};
rbtree_node_checker(const NodePtrCompare& comp, ExtraChecker extra_checker)
: base_checker_t(comp, extra_checker)
@ -83,13 +89,21 @@ struct rbtree_node_checker
const return_type& check_return_left, const return_type& check_return_right,
return_type& check_return)
{
if (node_traits::get_color(p) == node_traits::red())
{
if (node_traits::get_left(p))
BOOST_INTRUSIVE_INVARIANT_ASSERT(node_traits::get_color(node_traits::get_left(p)) == node_traits::black());
if (node_traits::get_right(p))
BOOST_INTRUSIVE_INVARIANT_ASSERT(node_traits::get_color(node_traits::get_right(p)) == node_traits::black());
if (node_traits::get_color(p) == node_traits::red()){
//Red nodes have black children
const node_ptr p_left(node_traits::get_left(p));
const node_ptr p_right(node_traits::get_right(p));
BOOST_INTRUSIVE_INVARIANT_ASSERT(!p_left || node_traits::get_color(p_left) == node_traits::black());
BOOST_INTRUSIVE_INVARIANT_ASSERT(!p_right || node_traits::get_color(p_right) == node_traits::black());
//Red node can't be root
BOOST_INTRUSIVE_INVARIANT_ASSERT(node_traits::get_parent(node_traits::get_parent(p)) != p);
}
//Every path to p contains the same number of black nodes
const std::size_t l_black_count = check_return_left.black_count_;
BOOST_INTRUSIVE_INVARIANT_ASSERT(l_black_count == check_return_right.black_count_);
check_return.black_count_ = l_black_count +
static_cast<std::size_t>(node_traits::get_color(p) == node_traits::black());
base_checker_t::operator()(p, check_return_left, check_return_right, check_return);
}
};