feat(util/rb_tree): add for_each_greater

This commit is contained in:
Leonardo de Moura 2016-03-01 15:40:22 -08:00
parent 2a4b3b75bd
commit 82fb38b440
3 changed files with 46 additions and 1 deletions

View file

@ -235,6 +235,21 @@ static void tst6() {
#endif
}
static void tst7() {
int_rb_tree t;
for (int i = 0; i < 1000; i++) {
t.insert(i);
}
for (int i = 0; i < 1000; i++) {
int c = 0;
t.for_each_greater(i, [&](int v) {
lean_assert(v > i);
c++;
});
lean_assert(c == 1000 - i - 1, c, i);
}
}
int main() {
tst1();
tst2();
@ -242,6 +257,6 @@ int main() {
tst4();
tst5();
tst6();
tst7();
return has_violations() ? 1 : 0;
}

View file

@ -82,6 +82,12 @@ public:
return optional<T>();
}
template<typename F>
void for_each_greater(K const & k, F && f) const {
auto f_prime = [&](entry const & e) { f(e.first, e.second); };
m_map.for_each_greater(mk_pair(k, T()), f_prime);
}
/** \brief (For debugging) Display the content of this splay map. */
friend std::ostream & operator<<(std::ostream & out, rb_map const & m) {
out << "{";

View file

@ -248,6 +248,25 @@ class rb_tree : public CMP {
return optional<T>();
}
template<typename F>
void for_each_greater(T const & v, F && f, node_cell const * n) const {
if (n) {
int c = cmp(v, n->m_value);
if (c == 0) {
for_each(f, n->m_right.m_ptr);
} else if (c > 0) {
// v > n->m_value
for_each_greater(v, f, n->m_right.m_ptr);
} else {
// v < n->m_value
lean_assert(c < 0);
for_each_greater(v, f, n->m_left.m_ptr);
f(n->m_value);
for_each(f, n->m_right.m_ptr);
}
}
}
static void display(std::ostream & out, node_cell const * n) {
if (n) {
out << "(";
@ -371,6 +390,11 @@ public:
template<typename F>
optional<T> find_if(F && f) const { return find_if(f, m_root.m_ptr); }
template<typename F>
void for_each_greater(T const & v, F && f) const {
for_each_greater(v, f, m_root.m_ptr);
}
// For debugging purposes
void display(std::ostream & out) const { display(out, m_root.m_ptr); }