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>
|
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>
|
||||||
|
|
|
@ -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) {
|
||||||
|
|
|
@ -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 );
|
||||||
|
|
|
@ -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()));
|
||||||
|
}
|
||||||
|
|
Loading…
Reference in a new issue