diff --git a/include/etl/intrusive_links.h b/include/etl/intrusive_links.h index 5c9544bf..59fdb49c 100644 --- a/include/etl/intrusive_links.h +++ b/include/etl/intrusive_links.h @@ -1303,16 +1303,30 @@ namespace etl typename etl::enable_if >::value, void>::type link_rotate_left(TLink& parent, TLink& leaf) { - parent.etl_right = leaf.etl_left; + TLink* grandparent = parent.etl_parent; - if (parent.etl_right != ETL_NULLPTR) - { - parent.etl_right->etl_parent = &parent; - } + parent.etl_right = leaf.etl_left; - leaf.etl_parent = parent.etl_parent; - parent.etl_parent = &leaf; - leaf.etl_left = &parent; + if (parent.etl_right != ETL_NULLPTR) + { + parent.etl_right->etl_parent = &parent; + } + + leaf.etl_parent = grandparent; + parent.etl_parent = &leaf; + leaf.etl_left = &parent; + + if (grandparent != ETL_NULLPTR) + { + if (grandparent->etl_left == &parent) + { + grandparent->etl_left = &leaf; + } + else if (grandparent->etl_right == &parent) + { + grandparent->etl_right = &leaf; + } + } } //*********************************** @@ -1358,19 +1372,32 @@ namespace etl typename etl::enable_if >::value, void>::type link_rotate_right(TLink& parent, TLink& leaf) { - parent.etl_left = leaf.etl_right; + TLink* grandparent = parent.etl_parent; - if (parent.etl_left != ETL_NULLPTR) - { - parent.etl_left->etl_parent = &parent; - } + parent.etl_left = leaf.etl_right; - leaf.etl_parent = parent.etl_parent; - parent.etl_parent = &leaf; - leaf.etl_right = &parent; + if (parent.etl_left != ETL_NULLPTR) + { + parent.etl_left->etl_parent = &parent; + } + + leaf.etl_parent = grandparent; + parent.etl_parent = &leaf; + leaf.etl_right = &parent; + + if (grandparent != ETL_NULLPTR) + { + if (grandparent->etl_left == &parent) + { + grandparent->etl_left = &leaf; + } + else if (grandparent->etl_right == &parent) + { + grandparent->etl_right = &leaf; + } + } } - - + template typename etl::enable_if >::value, void>::type link_rotate_right(TLink* parent, TLink* leaf) diff --git a/test/test_intrusive_links.cpp b/test/test_intrusive_links.cpp index c5bb92c8..efe8b5cb 100644 --- a/test/test_intrusive_links.cpp +++ b/test/test_intrusive_links.cpp @@ -1623,19 +1623,47 @@ namespace etl::link_right(b, a); etl::link_left(b, d); etl::link_right(a, c); - etl::link_left(a, e); + etl::link_left(a, e); + + // r // + // / // + // b // + // / \ // + // d a // + // / \ // + // e c // etl::link_rotate_left(b, a); + // r // + // / // + // a // + // / \ // + // b c // + // / \ // + // d e // + + CHECK(r.etl_left == &a); + CHECK(a.etl_parent == &r); - CHECK(b.etl_parent == &a); - CHECK(e.etl_parent == &b); - CHECK(d.etl_parent == &b); - CHECK(c.etl_parent == &a); CHECK(a.etl_left == &b); CHECK(a.etl_right == &c); + + CHECK(b.etl_parent == &a); CHECK(b.etl_left == &d); CHECK(b.etl_right == &e); + + CHECK(d.etl_parent == &b); + CHECK(d.etl_left == nullptr); + CHECK(d.etl_right == nullptr); + + CHECK(c.etl_parent == &a); + CHECK(c.etl_left == nullptr); + CHECK(c.etl_right == nullptr); + + CHECK(e.etl_parent == &b); + CHECK(e.etl_left == nullptr); + CHECK(e.etl_right == nullptr); } //************************************************************************* @@ -1656,16 +1684,41 @@ namespace etl::link_left(b, d); etl::link_right(a, c); + // r // + // / // + // b // + // / \ // + // d a // + // \ // + // c // + etl::link_rotate_left(b, a); + // r // + // / // + // a // + // / \ // + // b c // + // / // + // d // + + CHECK(r.etl_left == &a); + CHECK(a.etl_parent == &r); - CHECK(b.etl_parent == &a); - CHECK(d.etl_parent == &b); - CHECK(c.etl_parent == &a); CHECK(a.etl_left == &b); CHECK(a.etl_right == &c); + + CHECK(b.etl_parent == &a); CHECK(b.etl_left == &d); CHECK(b.etl_right == nullptr); + + CHECK(d.etl_parent == &b); + CHECK(d.etl_left == nullptr); + CHECK(d.etl_right == nullptr); + + CHECK(c.etl_parent == &a); + CHECK(c.etl_left == nullptr); + CHECK(c.etl_right == nullptr); } //************************************************************************* @@ -1684,21 +1737,49 @@ namespace e.clear(); etl::link_left(r, a); etl::link_left(a, b); - etl::link_left(b, d); etl::link_right(a, c); + etl::link_left(b, d); etl::link_right(b, e); + // r // + // / // + // a // + // / \ // + // b c // + // / \ // + // d e // + etl::link_rotate_right(a, b); + // r // + // / // + // b // + // / \ // + // d a // + // / \ // + // e c // + + CHECK(r.etl_left == &b); + CHECK(b.etl_parent == &r); - CHECK(d.etl_parent == &b); - CHECK(a.etl_parent == &b); - CHECK(e.etl_parent == &a); - CHECK(c.etl_parent == &a); CHECK(b.etl_left == &d); CHECK(b.etl_right == &a); + + CHECK(d.etl_parent == &b); + CHECK(d.etl_left == nullptr); + CHECK(d.etl_right == nullptr); + + CHECK(a.etl_parent == &b); CHECK(a.etl_left == &e); CHECK(a.etl_right == &c); + + CHECK(c.etl_parent == &a); + CHECK(c.etl_left == nullptr); + CHECK(c.etl_right == nullptr); + + CHECK(e.etl_parent == &a); + CHECK(e.etl_left == nullptr); + CHECK(e.etl_right == nullptr); } //************************************************************************* @@ -1719,16 +1800,41 @@ namespace etl::link_left(b, d); etl::link_right(a, c); + // r // + // / // + // a // + // / \ // + // b c // + // / // + // d // + etl::link_rotate_right(a, b); + // r // + // / // + // b // + // / \ // + // d a // + // \ // + // c // + + CHECK(r.etl_left == &b); + CHECK(b.etl_parent == &r); - CHECK(d.etl_parent == &b); - CHECK(a.etl_parent == &b); - CHECK(c.etl_parent == &a); CHECK(b.etl_left == &d); CHECK(b.etl_right == &a); + + CHECK(d.etl_parent == &b); + CHECK(d.etl_left == nullptr); + CHECK(d.etl_right == nullptr); + + CHECK(a.etl_parent == &b); CHECK(a.etl_left == nullptr); CHECK(a.etl_right == &c); + + CHECK(c.etl_parent == &a); + CHECK(c.etl_left == nullptr); + CHECK(c.etl_right == nullptr); } } }