First import of ScapegoatTree classes from old DuckLib/DuckMem.

This commit is contained in:
King_DuckZ 2018-11-27 10:00:36 +00:00
parent 9f1d24e832
commit 74a4e4fb2e
4 changed files with 898 additions and 0 deletions

View file

@ -0,0 +1,34 @@
#ifndef idDD2D1A57ABEB4BEEA0F7E46C347D1637
#define idDD2D1A57ABEB4BEEA0F7E46C347D1637
#include "ScapegoatTree.hpp"
namespace duckmem {
template <typename K, typename V, typename Hasher>
class ScapegoatMap {
public:
typedef K key_type;
typedef V value_type;
ScapegoatMap ( void );
~ScapegoatMap ( void );
private:
class DerivedPair : public std::pair<key_type, value_type> {
typedef std::pair<key_type, value_type> parent_type;
public:
DerivedPair ( void );
DerivedPair ( typename Loki::TypeTraits<key_type>::ParameterType parKey, typename Loki::TypeTraits<value_type>::ParameterType parValue );
~DerivedPair ( void );
bool operator< ( const DerivedPair& parOther ) const;
bool operator== ( const DerivedPair& parOther ) const;
};
ScapegoatTree<DerivedPair> m_tree;
};
} //namespace duckmem
#include "ScapegoatMap.inl"
#endif

View file

@ -0,0 +1,47 @@
namespace duckmem {
///-------------------------------------------------------------------------
///-------------------------------------------------------------------------
template <typename K, typename V, typename Hasher>
ScapegoatMap<K, V, Hasher>::DerivedPair::DerivedPair() {
}
///-------------------------------------------------------------------------
///-------------------------------------------------------------------------
template <typename K, typename V, typename Hasher>
ScapegoatMap<K, V, Hasher>::DerivedPair::DerivedPair (typename Loki::TypeTraits<key_type>::ParameterType parKey, typename Loki::TypeTraits<value_type>::ParameterType parValue) :
parent_type(parKey, parValue)
{
}
///-------------------------------------------------------------------------
///-------------------------------------------------------------------------
template <typename K, typename V, typename Hasher>
ScapegoatMap<K, V, Hasher>::DerivedPair::~DerivedPair() {
}
///-------------------------------------------------------------------------
///-------------------------------------------------------------------------
// template <typename K, typename V, typename Hasher>
// bool ScapegoatMap<K, V, Hasher>::DerivedPair::operator< (const DerivedPair& parOther) const {
// const typename Hasher::HashType thisHash = Hasher::ComputeFullHash(this->first);
// const typename Hasher::HashType otherHash = Hasher::ComputeFullHash(parOther->first);
// if (thisHash == otherHash) {
// const bool typeMinor = (this->first < parOther.first);
//
// else
//wrong - this breaks total ordering condition return (thisHash < otherHash);
// }
///-------------------------------------------------------------------------
///-------------------------------------------------------------------------
template <typename K, typename V, typename Hasher>
bool ScapegoatMap<K, V, Hasher>::DerivedPair::operator== (const DerivedPair& parOther) const {
const typename Hasher::HashType thisHash = Hasher::ComputeFullHash(this->first);
const typename Hasher::HashType otherHash = Hasher::ComputeFullHash(parOther->first);
if (thisHash != otherHash)
return false;
else
return (this->first == parOther.first);
}
} //namespace duckmem

View file

@ -0,0 +1,131 @@
#ifndef id79CEDB2530B54204A6BEDCBE0B767EA1
#define id79CEDB2530B54204A6BEDCBE0B767EA1
#include "TreeIterator.hpp"
#include "IteratorOnPtr.hpp"
#include "SmallObject.hpp"
#include "DuckMaths/Functions.hpp"
#include "DuckCore/Helpers.hpp"
#include "DuckCore/foreach.hpp"
#include "DuckCore/Casts.hpp"
#include <limits>
#include <utility>
#include <cmath>
//#define SCAPEGOATTREE_VERBOSE
//#define SCAPEGOATTREE_PARANOID
#define SCAPEGOATTREE_DYNAMIC_SIZE_TYPE
#if defined(DUCK_FINAL)
# if defined(SCAPEGOATTREE_VERBOSE)
# undef(SCAPEGOATTREE_VERBOSE)
# endif
#endif
#if !defined(ASSERTIONSENABLED)
# if defined(SCAPEGOATTREE_PARANOID)
# undef(SCAPEGOATTREE_PARANOID)
# endif
#endif
namespace duckmem {
#if defined(WITH_DEBUG_TESTS)
bool RunScapegoatTests ( void );
#endif
template <typename K>
class ScapegoatTree {
public:
typedef K value_type;
typedef size_t size_type;
private:
template <typename SizeType>
struct TreeNodeStruct : public SmallObject {
typedef SizeType size_type;
TreeNodeStruct ( void );
TreeNodeStruct ( typename Loki::TypeTraits<K>::ParameterType parContent ) : content(parContent) {}
K content;
TreeNodeStruct* left;
TreeNodeStruct* right;
size_type size;
};
#if defined(SCAPEGOATTREE_DYNAMIC_SIZE_TYPE)
typedef typename duckcore::Iif<sizeof(TreeNodeStruct<size_type>) == sizeof(TreeNodeStruct<u32>), size_type, u32>::Result TreeNodeSizeType;
typedef TreeNodeStruct<TreeNodeSizeType> TreeNode;
#else
typedef TreeNodeStruct<size_type> TreeNode;
#endif
STATIC_ASSERT(sizeof(typename TreeNode::size_type) <= sizeof(size_type));
typedef TreeNode NodeType;
typedef std::vector<NodeType*> NodeStack;
typedef std::pair<NodeType*, NodeType*> NodeTypePair;
public:
typedef value_type* pointer;
typedef value_type& reference;
typedef const value_type* const_pointer;
typedef const value_type& const_reference;
typedef TreeIterator<value_type, NodeType> iterator;
typedef TreeIterator<const value_type, NodeType> const_iterator;
ScapegoatTree ( void );
explicit ScapegoatTree ( float parAlpha );
~ScapegoatTree ( void );
float GetAlpha ( void ) const { return m_alpha; }
bool Include ( typename Loki::TypeTraits<K>::ParameterType parSearch ) const;
std::pair<iterator, bool> insert ( typename Loki::TypeTraits<K>::ParameterType parKey );
iterator insert ( const iterator&, typename Loki::TypeTraits<K>::ParameterType parValue );
bool empty ( void ) const { return m_count == 0; }
size_type size ( void ) const { return m_count; }
void reserve ( size_type parSize ) { m_reserved = std::max(parSize, m_count); }
size_type capacity ( void ) const { return m_reserved; }
void clear ( void );
void erase ( iterator parItem );
void erase ( iterator parFrom, iterator parLast );
size_type erase ( typename Loki::TypeTraits<value_type>::ParameterType parKey );
iterator begin ( void );
const_iterator begin ( void ) const;
iterator end ( void ) { return iterator(); }
const_iterator end ( void ) const { return const_iterator(); }
private:
template <typename T>
static T* FindClosestMatch ( T* parTree, typename Loki::TypeTraits<K>::ParameterType parKey );
static NodeType* GetInsertParent ( NodeType* parTree, typename Loki::TypeTraits<K>::ParameterType parKey, NodeStack& parRewind );
static NodeType* FindIFP ( const NodeType* parTree, typename Loki::TypeTraits<K>::ParameterType parKey );
static NodeType* FindParentIFP ( NodeType* parTree, const NodeType* parSearchNodeAddr );
static NodeType* GetNewNode ( typename Loki::TypeTraits<K>::ParameterType parKey );
static void DeleteNodes ( NodeType* parNode );
bool IsAlphaHeightBalanced ( size_type parHeight, size_type parSize ) const pure_function;
NodeTypePair FindScapegoat ( NodeStack& parParents ) const;
static NodeType* Rebalance ( NodeType* parSubtree, size_type parDepthHint );
static NodeType* Compress_first ( NodeType* parFrom, size_type parDepthHint );
static NodeType* Compress ( NodeType* parFrom );
static size_type GetMaxBalancedDepth ( size_type parSize, float parAlphaInvLogInv ) pure_function;
static size_type GetTreeMinDepthIB ( size_type parSize, float parAlphaInvLogInv ) pure_function;
static NodeType* DetachBottomNode ( NodeType* parTree, bool parSuccessor );
void RebalanceAfterDeletionIFN ( void );
#if defined(SCAPEGOATTREE_PARANOID)
static size_type AssertNodeSize ( const NodeType* parSubtree );
static size_type FindMaxDepth ( const NodeType* parSubtree ) { return FindMaxDepth_rec(parSubtree) - 1; }
static size_type FindMaxDepth_rec ( const NodeType* parSubtree );
#endif
NodeType* m_root;
size_type m_count;
size_type m_countMax;
size_type m_reserved;
float m_alpha;
float m_alphainvloginv;
};
} //namespace duckmem
#include "ScapegoatTree.inl"
#endif

View file

@ -0,0 +1,686 @@
namespace duckmem {
///-------------------------------------------------------------------------
///-------------------------------------------------------------------------
template <typename K>
ScapegoatTree<K>::ScapegoatTree() :
m_root(NULL),
m_count(0),
m_countMax(0),
m_reserved(0),
m_alpha(0.6f)
{
m_alphainvloginv = 1.0f / std::log(1.0f / m_alpha);
}
///-------------------------------------------------------------------------
///-------------------------------------------------------------------------
template <typename K>
ScapegoatTree<K>::ScapegoatTree (float parAlpha) :
m_root(NULL),
m_count(0),
m_countMax(0),
m_reserved(0),
m_alpha(parAlpha)
{
Assert(parAlpha < 1.0f);
Assert(parAlpha >= 0.5f);
m_alphainvloginv = 1.0f / std::log(1.0f / m_alpha);
}
///-------------------------------------------------------------------------
///-------------------------------------------------------------------------
template <typename K>
ScapegoatTree<K>::~ScapegoatTree() {
DeleteNodes(m_root);
#if defined(DUCK_DEBUG)
m_root = NULL;
m_count = 0xDEADBEEF;
m_countMax = 0xDEADBEEF;
m_reserved = 0xDEADBEEF;
#endif
}
///-------------------------------------------------------------------------
///I can't really find a good optimization for this method, so I'll just
///ignore the hint and rely on the normal insert().
///-------------------------------------------------------------------------
template <typename K>
typename ScapegoatTree<K>::iterator ScapegoatTree<K>::insert (const iterator&, typename Loki::TypeTraits<K>::ParameterType parValue) {
std::pair<iterator, bool> retVal = insert(parValue);
return retVal.first;
}
///-------------------------------------------------------------------------
///-------------------------------------------------------------------------
template <typename K>
std::pair<typename ScapegoatTree<K>::iterator, bool> ScapegoatTree<K>::insert (typename Loki::TypeTraits<K>::ParameterType parKey) {
const size_type depthHint = GetMaxBalancedDepth(std::max<size_type>(m_reserved, m_count + 1), m_alphainvloginv) + 3;
#if defined(SCAPEGOATTREE_VERBOSE)
std::cout << "insert(): depthHint = " << depthHint << ", m_count = " << m_count << ", m_countMax = " << m_countMax << ", m_reserved = " << m_reserved << std::endl;
#endif
if (NULL == m_root) {
m_root = GetNewNode(parKey);
m_root->left = m_root->right = NULL;
m_root->size = 1;
m_count = 1;
m_countMax = 1;
m_reserved = std::max(m_count, m_reserved);
IteratorOnPtr<NodeType**, NodeType*, false> rootWrapper(&m_root, 1);
return std::pair<iterator, bool>(iterator(rootWrapper, 1, depthHint), true);
}
else {
//Refuse to add a new item if the tree has more items than it
//can count
if (std::numeric_limits<size_type>::max() == m_count or std::numeric_limits<typename NodeType::size_type>::max() == m_root->size) {
AssertNotReached();
return std::pair<iterator, bool>(end(), false);
}
NodeStack stack;
stack.reserve(depthHint);
NodeType* const closestMatch = GetInsertParent(m_root, parKey, stack);
Assert(stack.size() <= depthHint);
if (closestMatch->content == parKey)
return std::pair<iterator, bool>(iterator(stack.begin(), stack.size(), depthHint), false);
Assert(NULL == closestMatch->left or closestMatch->left->content < parKey);
Assert(NULL == closestMatch->right or parKey < closestMatch->right->content);
NodeType* const newNode = GetNewNode(parKey);
newNode->left = newNode->right = NULL;
newNode->size = 1;
if (parKey < closestMatch->content) {
Assert(NULL == closestMatch->left);
closestMatch->left = newNode;
}
else {
Assert(NULL == closestMatch->right);
closestMatch->right = newNode;
}
++m_count;
m_countMax = std::max(m_count, m_countMax);
m_reserved = std::max(m_reserved, m_count);
//Update the count of every node
foreach_tn (itNode, stack) {
++(*itNode)->size;
}
//Add the new node to the stack
Assert(stack.capacity() > stack.size());
stack.push_back(newNode);
#if defined(SCAPEGOATTREE_PARANOID)
const size_type totalSize = AssertNodeSize(m_root);
Assert(totalSize == m_count);
Assert(m_root->size == duckcore::checked_numcast<typename NodeType::size_type>(m_count));
#endif
size_type newNodeDepth = stack.size() - 1;
//Rebalance if necessary
if (not IsAlphaHeightBalanced(newNodeDepth, this->size())) {
#if defined(SCAPEGOATTREE_PARANOID)
Assert(FindMaxDepth(m_root) == newNodeDepth);
#endif
Assert(GetMaxBalancedDepth(static_cast<size_type>(m_root->size), m_alphainvloginv) + 1 == newNodeDepth);
std::pair<NodeType*, NodeType*> scapegoatAndParent = FindScapegoat(stack);
AssertRelease(NULL != scapegoatAndParent.first);
NodeType* const newRoot = Rebalance(scapegoatAndParent.first, newNodeDepth + 1);
NodeType* const parent = scapegoatAndParent.second;
if (parent == NULL) {
Assert(scapegoatAndParent.first == m_root);
m_root = newRoot;
m_countMax = m_count;
}
else {
Assert(newRoot != parent);
if (parent->left == scapegoatAndParent.first) {
parent->left = newRoot;
}
else {
Assert(parent->right == scapegoatAndParent.first);
parent->right = newRoot;
}
}
#if defined(SCAPEGOATTREE_PARANOID)
AssertNodeSize(m_root);
Assert(FindMaxDepth(m_root) <= GetMaxBalancedDepth(static_cast<size_type>(m_root->size), m_alphainvloginv));
#endif
//Rebuild the stack.
//TODO: this is ugly and slow, see if you can find a better way
stack.clear();
GetInsertParent(m_root, parKey, stack);
newNodeDepth = stack.size() - 1;
Assert(IsAlphaHeightBalanced(newNodeDepth, this->size()));
}
return std::pair<iterator, bool>(iterator(stack.begin(), newNodeDepth + 1, duckmath::log2_fast(m_reserved + 1)), true);
}
}
///-------------------------------------------------------------------------
///-------------------------------------------------------------------------
template <typename K>
typename ScapegoatTree<K>::NodeType* ScapegoatTree<K>::Rebalance (NodeType* parSubtree, size_type parDepthHint) {
#if defined(SCAPEGOATTREE_VERBOSE)
std::cout << "Rebalancing subtree" << std::endl;
#endif
Assert(NULL != parSubtree);
NodeType* const newRoot = Compress_first(parSubtree, parDepthHint);
NodeType* const retVal = Compress(newRoot);
return retVal;
}
///-------------------------------------------------------------------------
///-------------------------------------------------------------------------
template <typename K>
typename ScapegoatTree<K>::NodeTypePair ScapegoatTree<K>::FindScapegoat (NodeStack& parParents) const {
Assert(not parParents.empty());
const size_type height = parParents.size();
for (size_type z = parParents.size() - 1; z > 0; --z) {
NodeType& currNode = *(parParents[z - 1]);
Assert(height - z > 0);
if (not IsAlphaHeightBalanced(height - z, static_cast<size_type>(currNode.size))) {
NodeType* parent;
if (z == 1)
parent = NULL;
else
parent = parParents[z - 2];
return NodeTypePair(&currNode, parent);
}
}
AssertNotReached();
set_not_reached();
return NodeTypePair(NULL, NULL);
}
///-------------------------------------------------------------------------
///-------------------------------------------------------------------------
template <typename K>
typename ScapegoatTree<K>::NodeType* ScapegoatTree<K>::GetNewNode (typename Loki::TypeTraits<K>::ParameterType parKey) {
return new NodeType(parKey);
}
///-------------------------------------------------------------------------
///-------------------------------------------------------------------------
template <typename K>
template <typename T>
T* ScapegoatTree<K>::FindClosestMatch (T* parTree, typename Loki::TypeTraits<K>::ParameterType parKey) {
Assert(NULL != parTree);
//if (parTree->left and parKey <= parTree->left->content)
if (parTree->left and not (parTree->left->content < parKey))
return FindClosestMatch(parTree->left, parKey);
//else if (parTree->right and parKey >= parTree->right->content)
else if (parTree->right and not (parKey < parTree->right->content))
return FindClosestMatch(parTree->right, parKey);
else
return parTree;
}
///-------------------------------------------------------------------------
///-------------------------------------------------------------------------
template <typename K>
typename ScapegoatTree<K>::NodeType* ScapegoatTree<K>::GetInsertParent (NodeType* parTree, typename Loki::TypeTraits<K>::ParameterType parKey, NodeStack& parRewind) {
Assert(NULL != parTree);
NodeType* retVal = parTree;
bool goLeft;
while ((goLeft = (retVal->left and parKey < retVal->content)) or (retVal->right and retVal->content < parKey)) {
parRewind.push_back(retVal);
if (goLeft) {
Assert(NULL != retVal->left);
Assert(parKey < retVal->content);
retVal = retVal->left;
}
else {
Assert(NULL != retVal->right);
Assert(retVal->content < parKey);
retVal = retVal->right;
}
}
Assert(NULL != retVal);
Assert(parRewind.empty() or parRewind.back() != retVal);
parRewind.push_back(retVal);
return retVal;
}
///-------------------------------------------------------------------------
///-------------------------------------------------------------------------
template <typename K>
void ScapegoatTree<K>::DeleteNodes (NodeType* parNode) {
if (parNode) {
DeleteNodes(parNode->left);
DeleteNodes(parNode->right);
delete parNode;
}
}
///-------------------------------------------------------------------------
///-------------------------------------------------------------------------
template <typename K>
bool ScapegoatTree<K>::IsAlphaHeightBalanced (size_type parHeight, size_type parSize) const {
const float sz = static_cast<float>(parSize);
const float ha = std::floor(std::log(sz) * m_alphainvloginv);
const float height = static_cast<float>(parHeight);
return height <= ha;
}
///-------------------------------------------------------------------------
///Stout/Warren vine to tree.
///This function destroys the links of the given subtree and creates a
///structure that is suitable for Compress(). Input is treated as if it
///was a linked list.
///-------------------------------------------------------------------------
template <typename K>
typename ScapegoatTree<K>::NodeType* ScapegoatTree<K>::Compress_first (NodeType* parFrom, size_type parDepthHint) {
const size_type vineSize = static_cast<size_type>(parFrom->size);
const size_type iteratorDepth = parDepthHint;
#if defined(SCAPEGOATTREE_VERBOSE)
std::cout << "Compress_first(): vineSize = " << vineSize << ", iteratorDepth = " << iteratorDepth << std::endl;
#endif
iterator itFirstStep(parFrom, iteratorDepth);
struct DummyNode {
DummyNode ( void ) : right(NULL) {}
NodeType* right;
};
class NodeWrapper {
public:
NodeWrapper ( void ) {}
explicit NodeWrapper ( NodeType* parOther ) : m_current(parOther), m_right(&parOther->right) {}
explicit NodeWrapper ( DummyNode* parOther ) : m_current(NULL), m_right(&parOther->right) {}
void Replace ( NodeType* parOther ) { m_current = parOther; m_right = &parOther->right; }
void Replace ( NodeWrapper* parOther ) { m_current = parOther->m_current; m_right = parOther->m_right; }
NodeType*& left ( void ) { Assert(m_current); return m_current->left; }
NodeType*& right ( void ) { Assert(m_right); return *m_right; }
typename NodeType::size_type& size ( void ) { Assert(m_current); return m_current->size; }
NodeType* pointer ( void ) { return m_current; }
private:
NodeType* m_current;
NodeType** m_right;
};
DummyNode pseudorootMem;
NodeWrapper parent(&pseudorootMem);
NodeWrapper current;
NodeWrapper child(&pseudorootMem);
size_type iterationsCount;
if (duckcore::IsPowerOfTwo(vineSize + 1))
iterationsCount = (1 << (duckmath::log2_fast(vineSize))) - 1;
else
iterationsCount = (vineSize - ((1 << duckmath::log2_fast(vineSize)) - 1));
#if defined(SCAPEGOATTREE_VERBOSE)
std::cout << "vineSize = " << vineSize << ", iterationsCount = " << iterationsCount << std::endl;
#endif
Assert(iterationsCount < vineSize); //Underflow error?
Assert(iterationsCount > 0);
for (size_type z = 0; z < iterationsCount; ++z) {
current.Replace(itFirstStep.GetPointer());
++itFirstStep;
child.Replace(itFirstStep.GetPointer());
++itFirstStep;
current.left() = NULL;
current.right() = NULL;
current.size() = 1;
parent.right() = child.pointer();
child.left() = current.pointer();
Assert(z * 2 < vineSize);
child.size() = duckcore::checked_numcast<typename NodeType::size_type>(vineSize - z * 2);
Assert(child.size() >= 1);
parent.Replace(&child);
}
Assert(iterationsCount * 2 <= vineSize);
for (size_type z = iterationsCount * 2; z < vineSize; ++z) {
child.right() = itFirstStep.GetPointer();
child.Replace(itFirstStep.GetPointer());
++itFirstStep;
child.left() = NULL;
child.size() = duckcore::checked_numcast<typename NodeType::size_type>(vineSize - z);
}
child.right() = NULL;
child.size() = (child.left() ? 2 : 1);
#if defined(SCAPEGOATTREE_VERBOSE)
std::cout << "Original size was " << vineSize << ", root's size is " << pseudorootMem.right->size << std::endl;
#endif
Assert(vineSize == static_cast<size_type>(pseudorootMem.right->size));
#if defined(SCAPEGOATTREE_PARANOID)
AssertNodeSize(pseudorootMem.right);
Assert(FindMaxDepth(pseudorootMem.right) <= vineSize);
#endif
return pseudorootMem.right;
}
///-------------------------------------------------------------------------
///Stout/Warren vine to tree.
///Performs the second and subsequent steps for compressing.
///-------------------------------------------------------------------------
template <typename K>
typename ScapegoatTree<K>::NodeType* ScapegoatTree<K>::Compress (NodeType* parFrom) {
Assert(NULL != parFrom);
//We don't know if the tree is complete, so let's calculate its depth
//rounded up to the nearest complete tree
const size_type treeSize = static_cast<size_type>(parFrom->size);
const size_type m = duckmath::log2_fast(1 + treeSize);
const size_type treeHeight = duckmath::log2_fast(treeSize + (1 << m));
#if defined(SCAPEGOATTREE_PARANOID)
size_type maxDepthInTree = FindMaxDepth(parFrom);
{
//We know step 0 of compression has already been done, so on with
//the spine size at step 1 (the one we're willing to do)
const size_type vineSize = (1 << (treeHeight - 1)) - 1;
size_type count = 0;
NodeType* currNode = parFrom;
do {
++count;
currNode = currNode->right;
} while (currNode);
const size_type countedNodes = ((count + 1) bitand ~1) - 1;
#if defined(SCAPEGOATTREE_VERBOSE)
std::cout << "treeSize = " << treeSize << ", vineSize = " << vineSize << ", treeHeight = " << treeHeight << ", manually counted " << countedNodes << " nodes (" << count << ")\n";
#endif
Assert(duckcore::IsPowerOfTwo(countedNodes + 1));
Assert(vineSize == countedNodes);
}
#endif
NodeType* retVal = parFrom;
Assert(treeHeight >= 2);
for (size_type k = 1; k < treeHeight - 1; ++k) {
#if defined(SCAPEGOATTREE_VERBOSE)
std::cout << "Compress() step " << k << std::endl;
#endif
//The rebalanced tree takes treeHeight-1 steps. One step has been done
//already, so we perform the remaining treeHeight-2 steps.
NodeType* scanner;
NodeType* child = retVal;
retVal = child->right;
Assert(NULL != retVal);
const size_type spineSize = (1 << (treeHeight - k - 1)) - 1;
Assert(spineSize > 0);
for (size_type s = 0; s < spineSize; ++s) {
scanner = child->right;
Assert(NULL != scanner);
child->right = scanner->left;
scanner->left = child;
const typename NodeType::size_type leftBranchSize = (child->right ? child->right->size : 0);
child->size -= scanner->size - leftBranchSize;
scanner->size += child->size - leftBranchSize;
if (s + 1 < spineSize) {
child = scanner->right;
Assert(NULL != child);
scanner->right = child->right;
}
#if defined(SCAPEGOATTREE_VERBOSE)
const size_type subtreeSize = (1 << (k + 1)) - 1;
std::cout << "k=" << k << " - Scanner's size updated to " << scanner->size << ", calculated subtreeSize = " << subtreeSize << std::endl;
#endif
}
Assert(NULL != scanner);
Assert(NULL != retVal);
Assert(treeSize == static_cast<size_type>(retVal->size));
#if defined(SCAPEGOATTREE_PARANOID)
AssertNodeSize(retVal);
{
const size_type newDepth = FindMaxDepth(retVal);
Assert(newDepth <= maxDepthInTree);
maxDepthInTree = newDepth;
}
#endif
}
Assert(static_cast<size_type>(retVal->size) == treeSize);
return retVal;
}
#if defined(SCAPEGOATTREE_PARANOID)
///-------------------------------------------------------------------------
///-------------------------------------------------------------------------
template <typename K>
typename ScapegoatTree<K>::size_type ScapegoatTree<K>::AssertNodeSize (const NodeType* parSubtree) {
Assert(parSubtree);
typename NodeType::size_type localSize = 1;
if (parSubtree->left) {
localSize += AssertNodeSize(parSubtree->left);
}
if (parSubtree->right) {
localSize += AssertNodeSize(parSubtree->right);
}
Assert(parSubtree->size == localSize);
return localSize;
}
///-------------------------------------------------------------------------
///-------------------------------------------------------------------------
template <typename K>
typename ScapegoatTree<K>::size_type ScapegoatTree<K>::FindMaxDepth_rec (const NodeType* parSubtree) {
Assert(parSubtree);
typename NodeType::size_type depthLeft = 0;
typename NodeType::size_type depthRight = 0;
if (parSubtree->left) {
depthLeft = FindMaxDepth_rec(parSubtree->left);
}
if (parSubtree->right) {
depthRight = FindMaxDepth_rec(parSubtree->right);
}
return 1 + std::max(depthLeft, depthRight);
}
#endif
///-------------------------------------------------------------------------
///-------------------------------------------------------------------------
template <typename K>
typename ScapegoatTree<K>::size_type ScapegoatTree<K>::GetMaxBalancedDepth (size_type parSize, float parAlphaInvLogInv) {
const float ha = std::log(static_cast<float>(parSize)) * parAlphaInvLogInv;
return static_cast<size_type>(ha);
}
///-------------------------------------------------------------------------
///-------------------------------------------------------------------------
template <typename K>
typename ScapegoatTree<K>::iterator ScapegoatTree<K>::begin() {
if (NULL == m_root)
return iterator();
const size_type depthHint = GetTreeMinDepthIB(m_reserved, m_alphainvloginv) + 1;
#if defined(SCAPEGOATTREE_PARANOID)
Assert(IsAlphaHeightBalanced(FindMaxDepth(m_root), static_cast<size_type>(m_root->size)));
Assert(FindMaxDepth(m_root) + 1 <= depthHint);
#endif
return iterator(m_root, depthHint + 1);
}
///-------------------------------------------------------------------------
///-------------------------------------------------------------------------
template <typename K>
typename ScapegoatTree<K>::const_iterator ScapegoatTree<K>::begin() const {
if (NULL == m_root)
return iterator();
const size_type depthHint = GetTreeMinDepthIB(m_count, m_alphainvloginv) + 1;
#if defined(SCAPEGOATTREE_PARANOID)
Assert(IsAlphaHeightBalanced(FindMaxDepth(m_root), static_cast<size_type>(m_root->size)));
Assert(FindMaxDepth(m_root) + 1 <= depthHint);
#endif
return const_iterator(m_root, depthHint + 1);
}
///-------------------------------------------------------------------------
///Get min tree depth if balanced
///-------------------------------------------------------------------------
template <typename K>
typename ScapegoatTree<K>::size_type ScapegoatTree<K>::GetTreeMinDepthIB (size_type parSize, float parAlphaInvLogInv) {
const float sz = static_cast<float>(parSize);
const size_type roundedDownDepthBase2 = duckmath::log2_fast(parSize + 1);
const float nodesAtLastLevel = (roundedDownDepthBase2 == 0 ? 0 : static_cast<float>(1 << roundedDownDepthBase2) - 1.0f);
const float retVal = std::log(sz + nodesAtLastLevel) * parAlphaInvLogInv;
return static_cast<size_type>(retVal);
}
///-------------------------------------------------------------------------
///-------------------------------------------------------------------------
template <typename K>
void ScapegoatTree<K>::clear() {
DeleteNodes(m_root);
m_count = 0;
m_countMax = 0;
m_root = NULL;
}
///-------------------------------------------------------------------------
///-------------------------------------------------------------------------
template <typename K>
typename ScapegoatTree<K>::NodeType* ScapegoatTree<K>::FindIFP (const NodeType* parTree, typename Loki::TypeTraits<K>::ParameterType parKey) {
while (parTree) {
if (parKey < parTree->content)
parTree = parTree->left;
else if (parTree->content < parKey)
parTree = parTree->right;
else
break;
}
return parTree;
}
///-------------------------------------------------------------------------
///-------------------------------------------------------------------------
template <typename K>
typename ScapegoatTree<K>::NodeType* ScapegoatTree<K>::FindParentIFP (NodeType* parTree, const NodeType* parSearchNodeAddr) {
if (parTree == parSearchNodeAddr)
return NULL;
NodeType* parent = parTree;
while (parTree and (parTree->left != parSearchNodeAddr and parTree->right != parSearchNodeAddr)) {
if (parSearchNodeAddr->content < parTree->content)
parTree = parTree->left;
else if (parTree->content < parSearchNodeAddr->content)
parTree = parTree->right;
else
break;
parent = parTree;
}
return parent;
}
///-------------------------------------------------------------------------
///Set parSuccessor to true to get the in-order successor, or false to
///get the in-order predecessor.
///-------------------------------------------------------------------------
template <typename K>
typename ScapegoatTree<K>::NodeType* ScapegoatTree<K>::DetachBottomNode (NodeType* parTree, bool parSuccessor) {
AssertRelease(NULL != parTree);
AssertRelease(NULL != parTree->left and NULL != parTree->right);
if (parSuccessor) {
NodeType* inorderSuccessor = parTree->right;
NodeType* successorsParent = parTree;
while (NULL != inorderSuccessor->left) {
successorsParent = inorderSuccessor;
inorderSuccessor = inorderSuccessor->left;
}
Assert(inorderSuccessor == successorsParent->left and inorderSuccessor != successorsParent->right);
Assert(NULL == inorderSuccessor->left);
Assert(NULL == inorderSuccessor->right or inorderSuccessor->right->content < successorsParent->content);
successorsParent->left = inorderSuccessor->right;
Assert(inorderSuccessor);
return inorderSuccessor;
}
else {
NodeType* inorderPredecessor = parTree->left;
NodeType* predecessorsParent = parTree;
while (NULL != inorderPredecessor->right) {
predecessorsParent = inorderPredecessor;
inorderPredecessor = inorderPredecessor->right;
}
Assert(inorderPredecessor == predecessorsParent->right and inorderPredecessor != predecessorsParent->left);
Assert(NULL == inorderPredecessor->right);
Assert(NULL == inorderPredecessor->left or predecessorsParent->content < inorderPredecessor->left->content);
predecessorsParent->right = inorderPredecessor->left;
Assert(inorderPredecessor);
return inorderPredecessor;
}
}
///-------------------------------------------------------------------------
///-------------------------------------------------------------------------
template <typename K>
bool ScapegoatTree<K>::Include (typename Loki::TypeTraits<K>::ParameterType parSearch) const {
const NodeType* const found = FindIFP(m_root, parSearch);
Assert(not found or not (parSearch < found->content or found->content < parSearch));
return static_cast<bool>(NULL != found);
}
///-------------------------------------------------------------------------
///-------------------------------------------------------------------------
template <typename K>
void ScapegoatTree<K>::RebalanceAfterDeletionIFN() {
const float sz = static_cast<float>(m_count);
const float m = static_cast<float>(m_countMax);
if (sz < m_alpha * m) {
const size_type sizeHint = static_cast<size_type>(std::ceil(std::log(sz) * m_alphainvloginv)) + 1;
Rebalance(m_root, sizeHint);
m_countMax = m_count;
}
}
///-------------------------------------------------------------------------
///-------------------------------------------------------------------------
template <typename K>
void ScapegoatTree<K>::erase (iterator parItem) {
NodeType* const dele = parItem->GetPointer();
AssertRelease(NULL != dele);
Assert(m_count > 0);
NodeType* parent;
if (dele == m_root)
parent = m_root;
else
parent = FindParentIFP(m_root, dele);
Assert(NULL != parent);
if (parent) {
Assert(dele == parent->left or dele == parent->right or dele == parent);
NodeType*& parentChildRef = (dele == m_root ? m_root : (dele == parent->left ? parent->left : parent->right));
if (NULL == dele->left and NULL == dele->right) {
parentChildRef = NULL;
}
else if (NULL == dele->left xor NULL == dele->right) {
parentChildRef = (dele->left ? dele->left : dele->right);
}
else {
NodeType* const inorderSuccessor = DetachBottomNode(dele, true);
parentChildRef = inorderSuccessor;
inorderSuccessor->left = dele->left;
inorderSuccessor->right = dele->right;
}
Assert(NULL == parent->left or parent->left->content < parent->content);
Assert(NULL == parent->right or parent->content < parent->right->content);
}
--m_count;
delete dele;
RebalanceAfterDeletionIFN();
}
// ///-------------------------------------------------------------------------
// ///-------------------------------------------------------------------------
// template <typename K>
// void ScapegoatTree<K>::erase (iterator parFrom, iterator parLast) {
// }
//
// ///-------------------------------------------------------------------------
// ///-------------------------------------------------------------------------
// template <typename K>
// typename ScapegoatTree<K>::size_type ScapegoatTree<K>::erase (typename Loki::TypeTraits<value_type>::ParameterType parKey) {
// }
} //namespace duckmem