From 180fa7638324b30ac5bcf5fb116d089a8204902a Mon Sep 17 00:00:00 2001 From: Oleg Dorovskoy Date: Sun, 30 Aug 2026 19:04:26 +0300 Subject: [PATCH 1/2] Faster RB tree violation checks --- tests/test_utility.hpp | 83 +++++++++--------------------------------- 1 file changed, 17 insertions(+), 66 deletions(-) diff --git a/tests/test_utility.hpp b/tests/test_utility.hpp index fb9ce38..b4b6d79 100644 --- a/tests/test_utility.hpp +++ b/tests/test_utility.hpp @@ -5,11 +5,10 @@ #include #include -#include #include /** - * Warning this function is very expensive. + * This function has linear complexity. */ template void testRedBlackPropertyViolation(TreeT const& tree) @@ -19,82 +18,34 @@ void testRedBlackPropertyViolation(TreeT const& tree) // root is always black. EXPECT_EQ(tree.root().color(), rb_color::black); - // check that all nodes have red or black coloring. (seems obvious, but is not on bug) - for (auto i = std::begin(tree); i != std::end(tree); ++i) - { - EXPECT_EQ(true, i.color() == rb_color::black || i.color() == rb_color::red); - } + std::function verify = [&](typename TreeT::const_iterator node) -> int { + if (node == std::cend(tree)) + return 1; - // check for (red children = black) property: - for (auto i = std::begin(tree); i != std::end(tree); ++i) - { - auto nodeColor = i.color(); - if (nodeColor == rb_color::red) + // check that all nodes have red or black coloring. (seems obvious, but is not on bug) + EXPECT_EQ(true, node.color() == rb_color::black || node.color() == rb_color::red); + + // check for (red children = black) property: + if (node.color() == rb_color::red) { - if (i.left() != std::end(tree)) + if (node.left() != std::end(tree)) { - EXPECT_EQ(i.left().color(), rb_color::black); + EXPECT_EQ(node.left().color(), rb_color::black); } - if (i.right() != std::end(tree)) + if (node.right() != std::end(tree)) { - EXPECT_EQ(i.right().color(), rb_color::black); + EXPECT_EQ(node.right().color(), rb_color::black); } } - } - - auto leafCollector = [&](typename TreeT::const_iterator root) { - std::list leaves{}; - std::function::iterator)> recursiveLeafFinder; - recursiveLeafFinder = [&](typename std::list::iterator self) { - if (self->left() != std::end(tree)) - { - recursiveLeafFinder(leaves.insert(self, self->left())); - } - if (self->right() != std::end(tree)) - { - *self = self->right(); - recursiveLeafFinder(self); - } - }; - leaves.push_back(root); - recursiveLeafFinder(leaves.begin()); - return leaves; - }; - // Test that all paths from a node down to its null descendants contain the same number of black nodes. - std::function blackHeight = [&](typename TreeT::const_iterator node) -> int { - if (node == std::cend(tree)) - return 1; - const auto leftHeight = blackHeight(node.left()); - const auto rightHeight = blackHeight(node.right()); + // Test that all paths from a node down to its null descendants contain the same number of black nodes. + const auto leftHeight = verify(node.left()); + const auto rightHeight = verify(node.right()); EXPECT_EQ(leftHeight, rightHeight); return leftHeight + (node.color() == rb_color::black ? 1 : 0); }; - blackHeight(tree.root()); - // Test that for every node, on the path to its leaves, has the same number of black nodes. - for (auto i = std::cbegin(tree); i != std::cend(tree); ++i) - { - auto leaves = leafCollector(i); - int comparisonCounter{0}; - for (auto const& leaf : leaves) - { - auto p = leaf; - int counter{0}; - do - { - if (p.color() == rb_color::black) - ++counter; - p = p.parent(); - } while (p != i && p != std::end(tree)); - if (comparisonCounter == 0) - comparisonCounter = counter; - else - { - EXPECT_EQ(comparisonCounter, counter); - } - } - } + verify(tree.root()); } template From df1b407be27427e0d958309f038e793d4f90eb94 Mon Sep 17 00:00:00 2001 From: Oleg Dorovskoy Date: Mon, 31 Aug 2026 09:04:53 +0300 Subject: [PATCH 2/2] testRedBlackPropertyViolation optimization minor improvements --- tests/test_utility.hpp | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) diff --git a/tests/test_utility.hpp b/tests/test_utility.hpp index b4b6d79..5d7523b 100644 --- a/tests/test_utility.hpp +++ b/tests/test_utility.hpp @@ -15,7 +15,11 @@ void testRedBlackPropertyViolation(TreeT const& tree) { using namespace lib_interval_tree; - // root is always black. + // empty tree is always correct + if (tree.root() == std::cend(tree)) + return; + + // root must be black EXPECT_EQ(tree.root().color(), rb_color::black); std::function verify = [&](typename TreeT::const_iterator node) -> int { @@ -23,16 +27,16 @@ void testRedBlackPropertyViolation(TreeT const& tree) return 1; // check that all nodes have red or black coloring. (seems obvious, but is not on bug) - EXPECT_EQ(true, node.color() == rb_color::black || node.color() == rb_color::red); + EXPECT_TRUE(node.color() == rb_color::black || node.color() == rb_color::red); // check for (red children = black) property: if (node.color() == rb_color::red) { - if (node.left() != std::end(tree)) + if (node.left() != std::cend(tree)) { EXPECT_EQ(node.left().color(), rb_color::black); } - if (node.right() != std::end(tree)) + if (node.right() != std::cend(tree)) { EXPECT_EQ(node.right().color(), rb_color::black); }