From d4e76658a1474596a1d4a57cc4237a80852a126a Mon Sep 17 00:00:00 2001 From: Daniel Steck Date: Thu, 13 May 2021 23:21:05 +0100 Subject: [PATCH 1/5] initial commit --- include/boost/intrusive/bstree_algorithms.hpp | 50 +-- test/swap_nodes_test.cpp | 337 ++++++++++++++++++ 2 files changed, 366 insertions(+), 21 deletions(-) create mode 100644 test/swap_nodes_test.cpp diff --git a/include/boost/intrusive/bstree_algorithms.hpp b/include/boost/intrusive/bstree_algorithms.hpp index b51c5b0..ebbe3df 100644 --- a/include/boost/intrusive/bstree_algorithms.hpp +++ b/include/boost/intrusive/bstree_algorithms.hpp @@ -396,38 +396,46 @@ class bstree_algorithms : public bstree_algorithms_base NodeTraits::set_parent(node1, NodeTraits::get_parent(node2)); NodeTraits::set_parent(node2, temp); - //Now adjust adjacent nodes for newly inserted node 1 + //Now adjust child nodes for newly inserted node 1 if((temp = NodeTraits::get_left(node1))){ NodeTraits::set_parent(temp, node1); } if((temp = NodeTraits::get_right(node1))){ NodeTraits::set_parent(temp, node1); } - if((temp = NodeTraits::get_parent(node1)) && - //The header has been already updated so avoid it - temp != header2){ - if(NodeTraits::get_left(temp) == node2){ - NodeTraits::set_left(temp, node1); - } - if(NodeTraits::get_right(temp) == node2){ - NodeTraits::set_right(temp, node1); - } - } - //Now adjust adjacent nodes for newly inserted node 2 - if((temp = NodeTraits::get_left(node2))){ + //Now adjust child nodes for newly inserted node 2 + if ((temp = NodeTraits::get_left(node2))) { NodeTraits::set_parent(temp, node2); } - if((temp = NodeTraits::get_right(node2))){ + if ((temp = NodeTraits::get_right(node2))) { NodeTraits::set_parent(temp, node2); } - if((temp = NodeTraits::get_parent(node2)) && - //The header has been already updated so avoid it - temp != header1){ - if(NodeTraits::get_left(temp) == node1){ - NodeTraits::set_left(temp, node2); + + //Finally adjust parent nodes + if ((temp = NodeTraits::get_parent(node1)) == NodeTraits::get_parent(node2)) { + auto left = NodeTraits::get_left(temp); + NodeTraits::set_left(temp, NodeTraits::get_right(temp)); + NodeTraits::set_right(temp, left); + } else { + if ((temp = NodeTraits::get_parent(node1)) && + //The header has been already updated so avoid it + temp != header2) { + if (NodeTraits::get_left(temp) == node2) { + NodeTraits::set_left(temp, node1); + } + if (NodeTraits::get_right(temp) == node2) { + NodeTraits::set_right(temp, node1); + } } - if(NodeTraits::get_right(temp) == node1){ - NodeTraits::set_right(temp, node2); + if ((temp = NodeTraits::get_parent(node2)) && + //The header has been already updated so avoid it + temp != header1) { + if (NodeTraits::get_left(temp) == node1) { + NodeTraits::set_left(temp, node2); + } + if (NodeTraits::get_right(temp) == node1) { + NodeTraits::set_right(temp, node2); + } } } } diff --git a/test/swap_nodes_test.cpp b/test/swap_nodes_test.cpp new file mode 100644 index 0000000..39052de --- /dev/null +++ b/test/swap_nodes_test.cpp @@ -0,0 +1,337 @@ +// +// Created by daniel on 27/04/2021. +// +#include +#include + +#include +#include + +namespace { + +struct Node : boost::intrusive::set_base_hook<> {}; + +typedef boost::intrusive::rbtree Tree; +typedef typename Tree::node_traits NodeTraits; + +NodeTraits::node_ptr get_parent(const Node& node) { + return NodeTraits::get_parent(node.this_ptr()); +} + +NodeTraits::node_ptr get_left(const Node& node) { + return NodeTraits::get_left(node.this_ptr()); +} + +NodeTraits::node_ptr get_right(const Node& node) { + return NodeTraits::get_right(node.this_ptr()); +} + +Tree perfect_binary_tree_of_height_2(std::vector& node_buffer) { + // Perfect binary tree of height 2 + // 3 + // ╱ ╲ + // 1 5 + // ╱ ╲ ╱ ╲ + // 0 2 4 6 + assert(node_buffer.size() == 7); + Tree tree; + + const Tree::iterator it3 = tree.insert_before(tree.end(), node_buffer[3]); + const Tree::iterator it1 = tree.insert_before(it3, node_buffer[1]); + const Tree::iterator it5 = tree.insert_before(tree.end(), node_buffer[5]); + tree.insert_before(it1, node_buffer[0]); + tree.insert_before(it3, node_buffer[2]); + tree.insert_before(it5, node_buffer[4]); + tree.insert_before(tree.end(), node_buffer[6]); + + // Make sure we got the tree we expected + assert(get_parent(node_buffer[0]) == node_buffer[1].this_ptr()); + assert(get_left(node_buffer[0]) == NULL); + assert(get_right(node_buffer[0]) == NULL); + assert(get_parent(node_buffer[1]) == node_buffer[3].this_ptr()); + assert(get_left(node_buffer[1]) == node_buffer[0].this_ptr()); + assert(get_right(node_buffer[1]) == node_buffer[2].this_ptr()); + assert(get_parent(node_buffer[2]) == node_buffer[1].this_ptr()); + assert(get_left(node_buffer[2]) == NULL); + assert(get_right(node_buffer[2]) == NULL); + assert(get_left(node_buffer[3]) == node_buffer[1].this_ptr()); + assert(get_right(node_buffer[3]) == node_buffer[5].this_ptr()); + assert(get_parent(node_buffer[4]) == node_buffer[5].this_ptr()); + assert(get_left(node_buffer[4]) == NULL); + assert(get_right(node_buffer[4]) == NULL); + assert(get_parent(node_buffer[5]) == node_buffer[3].this_ptr()); + assert(get_left(node_buffer[5]) == node_buffer[4].this_ptr()); + assert(get_right(node_buffer[5]) == node_buffer[6].this_ptr()); + assert(get_parent(node_buffer[6]) == node_buffer[5].this_ptr()); + assert(get_left(node_buffer[6]) == NULL); + assert(get_right(node_buffer[6]) == NULL); + + return tree; +} + +// Test that swaps node_buffer 0 and 4 and verifies the results +struct SwapUnrelatedLeafNodesTest { + std::vector& node_buffer; + Tree& tree; + + SwapUnrelatedLeafNodesTest(std::vector& node_buffer, Tree& tree) + : node_buffer(node_buffer), tree(tree) {} + + void check() { + assert(&*boost::next(tree.begin(), 0) == &node_buffer[4]); + assert(&*boost::next(tree.begin(), 1) == &node_buffer[1]); + assert(&*boost::next(tree.begin(), 2) == &node_buffer[2]); + assert(&*boost::next(tree.begin(), 3) == &node_buffer[3]); + assert(&*boost::next(tree.begin(), 4) == &node_buffer[0]); + assert(&*boost::next(tree.begin(), 5) == &node_buffer[5]); + assert(&*boost::next(tree.begin(), 6) == &node_buffer[6]); + assert(get_parent(node_buffer[0]) == node_buffer[5].this_ptr()); + assert(get_left(node_buffer[0]) == NULL); + assert(get_right(node_buffer[0]) == NULL); + assert(get_left(node_buffer[1]) == node_buffer[4].this_ptr()); + assert(get_right(node_buffer[1]) == node_buffer[2].this_ptr()); + assert(get_parent(node_buffer[4]) == node_buffer[1].this_ptr()); + assert(get_left(node_buffer[4]) == NULL); + assert(get_right(node_buffer[4]) == NULL); + assert(get_left(node_buffer[5]) == node_buffer[0].this_ptr()); + assert(get_right(node_buffer[5]) == node_buffer[6].this_ptr()); + } + + void swap04() { + node_buffer[0].swap_nodes(node_buffer[4]); + } + + void swap40() { + node_buffer[4].swap_nodes(node_buffer[0]); + } +}; + +// Test that swaps node_buffer 0 and 2 and verifies the results +struct SwapSiblingLeafNodesTest { + std::vector& node_buffer; + Tree& tree; + + SwapSiblingLeafNodesTest(std::vector& node_buffer, Tree& tree) + : node_buffer(node_buffer), tree(tree) {} + + void check() { + assert(&*boost::next(tree.begin(), 0) == &node_buffer[2]); + assert(&*boost::next(tree.begin(), 1) == &node_buffer[1]); + assert(&*boost::next(tree.begin(), 2) == &node_buffer[0]); + assert(&*boost::next(tree.begin(), 3) == &node_buffer[3]); + assert(&*boost::next(tree.begin(), 4) == &node_buffer[4]); + assert(&*boost::next(tree.begin(), 5) == &node_buffer[5]); + assert(&*boost::next(tree.begin(), 6) == &node_buffer[6]); + assert(get_parent(node_buffer[0]) == node_buffer[1].this_ptr()); + assert(get_left(node_buffer[0]) == NULL); + assert(get_right(node_buffer[0]) == NULL); + assert(get_left(node_buffer[1]) == node_buffer[2].this_ptr()); + assert(get_right(node_buffer[1]) == node_buffer[0].this_ptr()); + assert(get_parent(node_buffer[2]) == node_buffer[1].this_ptr()); + assert(get_left(node_buffer[2]) == NULL); + assert(get_right(node_buffer[2]) == NULL); + } + + void swap02() { + node_buffer[0].swap_nodes(node_buffer[2]); + } + + void swap20() { + node_buffer[2].swap_nodes(node_buffer[0]); + } +}; + +// Test that swaps node_buffer 1 and 5 and verifies the results +struct SwapSiblingNodesTest { + std::vector& node_buffer; + Tree& tree; + + SwapSiblingNodesTest(std::vector& node_buffer, Tree& tree) + : node_buffer(node_buffer), tree(tree) {} + + void check() { + assert(&*boost::next(tree.begin(), 0) == &node_buffer[0]); + assert(&*boost::next(tree.begin(), 1) == &node_buffer[5]); + assert(&*boost::next(tree.begin(), 2) == &node_buffer[2]); + assert(&*boost::next(tree.begin(), 3) == &node_buffer[3]); + assert(&*boost::next(tree.begin(), 4) == &node_buffer[4]); + assert(&*boost::next(tree.begin(), 5) == &node_buffer[1]); + assert(&*boost::next(tree.begin(), 6) == &node_buffer[6]); + assert(get_parent(node_buffer[0]) == node_buffer[5].this_ptr()); + assert(get_parent(node_buffer[1]) == node_buffer[3].this_ptr()); + assert(get_left(node_buffer[1]) == node_buffer[4].this_ptr()); + assert(get_right(node_buffer[1]) == node_buffer[6].this_ptr()); + assert(get_parent(node_buffer[2]) == node_buffer[5].this_ptr()); + assert(get_left(node_buffer[3]) == node_buffer[5].this_ptr()); + assert(get_right(node_buffer[3]) == node_buffer[1].this_ptr()); + assert(get_parent(node_buffer[4]) == node_buffer[1].this_ptr()); + assert(get_parent(node_buffer[5]) == node_buffer[3].this_ptr()); + assert(get_left(node_buffer[5]) == node_buffer[0].this_ptr()); + assert(get_right(node_buffer[5]) == node_buffer[2].this_ptr()); + assert(get_parent(node_buffer[6]) == node_buffer[1].this_ptr()); + } + + void swap15() { + node_buffer[1].swap_nodes(node_buffer[5]); + } + + void swap51() { + node_buffer[5].swap_nodes(node_buffer[1]); + } +}; + +// Test that swaps node_buffer 0 and 1 and verifies the results +struct SwapWithLeftChildTest { + std::vector& node_buffer; + Tree& tree; + + SwapWithLeftChildTest(std::vector& node_buffer, Tree& tree) + : node_buffer(node_buffer), tree(tree) {} + + void check() { + assert(&*boost::next(tree.begin(), 0) == &node_buffer[1]); + assert(&*boost::next(tree.begin(), 1) == &node_buffer[0]); + assert(&*boost::next(tree.begin(), 2) == &node_buffer[2]); + assert(&*boost::next(tree.begin(), 3) == &node_buffer[3]); + assert(&*boost::next(tree.begin(), 4) == &node_buffer[4]); + assert(&*boost::next(tree.begin(), 5) == &node_buffer[5]); + assert(&*boost::next(tree.begin(), 6) == &node_buffer[6]); + assert(get_parent(node_buffer[0]) == node_buffer[3].this_ptr()); + assert(get_left(node_buffer[0]) == node_buffer[1].this_ptr()); + assert(get_right(node_buffer[0]) == node_buffer[2].this_ptr()); + assert(get_parent(node_buffer[1]) == node_buffer[0].this_ptr()); + assert(get_left(node_buffer[1]) == NULL); + assert(get_right(node_buffer[1]) == NULL); + assert(get_parent(node_buffer[2]) == node_buffer[0].this_ptr()); + assert(get_left(node_buffer[2]) == NULL); + assert(get_right(node_buffer[2]) == NULL); + } + + void swap01() { + node_buffer[0].swap_nodes(node_buffer[1]); + } + + void swap10() { + node_buffer[1].swap_nodes(node_buffer[0]); + } +}; + +// Test that swaps node_buffer 1 and 2 and verifies the results +struct SwapWithRightChildTest { + std::vector& node_buffer; + Tree& tree; + + SwapWithRightChildTest(std::vector& node_buffer, Tree& tree) + : node_buffer(node_buffer), tree(tree) {} + + void check() { + assert(&*boost::next(tree.begin(), 0) == &node_buffer[0]); + assert(&*boost::next(tree.begin(), 1) == &node_buffer[2]); + assert(&*boost::next(tree.begin(), 2) == &node_buffer[1]); + assert(&*boost::next(tree.begin(), 3) == &node_buffer[3]); + assert(&*boost::next(tree.begin(), 4) == &node_buffer[4]); + assert(&*boost::next(tree.begin(), 5) == &node_buffer[5]); + assert(&*boost::next(tree.begin(), 6) == &node_buffer[6]); + assert(get_parent(node_buffer[0]) == node_buffer[2].this_ptr()); + assert(get_left(node_buffer[0]) == NULL); + assert(get_right(node_buffer[0]) == NULL); + assert(get_parent(node_buffer[1]) == node_buffer[2].this_ptr()); + assert(get_left(node_buffer[1]) == NULL); + assert(get_right(node_buffer[1]) == NULL); + assert(get_parent(node_buffer[2]) == node_buffer[3].this_ptr()); + assert(get_left(node_buffer[2]) == node_buffer[0].this_ptr()); + assert(get_right(node_buffer[2]) == node_buffer[1].this_ptr()); + } + + void swap12() { + node_buffer[1].swap_nodes(node_buffer[2]); + } + + void swap21() { + node_buffer[2].swap_nodes(node_buffer[1]); + } +}; + +} + +int main() { + { // SwapUnrelatedLeafNodesTest 0 -> 4 + std::vector node_buffer(7); + Tree tree = perfect_binary_tree_of_height_2(node_buffer); + SwapUnrelatedLeafNodesTest test(node_buffer, tree); + test.swap04(); + test.check(); + } + + { // SwapUnrelatedLeafNodesTest 0 <- 4 + std::vector node_buffer(7); + Tree tree = perfect_binary_tree_of_height_2(node_buffer); + SwapUnrelatedLeafNodesTest test(node_buffer, tree); + test.swap40(); + test.check(); + } + + { // SwapSiblingLeafNodesTest 0 -> 2 + std::vector node_buffer(7); + Tree tree = perfect_binary_tree_of_height_2(node_buffer); + SwapSiblingLeafNodesTest test(node_buffer, tree); + test.swap02(); + test.check(); + } + + { // SwapSiblingLeafNodesTest 0 <- 2 + std::vector node_buffer(7); + Tree tree = perfect_binary_tree_of_height_2(node_buffer); + SwapSiblingLeafNodesTest test(node_buffer, tree); + test.swap20(); + test.check(); + } + + { // SwapSiblingNodesTest 1 -> 5 + std::vector node_buffer(7); + Tree tree = perfect_binary_tree_of_height_2(node_buffer); + SwapSiblingNodesTest test(node_buffer, tree); + test.swap15(); + test.check(); + } + + { // SwapSiblingNodesTest 1 <- 5 + std::vector node_buffer(7); + Tree tree = perfect_binary_tree_of_height_2(node_buffer); + SwapSiblingNodesTest test(node_buffer, tree); + test.swap51(); + test.check(); + } + + { // SwapWithLeftChildTest 0 -> 1 + std::vector node_buffer(7); + Tree tree = perfect_binary_tree_of_height_2(node_buffer); + SwapWithLeftChildTest test(node_buffer, tree); + test.swap01(); + test.check(); + } + + { // SwapWithLeftChildTest 0 <- 1 + std::vector node_buffer(7); + Tree tree = perfect_binary_tree_of_height_2(node_buffer); + SwapWithLeftChildTest test(node_buffer, tree); + test.swap10(); + test.check(); + } + + { // SwapWithRightChildTest 1 -> 2 + std::vector node_buffer(7); + Tree tree = perfect_binary_tree_of_height_2(node_buffer); + SwapWithRightChildTest test(node_buffer, tree); + test.swap12(); + test.check(); + } + + { // SwapWithRightChildTest 1 <- 2 + std::vector node_buffer(7); + Tree tree = perfect_binary_tree_of_height_2(node_buffer); + SwapWithRightChildTest test(node_buffer, tree); + test.swap21(); + test.check(); + } +} From 8a652bd35519e99659261b1a8b8c2e02a5873dea Mon Sep 17 00:00:00 2001 From: Daniel Steck Date: Thu, 13 May 2021 23:28:33 +0100 Subject: [PATCH 2/5] C++03 and (C) --- include/boost/intrusive/bstree_algorithms.hpp | 4 +++- test/swap_nodes_test.cpp | 10 +++++++++- 2 files changed, 12 insertions(+), 2 deletions(-) diff --git a/include/boost/intrusive/bstree_algorithms.hpp b/include/boost/intrusive/bstree_algorithms.hpp index ebbe3df..febace9 100644 --- a/include/boost/intrusive/bstree_algorithms.hpp +++ b/include/boost/intrusive/bstree_algorithms.hpp @@ -1,6 +1,7 @@ ///////////////////////////////////////////////////////////////////////////// // // (C) Copyright Ion Gaztanaga 2007-2014 +// (C) Copyright Daniel Steck 2021 // // Distributed under the Boost Software License, Version 1.0. // (See accompanying file LICENSE_1_0.txt or copy at @@ -413,7 +414,8 @@ class bstree_algorithms : public bstree_algorithms_base //Finally adjust parent nodes if ((temp = NodeTraits::get_parent(node1)) == NodeTraits::get_parent(node2)) { - auto left = NodeTraits::get_left(temp); + // special logic for the case where the nodes are siblings + const node_ptr left = NodeTraits::get_left(temp); NodeTraits::set_left(temp, NodeTraits::get_right(temp)); NodeTraits::set_right(temp, left); } else { diff --git a/test/swap_nodes_test.cpp b/test/swap_nodes_test.cpp index 39052de..13a17af 100644 --- a/test/swap_nodes_test.cpp +++ b/test/swap_nodes_test.cpp @@ -1,6 +1,14 @@ +///////////////////////////////////////////////////////////////////////////// // -// Created by daniel on 27/04/2021. +// (C) Copyright Daniel Steck 2021 // +// Distributed under the Boost Software License, Version 1.0. +// (See accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) +// +// See http://www.boost.org/libs/intrusive for documentation. +// +///////////////////////////////////////////////////////////////////////////// #include #include From 300ffd23631fb9b89014d4eb0aa03be831ceccaa Mon Sep 17 00:00:00 2001 From: Daniel Steck Date: Thu, 13 May 2021 23:30:19 +0100 Subject: [PATCH 3/5] unintended whitespace change --- include/boost/intrusive/bstree_algorithms.hpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/include/boost/intrusive/bstree_algorithms.hpp b/include/boost/intrusive/bstree_algorithms.hpp index febace9..3d47299 100644 --- a/include/boost/intrusive/bstree_algorithms.hpp +++ b/include/boost/intrusive/bstree_algorithms.hpp @@ -405,10 +405,10 @@ class bstree_algorithms : public bstree_algorithms_base NodeTraits::set_parent(temp, node1); } //Now adjust child nodes for newly inserted node 2 - if ((temp = NodeTraits::get_left(node2))) { + if((temp = NodeTraits::get_left(node2))){ NodeTraits::set_parent(temp, node2); } - if ((temp = NodeTraits::get_right(node2))) { + if((temp = NodeTraits::get_right(node2))){ NodeTraits::set_parent(temp, node2); } From 8551b3958d821a4acffa80980d04bfecdde3cd22 Mon Sep 17 00:00:00 2001 From: Daniel Steck Date: Thu, 13 May 2021 23:39:26 +0100 Subject: [PATCH 4/5] C++03 --- test/swap_nodes_test.cpp | 35 +++++++++++++++++++++-------------- 1 file changed, 21 insertions(+), 14 deletions(-) diff --git a/test/swap_nodes_test.cpp b/test/swap_nodes_test.cpp index 13a17af..4603d15 100644 --- a/test/swap_nodes_test.cpp +++ b/test/swap_nodes_test.cpp @@ -34,7 +34,7 @@ NodeTraits::node_ptr get_right(const Node& node) { return NodeTraits::get_right(node.this_ptr()); } -Tree perfect_binary_tree_of_height_2(std::vector& node_buffer) { +void perfect_binary_tree_of_height_2(std::vector& node_buffer, Tree& tree) { // Perfect binary tree of height 2 // 3 // ╱ ╲ @@ -42,7 +42,6 @@ Tree perfect_binary_tree_of_height_2(std::vector& node_buffer) { // ╱ ╲ ╱ ╲ // 0 2 4 6 assert(node_buffer.size() == 7); - Tree tree; const Tree::iterator it3 = tree.insert_before(tree.end(), node_buffer[3]); const Tree::iterator it1 = tree.insert_before(it3, node_buffer[1]); @@ -73,8 +72,6 @@ Tree perfect_binary_tree_of_height_2(std::vector& node_buffer) { assert(get_parent(node_buffer[6]) == node_buffer[5].this_ptr()); assert(get_left(node_buffer[6]) == NULL); assert(get_right(node_buffer[6]) == NULL); - - return tree; } // Test that swaps node_buffer 0 and 4 and verifies the results @@ -265,7 +262,8 @@ struct SwapWithRightChildTest { int main() { { // SwapUnrelatedLeafNodesTest 0 -> 4 std::vector node_buffer(7); - Tree tree = perfect_binary_tree_of_height_2(node_buffer); + Tree tree; + perfect_binary_tree_of_height_2(node_buffer, tree); SwapUnrelatedLeafNodesTest test(node_buffer, tree); test.swap04(); test.check(); @@ -273,7 +271,8 @@ int main() { { // SwapUnrelatedLeafNodesTest 0 <- 4 std::vector node_buffer(7); - Tree tree = perfect_binary_tree_of_height_2(node_buffer); + Tree tree; + perfect_binary_tree_of_height_2(node_buffer, tree); SwapUnrelatedLeafNodesTest test(node_buffer, tree); test.swap40(); test.check(); @@ -281,7 +280,8 @@ int main() { { // SwapSiblingLeafNodesTest 0 -> 2 std::vector node_buffer(7); - Tree tree = perfect_binary_tree_of_height_2(node_buffer); + Tree tree; + perfect_binary_tree_of_height_2(node_buffer, tree); SwapSiblingLeafNodesTest test(node_buffer, tree); test.swap02(); test.check(); @@ -289,7 +289,8 @@ int main() { { // SwapSiblingLeafNodesTest 0 <- 2 std::vector node_buffer(7); - Tree tree = perfect_binary_tree_of_height_2(node_buffer); + Tree tree; + perfect_binary_tree_of_height_2(node_buffer, tree); SwapSiblingLeafNodesTest test(node_buffer, tree); test.swap20(); test.check(); @@ -297,7 +298,8 @@ int main() { { // SwapSiblingNodesTest 1 -> 5 std::vector node_buffer(7); - Tree tree = perfect_binary_tree_of_height_2(node_buffer); + Tree tree; + perfect_binary_tree_of_height_2(node_buffer, tree); SwapSiblingNodesTest test(node_buffer, tree); test.swap15(); test.check(); @@ -305,7 +307,8 @@ int main() { { // SwapSiblingNodesTest 1 <- 5 std::vector node_buffer(7); - Tree tree = perfect_binary_tree_of_height_2(node_buffer); + Tree tree; + perfect_binary_tree_of_height_2(node_buffer, tree); SwapSiblingNodesTest test(node_buffer, tree); test.swap51(); test.check(); @@ -313,7 +316,8 @@ int main() { { // SwapWithLeftChildTest 0 -> 1 std::vector node_buffer(7); - Tree tree = perfect_binary_tree_of_height_2(node_buffer); + Tree tree; + perfect_binary_tree_of_height_2(node_buffer, tree); SwapWithLeftChildTest test(node_buffer, tree); test.swap01(); test.check(); @@ -321,7 +325,8 @@ int main() { { // SwapWithLeftChildTest 0 <- 1 std::vector node_buffer(7); - Tree tree = perfect_binary_tree_of_height_2(node_buffer); + Tree tree; + perfect_binary_tree_of_height_2(node_buffer, tree); SwapWithLeftChildTest test(node_buffer, tree); test.swap10(); test.check(); @@ -329,7 +334,8 @@ int main() { { // SwapWithRightChildTest 1 -> 2 std::vector node_buffer(7); - Tree tree = perfect_binary_tree_of_height_2(node_buffer); + Tree tree; + perfect_binary_tree_of_height_2(node_buffer, tree); SwapWithRightChildTest test(node_buffer, tree); test.swap12(); test.check(); @@ -337,7 +343,8 @@ int main() { { // SwapWithRightChildTest 1 <- 2 std::vector node_buffer(7); - Tree tree = perfect_binary_tree_of_height_2(node_buffer); + Tree tree; + perfect_binary_tree_of_height_2(node_buffer, tree); SwapWithRightChildTest test(node_buffer, tree); test.swap21(); test.check(); From 79d2a6df4b73908c3034fbfc0c2c45736652f529 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ion=20Gazta=C3=B1aga?= Date: Sun, 20 Jun 2021 02:01:20 +0200 Subject: [PATCH 5/5] Put swap tests inside generic associative container tests so that they are executed for every tree type. --- doc/intrusive.qbk | 1 + include/boost/intrusive/bstree_algorithms.hpp | 2 +- .../boost/intrusive/detail/config_begin.hpp | 1 + test/generic_assoc_test.hpp | 228 +++++++++++- test/swap_nodes_test.cpp | 352 ------------------ 5 files changed, 230 insertions(+), 354 deletions(-) delete mode 100644 test/swap_nodes_test.cpp diff --git a/doc/intrusive.qbk b/doc/intrusive.qbk index a6df2e0..cb63a77 100644 --- a/doc/intrusive.qbk +++ b/doc/intrusive.qbk @@ -3894,6 +3894,7 @@ to be inserted in intrusive containers are allocated using `std::vector` or `std * [@https://github.com/boostorg/intrusive/pull/57 GitHub #57: ['UB: comparing unrelated pointers]] * [@https://github.com/boostorg/intrusive/issues/59 GitHub #59: ['Add noexcept support to the library]] * [@https://github.com/boostorg/intrusive/issues/60 GitHub #60: ['Licensing question for math.hpp]] + * [@https://github.com/boostorg/intrusive/pull/61 GitHub #61: ['Fix bstree_algorithms<>::swap_nodes]] * [@https://github.com/boostorg/intrusive/issues/63 GitHub #63: ['nop splice removes element]] [endsect] diff --git a/include/boost/intrusive/bstree_algorithms.hpp b/include/boost/intrusive/bstree_algorithms.hpp index 3d47299..350b2e4 100644 --- a/include/boost/intrusive/bstree_algorithms.hpp +++ b/include/boost/intrusive/bstree_algorithms.hpp @@ -1,6 +1,6 @@ ///////////////////////////////////////////////////////////////////////////// // -// (C) Copyright Ion Gaztanaga 2007-2014 +// (C) Copyright Ion Gaztanaga 2007-2021 // (C) Copyright Daniel Steck 2021 // // Distributed under the Boost Software License, Version 1.0. diff --git a/include/boost/intrusive/detail/config_begin.hpp b/include/boost/intrusive/detail/config_begin.hpp index 8bd57a3..b261ca9 100644 --- a/include/boost/intrusive/detail/config_begin.hpp +++ b/include/boost/intrusive/detail/config_begin.hpp @@ -17,6 +17,7 @@ #ifdef BOOST_MSVC #pragma warning (push) + #pragma warning (disable : 4619) // there is no warning number 'XXXX' #pragma warning (disable : 4275) // non DLL-interface classkey "identifier" used as base for DLL-interface classkey "identifier" #pragma warning (disable : 4251) // "identifier" : class "type" needs to have dll-interface to be used by clients of class "type2" #pragma warning (disable : 4675) // "method" should be declared "static" and have exactly one parameter diff --git a/test/generic_assoc_test.hpp b/test/generic_assoc_test.hpp index 93d5db7..c12849e 100644 --- a/test/generic_assoc_test.hpp +++ b/test/generic_assoc_test.hpp @@ -1,7 +1,8 @@ ///////////////////////////////////////////////////////////////////////////// // // (C) Copyright Olaf Krzikalla 2004-2006. -// (C) Copyright Ion Gaztanaga 2006-2013. +// (C) Copyright Ion Gaztanaga 2006-2021. +// (C) Copyright Daniel Steck 2021 // // Distributed under the Boost Software License, Version 1.0. // (See accompanying file LICENSE_1_0.txt or copy at @@ -18,6 +19,7 @@ #include #include "test_macros.hpp" #include "test_container.hpp" +#include namespace boost{ namespace intrusive{ @@ -40,6 +42,9 @@ struct test_generic_assoc static void test_root(value_cont_type&); static void test_clone(value_cont_type&); static void test_insert_erase_burst(); + static void test_swap_nodes(); + template + static void test_perfect_binary_tree_of_height_2(value_cont_type &values, Assoc &assoc); static void test_container_from_end(value_cont_type&, detail::true_type); static void test_container_from_end(value_cont_type&, detail::false_type) {} static void test_splay_up(value_cont_type&, detail::true_type); @@ -130,6 +135,226 @@ void test_generic_assoc::test_insert_erase_burst() } } +// Perfect binary tree of height 2 +// 3 | +// / \ | +// 1 5 | +// / \ / \ | +// 0 2 4 6 | +template +template +void test_generic_assoc::test_perfect_binary_tree_of_height_2 + (value_cont_type &values, Assoc &assoc) +{ + //value_cont_type values; + const std::size_t MaxValues = 7; + BOOST_TEST(values.size() == MaxValues); + for(std::size_t i = 0; i != MaxValues; ++i){ + (&values[i])->value_ = i; + } + + typedef typename Assoc::iterator iterator; + + BOOST_TEST( assoc.empty() ); + assoc.clear(); + + const iterator it3 = assoc.insert_before(assoc.end(), values[3]); + const iterator it1 = assoc.insert_before(it3, values[1]); + const iterator it5 = assoc.insert_before(assoc.end(), values[5]); + assoc.insert_before(it1, values[0]); + assoc.insert_before(it3, values[2]); + assoc.insert_before(it5, values[4]); + assoc.insert_before(assoc.end(), values[6]); +} + + +template +void test_generic_assoc::test_swap_nodes() +{ +// Perfect binary tree of height 2 +// 3 | +// / \ | +// 1 5 | +// / \ / \ | +// 0 2 4 6 | + + typedef typename ContainerDefiner::template container + <>::type assoc_type; + typedef typename assoc_type::value_traits value_traits_t; + typedef typename assoc_type::node_algorithms node_algorithms_t; + const std::size_t MaxValues = 7; + + { //Unrelated swap + value_cont_type values(MaxValues); + assoc_type testset; + test_perfect_binary_tree_of_height_2(values, testset); + + node_algorithms_t::swap_nodes + ( value_traits_t::to_node_ptr(values[0]) + , value_traits_t::to_node_ptr(values[4]) + ); + + BOOST_TEST( (&*boost::next(testset.begin(), 0) == &values[4]) ); + BOOST_TEST( (&*boost::next(testset.begin(), 1) == &values[1]) ); + BOOST_TEST( (&*boost::next(testset.begin(), 2) == &values[2]) ); + BOOST_TEST( (&*boost::next(testset.begin(), 3) == &values[3]) ); + BOOST_TEST( (&*boost::next(testset.begin(), 4) == &values[0]) ); + BOOST_TEST( (&*boost::next(testset.begin(), 5) == &values[5]) ); + BOOST_TEST( (&*boost::next(testset.begin(), 6) == &values[6]) ); + + node_algorithms_t::swap_nodes + ( value_traits_t::to_node_ptr(values[4]) + , value_traits_t::to_node_ptr(values[0]) + ); + + BOOST_TEST( (&*boost::next(testset.begin(), 0) == &values[0]) ); + BOOST_TEST( (&*boost::next(testset.begin(), 1) == &values[1]) ); + BOOST_TEST( (&*boost::next(testset.begin(), 2) == &values[2]) ); + BOOST_TEST( (&*boost::next(testset.begin(), 3) == &values[3]) ); + BOOST_TEST( (&*boost::next(testset.begin(), 4) == &values[4]) ); + BOOST_TEST( (&*boost::next(testset.begin(), 5) == &values[5]) ); + BOOST_TEST( (&*boost::next(testset.begin(), 6) == &values[6]) ); + + testset.check(); + } + + { //sibling leaf nodes + value_cont_type values(MaxValues); + assoc_type testset; + test_perfect_binary_tree_of_height_2(values, testset); + + node_algorithms_t::swap_nodes + ( value_traits_t::to_node_ptr(values[0]) + , value_traits_t::to_node_ptr(values[2]) + ); + + BOOST_TEST( (&*boost::next(testset.begin(), 0) == &values[2]) ); + BOOST_TEST( (&*boost::next(testset.begin(), 1) == &values[1]) ); + BOOST_TEST( (&*boost::next(testset.begin(), 2) == &values[0]) ); + BOOST_TEST( (&*boost::next(testset.begin(), 3) == &values[3]) ); + BOOST_TEST( (&*boost::next(testset.begin(), 4) == &values[4]) ); + BOOST_TEST( (&*boost::next(testset.begin(), 5) == &values[5]) ); + BOOST_TEST( (&*boost::next(testset.begin(), 6) == &values[6]) ); + + node_algorithms_t::swap_nodes + ( value_traits_t::to_node_ptr(values[0]) + , value_traits_t::to_node_ptr(values[2]) + ); + + BOOST_TEST( (&*boost::next(testset.begin(), 0) == &values[0]) ); + BOOST_TEST( (&*boost::next(testset.begin(), 1) == &values[1]) ); + BOOST_TEST( (&*boost::next(testset.begin(), 2) == &values[2]) ); + BOOST_TEST( (&*boost::next(testset.begin(), 3) == &values[3]) ); + BOOST_TEST( (&*boost::next(testset.begin(), 4) == &values[4]) ); + BOOST_TEST( (&*boost::next(testset.begin(), 5) == &values[5]) ); + BOOST_TEST( (&*boost::next(testset.begin(), 6) == &values[6]) ); + + testset.check(); + } + + { //sibling nodes + value_cont_type values(MaxValues); + assoc_type testset; + test_perfect_binary_tree_of_height_2(values, testset); + + node_algorithms_t::swap_nodes + ( value_traits_t::to_node_ptr(values[1]) + , value_traits_t::to_node_ptr(values[5]) + ); + + BOOST_TEST( (&*boost::next(testset.begin(), 0) == &values[0]) ); + BOOST_TEST( (&*boost::next(testset.begin(), 1) == &values[5]) ); + BOOST_TEST( (&*boost::next(testset.begin(), 2) == &values[2]) ); + BOOST_TEST( (&*boost::next(testset.begin(), 3) == &values[3]) ); + BOOST_TEST( (&*boost::next(testset.begin(), 4) == &values[4]) ); + BOOST_TEST( (&*boost::next(testset.begin(), 5) == &values[1]) ); + BOOST_TEST( (&*boost::next(testset.begin(), 6) == &values[6]) ); + + node_algorithms_t::swap_nodes + ( value_traits_t::to_node_ptr(values[1]) + , value_traits_t::to_node_ptr(values[5]) + ); + + BOOST_TEST( (&*boost::next(testset.begin(), 0) == &values[0]) ); + BOOST_TEST( (&*boost::next(testset.begin(), 1) == &values[1]) ); + BOOST_TEST( (&*boost::next(testset.begin(), 2) == &values[2]) ); + BOOST_TEST( (&*boost::next(testset.begin(), 3) == &values[3]) ); + BOOST_TEST( (&*boost::next(testset.begin(), 4) == &values[4]) ); + BOOST_TEST( (&*boost::next(testset.begin(), 5) == &values[5]) ); + BOOST_TEST( (&*boost::next(testset.begin(), 6) == &values[6]) ); + + testset.check(); + } + + { //left child + value_cont_type values(MaxValues); + assoc_type testset; + test_perfect_binary_tree_of_height_2(values, testset); + + node_algorithms_t::swap_nodes + ( value_traits_t::to_node_ptr(values[0]) + , value_traits_t::to_node_ptr(values[1]) + ); + + BOOST_TEST( (&*boost::next(testset.begin(), 0) == &values[1]) ); + BOOST_TEST( (&*boost::next(testset.begin(), 1) == &values[0]) ); + BOOST_TEST( (&*boost::next(testset.begin(), 2) == &values[2]) ); + BOOST_TEST( (&*boost::next(testset.begin(), 3) == &values[3]) ); + BOOST_TEST( (&*boost::next(testset.begin(), 4) == &values[4]) ); + BOOST_TEST( (&*boost::next(testset.begin(), 5) == &values[5]) ); + BOOST_TEST( (&*boost::next(testset.begin(), 6) == &values[6]) ); + + node_algorithms_t::swap_nodes + ( value_traits_t::to_node_ptr(values[0]) + , value_traits_t::to_node_ptr(values[1]) + ); + + BOOST_TEST( (&*boost::next(testset.begin(), 0) == &values[0]) ); + BOOST_TEST( (&*boost::next(testset.begin(), 1) == &values[1]) ); + BOOST_TEST( (&*boost::next(testset.begin(), 2) == &values[2]) ); + BOOST_TEST( (&*boost::next(testset.begin(), 3) == &values[3]) ); + BOOST_TEST( (&*boost::next(testset.begin(), 4) == &values[4]) ); + BOOST_TEST( (&*boost::next(testset.begin(), 5) == &values[5]) ); + BOOST_TEST( (&*boost::next(testset.begin(), 6) == &values[6]) ); + + testset.check(); + } + + { //right child + value_cont_type values(MaxValues); + assoc_type testset; + test_perfect_binary_tree_of_height_2(values, testset); + + node_algorithms_t::swap_nodes + ( value_traits_t::to_node_ptr(values[1]) + , value_traits_t::to_node_ptr(values[2]) + ); + + BOOST_TEST( (&*boost::next(testset.begin(), 0) == &values[0]) ); + BOOST_TEST( (&*boost::next(testset.begin(), 1) == &values[2]) ); + BOOST_TEST( (&*boost::next(testset.begin(), 2) == &values[1]) ); + BOOST_TEST( (&*boost::next(testset.begin(), 3) == &values[3]) ); + BOOST_TEST( (&*boost::next(testset.begin(), 4) == &values[4]) ); + BOOST_TEST( (&*boost::next(testset.begin(), 5) == &values[5]) ); + BOOST_TEST( (&*boost::next(testset.begin(), 6) == &values[6]) ); + + node_algorithms_t::swap_nodes + ( value_traits_t::to_node_ptr(values[1]) + , value_traits_t::to_node_ptr(values[2]) + ); + + BOOST_TEST( (&*boost::next(testset.begin(), 0) == &values[0]) ); + BOOST_TEST( (&*boost::next(testset.begin(), 1) == &values[1]) ); + BOOST_TEST( (&*boost::next(testset.begin(), 2) == &values[2]) ); + BOOST_TEST( (&*boost::next(testset.begin(), 3) == &values[3]) ); + BOOST_TEST( (&*boost::next(testset.begin(), 4) == &values[4]) ); + BOOST_TEST( (&*boost::next(testset.begin(), 5) == &values[5]) ); + BOOST_TEST( (&*boost::next(testset.begin(), 6) == &values[6]) ); + + testset.check(); + } +} + template void test_generic_assoc::test_all(value_cont_type& values) { @@ -143,6 +368,7 @@ void test_generic_assoc::test_all(value_cont_type& values) test_rebalance(values, detail::bool_< has_rebalance< assoc_type >::value >()); test_insert_before(values, detail::bool_< has_insert_before< assoc_type >::value >()); test_insert_erase_burst(); + test_swap_nodes(); test_container_from_iterator(values, detail::bool_< assoc_type::has_container_from_iterator >()); } diff --git a/test/swap_nodes_test.cpp b/test/swap_nodes_test.cpp deleted file mode 100644 index 4603d15..0000000 --- a/test/swap_nodes_test.cpp +++ /dev/null @@ -1,352 +0,0 @@ -///////////////////////////////////////////////////////////////////////////// -// -// (C) Copyright Daniel Steck 2021 -// -// Distributed under the Boost Software License, Version 1.0. -// (See accompanying file LICENSE_1_0.txt or copy at -// http://www.boost.org/LICENSE_1_0.txt) -// -// See http://www.boost.org/libs/intrusive for documentation. -// -///////////////////////////////////////////////////////////////////////////// -#include -#include - -#include -#include - -namespace { - -struct Node : boost::intrusive::set_base_hook<> {}; - -typedef boost::intrusive::rbtree Tree; -typedef typename Tree::node_traits NodeTraits; - -NodeTraits::node_ptr get_parent(const Node& node) { - return NodeTraits::get_parent(node.this_ptr()); -} - -NodeTraits::node_ptr get_left(const Node& node) { - return NodeTraits::get_left(node.this_ptr()); -} - -NodeTraits::node_ptr get_right(const Node& node) { - return NodeTraits::get_right(node.this_ptr()); -} - -void perfect_binary_tree_of_height_2(std::vector& node_buffer, Tree& tree) { - // Perfect binary tree of height 2 - // 3 - // ╱ ╲ - // 1 5 - // ╱ ╲ ╱ ╲ - // 0 2 4 6 - assert(node_buffer.size() == 7); - - const Tree::iterator it3 = tree.insert_before(tree.end(), node_buffer[3]); - const Tree::iterator it1 = tree.insert_before(it3, node_buffer[1]); - const Tree::iterator it5 = tree.insert_before(tree.end(), node_buffer[5]); - tree.insert_before(it1, node_buffer[0]); - tree.insert_before(it3, node_buffer[2]); - tree.insert_before(it5, node_buffer[4]); - tree.insert_before(tree.end(), node_buffer[6]); - - // Make sure we got the tree we expected - assert(get_parent(node_buffer[0]) == node_buffer[1].this_ptr()); - assert(get_left(node_buffer[0]) == NULL); - assert(get_right(node_buffer[0]) == NULL); - assert(get_parent(node_buffer[1]) == node_buffer[3].this_ptr()); - assert(get_left(node_buffer[1]) == node_buffer[0].this_ptr()); - assert(get_right(node_buffer[1]) == node_buffer[2].this_ptr()); - assert(get_parent(node_buffer[2]) == node_buffer[1].this_ptr()); - assert(get_left(node_buffer[2]) == NULL); - assert(get_right(node_buffer[2]) == NULL); - assert(get_left(node_buffer[3]) == node_buffer[1].this_ptr()); - assert(get_right(node_buffer[3]) == node_buffer[5].this_ptr()); - assert(get_parent(node_buffer[4]) == node_buffer[5].this_ptr()); - assert(get_left(node_buffer[4]) == NULL); - assert(get_right(node_buffer[4]) == NULL); - assert(get_parent(node_buffer[5]) == node_buffer[3].this_ptr()); - assert(get_left(node_buffer[5]) == node_buffer[4].this_ptr()); - assert(get_right(node_buffer[5]) == node_buffer[6].this_ptr()); - assert(get_parent(node_buffer[6]) == node_buffer[5].this_ptr()); - assert(get_left(node_buffer[6]) == NULL); - assert(get_right(node_buffer[6]) == NULL); -} - -// Test that swaps node_buffer 0 and 4 and verifies the results -struct SwapUnrelatedLeafNodesTest { - std::vector& node_buffer; - Tree& tree; - - SwapUnrelatedLeafNodesTest(std::vector& node_buffer, Tree& tree) - : node_buffer(node_buffer), tree(tree) {} - - void check() { - assert(&*boost::next(tree.begin(), 0) == &node_buffer[4]); - assert(&*boost::next(tree.begin(), 1) == &node_buffer[1]); - assert(&*boost::next(tree.begin(), 2) == &node_buffer[2]); - assert(&*boost::next(tree.begin(), 3) == &node_buffer[3]); - assert(&*boost::next(tree.begin(), 4) == &node_buffer[0]); - assert(&*boost::next(tree.begin(), 5) == &node_buffer[5]); - assert(&*boost::next(tree.begin(), 6) == &node_buffer[6]); - assert(get_parent(node_buffer[0]) == node_buffer[5].this_ptr()); - assert(get_left(node_buffer[0]) == NULL); - assert(get_right(node_buffer[0]) == NULL); - assert(get_left(node_buffer[1]) == node_buffer[4].this_ptr()); - assert(get_right(node_buffer[1]) == node_buffer[2].this_ptr()); - assert(get_parent(node_buffer[4]) == node_buffer[1].this_ptr()); - assert(get_left(node_buffer[4]) == NULL); - assert(get_right(node_buffer[4]) == NULL); - assert(get_left(node_buffer[5]) == node_buffer[0].this_ptr()); - assert(get_right(node_buffer[5]) == node_buffer[6].this_ptr()); - } - - void swap04() { - node_buffer[0].swap_nodes(node_buffer[4]); - } - - void swap40() { - node_buffer[4].swap_nodes(node_buffer[0]); - } -}; - -// Test that swaps node_buffer 0 and 2 and verifies the results -struct SwapSiblingLeafNodesTest { - std::vector& node_buffer; - Tree& tree; - - SwapSiblingLeafNodesTest(std::vector& node_buffer, Tree& tree) - : node_buffer(node_buffer), tree(tree) {} - - void check() { - assert(&*boost::next(tree.begin(), 0) == &node_buffer[2]); - assert(&*boost::next(tree.begin(), 1) == &node_buffer[1]); - assert(&*boost::next(tree.begin(), 2) == &node_buffer[0]); - assert(&*boost::next(tree.begin(), 3) == &node_buffer[3]); - assert(&*boost::next(tree.begin(), 4) == &node_buffer[4]); - assert(&*boost::next(tree.begin(), 5) == &node_buffer[5]); - assert(&*boost::next(tree.begin(), 6) == &node_buffer[6]); - assert(get_parent(node_buffer[0]) == node_buffer[1].this_ptr()); - assert(get_left(node_buffer[0]) == NULL); - assert(get_right(node_buffer[0]) == NULL); - assert(get_left(node_buffer[1]) == node_buffer[2].this_ptr()); - assert(get_right(node_buffer[1]) == node_buffer[0].this_ptr()); - assert(get_parent(node_buffer[2]) == node_buffer[1].this_ptr()); - assert(get_left(node_buffer[2]) == NULL); - assert(get_right(node_buffer[2]) == NULL); - } - - void swap02() { - node_buffer[0].swap_nodes(node_buffer[2]); - } - - void swap20() { - node_buffer[2].swap_nodes(node_buffer[0]); - } -}; - -// Test that swaps node_buffer 1 and 5 and verifies the results -struct SwapSiblingNodesTest { - std::vector& node_buffer; - Tree& tree; - - SwapSiblingNodesTest(std::vector& node_buffer, Tree& tree) - : node_buffer(node_buffer), tree(tree) {} - - void check() { - assert(&*boost::next(tree.begin(), 0) == &node_buffer[0]); - assert(&*boost::next(tree.begin(), 1) == &node_buffer[5]); - assert(&*boost::next(tree.begin(), 2) == &node_buffer[2]); - assert(&*boost::next(tree.begin(), 3) == &node_buffer[3]); - assert(&*boost::next(tree.begin(), 4) == &node_buffer[4]); - assert(&*boost::next(tree.begin(), 5) == &node_buffer[1]); - assert(&*boost::next(tree.begin(), 6) == &node_buffer[6]); - assert(get_parent(node_buffer[0]) == node_buffer[5].this_ptr()); - assert(get_parent(node_buffer[1]) == node_buffer[3].this_ptr()); - assert(get_left(node_buffer[1]) == node_buffer[4].this_ptr()); - assert(get_right(node_buffer[1]) == node_buffer[6].this_ptr()); - assert(get_parent(node_buffer[2]) == node_buffer[5].this_ptr()); - assert(get_left(node_buffer[3]) == node_buffer[5].this_ptr()); - assert(get_right(node_buffer[3]) == node_buffer[1].this_ptr()); - assert(get_parent(node_buffer[4]) == node_buffer[1].this_ptr()); - assert(get_parent(node_buffer[5]) == node_buffer[3].this_ptr()); - assert(get_left(node_buffer[5]) == node_buffer[0].this_ptr()); - assert(get_right(node_buffer[5]) == node_buffer[2].this_ptr()); - assert(get_parent(node_buffer[6]) == node_buffer[1].this_ptr()); - } - - void swap15() { - node_buffer[1].swap_nodes(node_buffer[5]); - } - - void swap51() { - node_buffer[5].swap_nodes(node_buffer[1]); - } -}; - -// Test that swaps node_buffer 0 and 1 and verifies the results -struct SwapWithLeftChildTest { - std::vector& node_buffer; - Tree& tree; - - SwapWithLeftChildTest(std::vector& node_buffer, Tree& tree) - : node_buffer(node_buffer), tree(tree) {} - - void check() { - assert(&*boost::next(tree.begin(), 0) == &node_buffer[1]); - assert(&*boost::next(tree.begin(), 1) == &node_buffer[0]); - assert(&*boost::next(tree.begin(), 2) == &node_buffer[2]); - assert(&*boost::next(tree.begin(), 3) == &node_buffer[3]); - assert(&*boost::next(tree.begin(), 4) == &node_buffer[4]); - assert(&*boost::next(tree.begin(), 5) == &node_buffer[5]); - assert(&*boost::next(tree.begin(), 6) == &node_buffer[6]); - assert(get_parent(node_buffer[0]) == node_buffer[3].this_ptr()); - assert(get_left(node_buffer[0]) == node_buffer[1].this_ptr()); - assert(get_right(node_buffer[0]) == node_buffer[2].this_ptr()); - assert(get_parent(node_buffer[1]) == node_buffer[0].this_ptr()); - assert(get_left(node_buffer[1]) == NULL); - assert(get_right(node_buffer[1]) == NULL); - assert(get_parent(node_buffer[2]) == node_buffer[0].this_ptr()); - assert(get_left(node_buffer[2]) == NULL); - assert(get_right(node_buffer[2]) == NULL); - } - - void swap01() { - node_buffer[0].swap_nodes(node_buffer[1]); - } - - void swap10() { - node_buffer[1].swap_nodes(node_buffer[0]); - } -}; - -// Test that swaps node_buffer 1 and 2 and verifies the results -struct SwapWithRightChildTest { - std::vector& node_buffer; - Tree& tree; - - SwapWithRightChildTest(std::vector& node_buffer, Tree& tree) - : node_buffer(node_buffer), tree(tree) {} - - void check() { - assert(&*boost::next(tree.begin(), 0) == &node_buffer[0]); - assert(&*boost::next(tree.begin(), 1) == &node_buffer[2]); - assert(&*boost::next(tree.begin(), 2) == &node_buffer[1]); - assert(&*boost::next(tree.begin(), 3) == &node_buffer[3]); - assert(&*boost::next(tree.begin(), 4) == &node_buffer[4]); - assert(&*boost::next(tree.begin(), 5) == &node_buffer[5]); - assert(&*boost::next(tree.begin(), 6) == &node_buffer[6]); - assert(get_parent(node_buffer[0]) == node_buffer[2].this_ptr()); - assert(get_left(node_buffer[0]) == NULL); - assert(get_right(node_buffer[0]) == NULL); - assert(get_parent(node_buffer[1]) == node_buffer[2].this_ptr()); - assert(get_left(node_buffer[1]) == NULL); - assert(get_right(node_buffer[1]) == NULL); - assert(get_parent(node_buffer[2]) == node_buffer[3].this_ptr()); - assert(get_left(node_buffer[2]) == node_buffer[0].this_ptr()); - assert(get_right(node_buffer[2]) == node_buffer[1].this_ptr()); - } - - void swap12() { - node_buffer[1].swap_nodes(node_buffer[2]); - } - - void swap21() { - node_buffer[2].swap_nodes(node_buffer[1]); - } -}; - -} - -int main() { - { // SwapUnrelatedLeafNodesTest 0 -> 4 - std::vector node_buffer(7); - Tree tree; - perfect_binary_tree_of_height_2(node_buffer, tree); - SwapUnrelatedLeafNodesTest test(node_buffer, tree); - test.swap04(); - test.check(); - } - - { // SwapUnrelatedLeafNodesTest 0 <- 4 - std::vector node_buffer(7); - Tree tree; - perfect_binary_tree_of_height_2(node_buffer, tree); - SwapUnrelatedLeafNodesTest test(node_buffer, tree); - test.swap40(); - test.check(); - } - - { // SwapSiblingLeafNodesTest 0 -> 2 - std::vector node_buffer(7); - Tree tree; - perfect_binary_tree_of_height_2(node_buffer, tree); - SwapSiblingLeafNodesTest test(node_buffer, tree); - test.swap02(); - test.check(); - } - - { // SwapSiblingLeafNodesTest 0 <- 2 - std::vector node_buffer(7); - Tree tree; - perfect_binary_tree_of_height_2(node_buffer, tree); - SwapSiblingLeafNodesTest test(node_buffer, tree); - test.swap20(); - test.check(); - } - - { // SwapSiblingNodesTest 1 -> 5 - std::vector node_buffer(7); - Tree tree; - perfect_binary_tree_of_height_2(node_buffer, tree); - SwapSiblingNodesTest test(node_buffer, tree); - test.swap15(); - test.check(); - } - - { // SwapSiblingNodesTest 1 <- 5 - std::vector node_buffer(7); - Tree tree; - perfect_binary_tree_of_height_2(node_buffer, tree); - SwapSiblingNodesTest test(node_buffer, tree); - test.swap51(); - test.check(); - } - - { // SwapWithLeftChildTest 0 -> 1 - std::vector node_buffer(7); - Tree tree; - perfect_binary_tree_of_height_2(node_buffer, tree); - SwapWithLeftChildTest test(node_buffer, tree); - test.swap01(); - test.check(); - } - - { // SwapWithLeftChildTest 0 <- 1 - std::vector node_buffer(7); - Tree tree; - perfect_binary_tree_of_height_2(node_buffer, tree); - SwapWithLeftChildTest test(node_buffer, tree); - test.swap10(); - test.check(); - } - - { // SwapWithRightChildTest 1 -> 2 - std::vector node_buffer(7); - Tree tree; - perfect_binary_tree_of_height_2(node_buffer, tree); - SwapWithRightChildTest test(node_buffer, tree); - test.swap12(); - test.check(); - } - - { // SwapWithRightChildTest 1 <- 2 - std::vector node_buffer(7); - Tree tree; - perfect_binary_tree_of_height_2(node_buffer, tree); - SwapWithRightChildTest test(node_buffer, tree); - test.swap21(); - test.check(); - } -}