Add erase test for scapegoat tree.

Fix build as needed, implement find().
This commit is contained in:
King_DuckZ 2020-08-13 22:58:35 +01:00
parent 62b22c4288
commit e61832f7cd
4 changed files with 95 additions and 8 deletions

View file

@ -559,7 +559,7 @@ namespace duckmem {
///------------------------------------------------------------------------- ///-------------------------------------------------------------------------
///------------------------------------------------------------------------- ///-------------------------------------------------------------------------
template <typename K> template <typename K>
typename ScapegoatTree<K>::NodeType* ScapegoatTree<K>::find_ifp (const NodeType* parTree, const K& parKey) { typename ScapegoatTree<K>::NodeType* ScapegoatTree<K>::find_ifp (NodeType* parTree, const K& parKey) {
while (parTree) { while (parTree) {
if (parKey < parTree->content) if (parKey < parTree->content)
parTree = parTree->left; parTree = parTree->left;
@ -632,7 +632,7 @@ namespace duckmem {
///------------------------------------------------------------------------- ///-------------------------------------------------------------------------
template <typename K> template <typename K>
bool ScapegoatTree<K>::include (const K& parSearch) const { bool ScapegoatTree<K>::include (const K& parSearch) const {
const NodeType* const found = FindIFP(m_root, parSearch); const NodeType* const found = find_ifp(m_root, parSearch);
Assert(not found or not (parSearch < found->content or found->content < parSearch)); Assert(not found or not (parSearch < found->content or found->content < parSearch));
return static_cast<bool>(NULL != found); return static_cast<bool>(NULL != found);
} }
@ -654,7 +654,7 @@ namespace duckmem {
///------------------------------------------------------------------------- ///-------------------------------------------------------------------------
template <typename K> template <typename K>
void ScapegoatTree<K>::erase (iterator parItem) { void ScapegoatTree<K>::erase (iterator parItem) {
NodeType* const dele = parItem->GetPointer(); NodeType* const dele = parItem.GetPointer();
AssertRelease(NULL != dele); AssertRelease(NULL != dele);
Assert(m_count > 0); Assert(m_count > 0);
@ -662,7 +662,7 @@ namespace duckmem {
if (dele == m_root) if (dele == m_root)
parent = m_root; parent = m_root;
else else
parent = FindParentIFP(m_root, dele); parent = find_parent_ifp(m_root, dele);
Assert(NULL != parent); Assert(NULL != parent);
if (parent) { if (parent) {
@ -675,7 +675,7 @@ namespace duckmem {
parentChildRef = (dele->left ? dele->left : dele->right); parentChildRef = (dele->left ? dele->left : dele->right);
} }
else { else {
NodeType* const inorderSuccessor = DetachBottomNode(dele, true); NodeType* const inorderSuccessor = detach_bottom_node(dele, true);
parentChildRef = inorderSuccessor; parentChildRef = inorderSuccessor;
inorderSuccessor->left = dele->left; inorderSuccessor->left = dele->left;
@ -689,6 +689,28 @@ namespace duckmem {
rebalance_after_deletion_ifn(); rebalance_after_deletion_ifn();
} }
///-------------------------------------------------------------------------
///-------------------------------------------------------------------------
template <typename K>
inline typename ScapegoatTree<K>::iterator ScapegoatTree<K>::find (const K& parSearch) {
NodeStack stack;
const size_type depthHint = get_max_balanced_depth(std::max<size_type>(m_reserved, m_count + 1), m_alphainvloginv) + 3;
stack.reserve(depthHint);
NodeType* const closestMatch = get_insert_parent(m_root, parSearch, stack);
Assert(stack.size() <= depthHint);
if (closestMatch->content == parSearch)
return iterator(stack.begin(), stack.size(), depthHint);
else
return this->end();
}
///-------------------------------------------------------------------------
///-------------------------------------------------------------------------
template <typename K>
inline typename ScapegoatTree<K>::const_iterator ScapegoatTree<K>::find (const K& parSearch) const {
return const_cast<ScapegoatTree<K>*>(this)->find(parSearch);
}
// ///------------------------------------------------------------------------- // ///-------------------------------------------------------------------------
// ///------------------------------------------------------------------------- // ///-------------------------------------------------------------------------
// template <typename K> // template <typename K>

View file

@ -44,9 +44,9 @@ namespace duckmem {
std::vector<P> localCopy; std::vector<P> localCopy;
localCopy.reserve(parOther.m_stack.size()); localCopy.reserve(parOther.m_stack.size());
while (not otherStackCopy.empty()) { while (not otherStackCopy.empty()) {
P convertedItem = otherStackCopy.top(); P convertedItem = otherStackCopy.back();
localCopy.push_back(convertedItem); localCopy.push_back(convertedItem);
otherStackCopy.pop(); otherStackCopy.pop_back();
} }
m_stack.reserve(parOther.m_stack.capacity()); m_stack.reserve(parOther.m_stack.capacity());
for (typename std::vector<P>::reverse_iterator itRev = localCopy.rbegin(), itRevEnd = localCopy.rend(); itRev != itRevEnd; ++itRev) { for (typename std::vector<P>::reverse_iterator itRev = localCopy.rbegin(), itRevEnd = localCopy.rend(); itRev != itRevEnd; ++itRev) {

View file

@ -117,6 +117,8 @@ namespace duckmem {
void erase ( iterator parItem ); void erase ( iterator parItem );
void erase ( iterator parFrom, iterator parLast ); void erase ( iterator parFrom, iterator parLast );
size_type erase ( const value_type& parKey ); size_type erase ( const value_type& parKey );
iterator find ( const K& parSearch );
const_iterator find ( const K& parSearch ) const;
iterator begin ( void ); iterator begin ( void );
const_iterator begin ( void ) const; const_iterator begin ( void ) const;
@ -127,7 +129,7 @@ namespace duckmem {
template <typename T> template <typename T>
static T* find_closest_match ( T* parTree, const K& parKey ); static T* find_closest_match ( T* parTree, const K& parKey );
static NodeType* get_insert_parent ( NodeType* parTree, const K& parKey, NodeStack& parRewind ); static NodeType* get_insert_parent ( NodeType* parTree, const K& parKey, NodeStack& parRewind );
static NodeType* find_ifp ( const NodeType* parTree, const K& parKey ); static NodeType* find_ifp ( NodeType* parTree, const K& parKey );
static NodeType* find_parent_ifp ( NodeType* parTree, const NodeType* parSearchNodeAddr ); static NodeType* find_parent_ifp ( NodeType* parTree, const NodeType* parSearchNodeAddr );
static NodeType* get_new_node ( const K& parKey ); static NodeType* get_new_node ( const K& parKey );
static void delete_nodes ( NodeType* parNode ); static void delete_nodes ( NodeType* parNode );

View file

@ -17,6 +17,7 @@
#include "catch2/catch.hpp" #include "catch2/catch.hpp"
#include "duckhandy/scapegoat_tree.hpp" #include "duckhandy/scapegoat_tree.hpp"
#include <set>
TEST_CASE ("Insert values in a ScapegoatTree", "[Scapegoat][ScapegoatTree][containers]") { TEST_CASE ("Insert values in a ScapegoatTree", "[Scapegoat][ScapegoatTree][containers]") {
using duckmem::ScapegoatTree; using duckmem::ScapegoatTree;
@ -87,3 +88,65 @@ TEST_CASE ("Insert values in a ScapegoatTree", "[Scapegoat][ScapegoatTree][conta
} }
} }
TEST_CASE ("Erase values from a ScapegoatTree", "[Scapegoat][ScapegoatTree][containers]") {
using duckmem::ScapegoatTree;
//auto rand_num = std::bind(std::uniform_int_distribution<int>(1, 1000), std::mt19937(std::time(0)));
ScapegoatTree<int> tree;
for (int z = 0; z < 5000; ++z) {
tree.insert(z + 1);
}
CHECK(tree.size() == 5000);
std::set<int> cpy(tree.begin(), tree.end());
CHECK(cpy.size() == 5000);
{
auto it_num = tree.find(0);
CHECK(it_num == tree.end());
}
{
auto it_num = tree.find(1);
REQUIRE(it_num != tree.end());
CHECK(*it_num == 1);
CHECK(it_num == tree.begin());
tree.erase(it_num);
cpy.erase(1);
CHECK(tree.size() == 4999);
it_num = tree.find(1);
CHECK(it_num == tree.end());
CHECK(not tree.include(1));
}
{
auto it_num = tree.find(2345);
REQUIRE(it_num != tree.end());
CHECK(*it_num == 2345);
tree.erase(it_num);
cpy.erase(2345);
CHECK(tree.size() == 4998);
it_num = tree.find(2345);
CHECK(it_num == tree.end());
CHECK(not tree.include(2345));
}
{
auto it_num = tree.find(3000);
REQUIRE(it_num != tree.end());
int test_num = 3000;
for (; it_num != tree.end(); ++it_num) {
CHECK(*it_num == test_num);
test_num++;
}
CHECK(test_num == 5001);
}
{
const ScapegoatTree<int>& ref = tree;
auto it_num = ref.find(18);
REQUIRE(it_num != ref.end());
CHECK(*it_num == 18);
CHECK(ref.include(18));
}
REQUIRE(tree.size() == cpy.size());
CHECK(std::equal(tree.begin(), tree.end(), cpy.begin()));
}