feat(util/rb_tree): add check_invariant for red black trees

Signed-off-by: Leonardo de Moura <leonardo@microsoft.com>
This commit is contained in:
Leonardo de Moura 2014-02-21 17:39:24 -08:00
parent 1ab12eb105
commit 54d5088c98

View file

@ -9,6 +9,7 @@ Author: Leonardo de Moura
#include "util/rc.h" #include "util/rc.h"
#include "util/debug.h" #include "util/debug.h"
#include "util/buffer.h" #include "util/buffer.h"
#include "util/optional.h"
namespace lean { namespace lean {
/** /**
@ -245,13 +246,58 @@ class rb_tree : public CMP {
} }
} }
bool check_invariant(node_cell const * n, unsigned curr_black, optional<unsigned> & num_black) const {
// We check:
// 1) the nodes are really ordered, that is, left->value < n->value < right->value
// 2) there are no two consecutive red nodes
// 3) every path has the same number of black nodes
if (n) {
if (!n->m_red)
curr_black++;
if (n->m_left) {
lean_assert(!n->m_red || !n->m_left.is_red());
check_invariant(n->m_left.m_ptr, curr_black, num_black);
lean_assert(cmp(n->m_left->m_value, n->m_value) < 0);
}
if (n->m_right) {
lean_assert(!n->m_red || !n->m_right.is_red());
check_invariant(n->m_right.m_ptr, curr_black, num_black);
lean_assert(cmp(n->m_value, n->m_right->m_value) < 0);
}
} else {
// end of a path
if (num_black) {
lean_assert(curr_black == *num_black);
} else {
num_black = curr_black;
}
}
return true;
}
node m_root; node m_root;
public: public:
void insert(T const & v) { m_root = set_black(insert(m_root.steal(), v)); } void insert(T const & v) {
void erase_min(T const & v) { m_root = set_black(erase_min(m_root.steal())); } m_root = set_black(insert(m_root.steal(), v));
void erase_core(T const & v) { lean_assert(contains(v)); m_root = set_black(erase(m_root.steal(), v)); } lean_assert(check_invariant());
void erase(T const & v) { if (contains(v)) erase_core(v); } }
void erase_min(T const & v) {
m_root = set_black(erase_min(m_root.steal()));
lean_assert(check_invariant());
}
void erase_core(T const & v) {
lean_assert(contains(v));
m_root = set_black(erase(m_root.steal(), v));
lean_assert(check_invariant());
}
void erase(T const & v) {
if (contains(v))
erase_core(v);
}
T const * find(T const & v) const { T const * find(T const & v) const {
node_cell const * h = m_root.m_ptr; node_cell const * h = m_root.m_ptr;
@ -293,6 +339,11 @@ public:
return out; return out;
} }
bool check_invariant() const {
optional<unsigned> num_black;
return check_invariant(m_root.m_ptr, 0, num_black);
}
/** /**
\brief Copy the contents of this tree to the given buffer. \brief Copy the contents of this tree to the given buffer.
The elements will be stored in increasing order. The elements will be stored in increasing order.