Fix link rotations for etl::tree_node (#1299)

* Fixed tree node rotate

Improved tree node rotate tests to test all links.

* Removed trailing whitespace

* Removed trailing whitespace

---------

Co-authored-by: John Wellbelove <john.wellbelove@etlcpp.com>
This commit is contained in:
John Wellbelove 2026-02-18 20:46:21 +00:00 committed by GitHub
parent 45b352a059
commit 1b244ec4c0
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
2 changed files with 169 additions and 36 deletions

View File

@ -944,7 +944,7 @@ namespace etl
{
TLink* current = &first;
((current->etl_next = &links, static_cast<TLink&>(links).etl_previous = current, current = &links), ...);
return current;
}
@ -1303,16 +1303,30 @@ namespace etl
typename etl::enable_if<etl::is_same<TLink, etl::tree_link<TLink::ID> >::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<etl::is_same<TLink, etl::tree_link<TLink::ID> >::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 TLink>
typename etl::enable_if<etl::is_same<TLink, etl::tree_link<TLink::ID> >::value, void>::type
link_rotate_right(TLink* parent, TLink* leaf)

View File

@ -554,7 +554,7 @@ namespace
CHECK(data1.FLink0::etl_next == &data2);
CHECK(data2.FLink0::etl_next == nullptr);
CHECK(data3.FLink0::etl_next == nullptr);
etl::link_clear_range(*start);
CHECK(data0.FLink0::etl_next == &data3);
CHECK(data1.FLink0::etl_next == nullptr);
@ -882,11 +882,11 @@ namespace
BData data2(2);
BData data3(3);
// Use reference interface
// Use reference interface
data0.BLink0::set_next(data1);
data1.BLink0::set_next(data2);
data2.BLink0::set_next(data3);
data1.BLink0::set_previous(data0);
data2.BLink0::set_previous(data1);
data3.BLink0::set_previous(data2);
@ -1625,17 +1625,45 @@ namespace
etl::link_right(a, c);
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);
}
}
}