Add erase test for scapegoat tree.
Fix build as needed, implement find().
This commit is contained in:
parent
62b22c4288
commit
e61832f7cd
4 changed files with 95 additions and 8 deletions
|
@ -559,7 +559,7 @@ namespace duckmem {
|
|||
///-------------------------------------------------------------------------
|
||||
///-------------------------------------------------------------------------
|
||||
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) {
|
||||
if (parKey < parTree->content)
|
||||
parTree = parTree->left;
|
||||
|
@ -632,7 +632,7 @@ namespace duckmem {
|
|||
///-------------------------------------------------------------------------
|
||||
template <typename K>
|
||||
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));
|
||||
return static_cast<bool>(NULL != found);
|
||||
}
|
||||
|
@ -654,7 +654,7 @@ namespace duckmem {
|
|||
///-------------------------------------------------------------------------
|
||||
template <typename K>
|
||||
void ScapegoatTree<K>::erase (iterator parItem) {
|
||||
NodeType* const dele = parItem->GetPointer();
|
||||
NodeType* const dele = parItem.GetPointer();
|
||||
AssertRelease(NULL != dele);
|
||||
Assert(m_count > 0);
|
||||
|
||||
|
@ -662,7 +662,7 @@ namespace duckmem {
|
|||
if (dele == m_root)
|
||||
parent = m_root;
|
||||
else
|
||||
parent = FindParentIFP(m_root, dele);
|
||||
parent = find_parent_ifp(m_root, dele);
|
||||
Assert(NULL != parent);
|
||||
|
||||
if (parent) {
|
||||
|
@ -675,7 +675,7 @@ namespace duckmem {
|
|||
parentChildRef = (dele->left ? dele->left : dele->right);
|
||||
}
|
||||
else {
|
||||
NodeType* const inorderSuccessor = DetachBottomNode(dele, true);
|
||||
NodeType* const inorderSuccessor = detach_bottom_node(dele, true);
|
||||
|
||||
parentChildRef = inorderSuccessor;
|
||||
inorderSuccessor->left = dele->left;
|
||||
|
@ -689,6 +689,28 @@ namespace duckmem {
|
|||
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>
|
||||
|
|
|
@ -44,9 +44,9 @@ namespace duckmem {
|
|||
std::vector<P> localCopy;
|
||||
localCopy.reserve(parOther.m_stack.size());
|
||||
while (not otherStackCopy.empty()) {
|
||||
P convertedItem = otherStackCopy.top();
|
||||
P convertedItem = otherStackCopy.back();
|
||||
localCopy.push_back(convertedItem);
|
||||
otherStackCopy.pop();
|
||||
otherStackCopy.pop_back();
|
||||
}
|
||||
m_stack.reserve(parOther.m_stack.capacity());
|
||||
for (typename std::vector<P>::reverse_iterator itRev = localCopy.rbegin(), itRevEnd = localCopy.rend(); itRev != itRevEnd; ++itRev) {
|
||||
|
|
|
@ -117,6 +117,8 @@ namespace duckmem {
|
|||
void erase ( iterator parItem );
|
||||
void erase ( iterator parFrom, iterator parLast );
|
||||
size_type erase ( const value_type& parKey );
|
||||
iterator find ( const K& parSearch );
|
||||
const_iterator find ( const K& parSearch ) const;
|
||||
|
||||
iterator begin ( void );
|
||||
const_iterator begin ( void ) const;
|
||||
|
@ -127,7 +129,7 @@ namespace duckmem {
|
|||
template <typename T>
|
||||
static T* find_closest_match ( T* parTree, const K& parKey );
|
||||
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* get_new_node ( const K& parKey );
|
||||
static void delete_nodes ( NodeType* parNode );
|
||||
|
|
|
@ -17,6 +17,7 @@
|
|||
|
||||
#include "catch2/catch.hpp"
|
||||
#include "duckhandy/scapegoat_tree.hpp"
|
||||
#include <set>
|
||||
|
||||
TEST_CASE ("Insert values in a ScapegoatTree", "[Scapegoat][ScapegoatTree][containers]") {
|
||||
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()));
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue