- Naming style migrated to camel-case - P7lib logger sources added - Vcpkg manifest, CMake presets and build moved to root - SDL2, Vulkan and RmlUi dependencies added - Logger LOG macro added - Logger configuration - SDL2 window configuration - Vulkan configuration - RmlUi configuration - SDL event loop
868 lines
25 KiB
C++
868 lines
25 KiB
C++
////////////////////////////////////////////////////////////////////////////////
|
|
// /
|
|
// 2012-2020 (c) Baical /
|
|
// /
|
|
// This library is free software; you can redistribute it and/or /
|
|
// modify it under the terms of the GNU Lesser General Public /
|
|
// License as published by the Free Software Foundation; either /
|
|
// version 3.0 of the License, or (at your option) any later version. /
|
|
// /
|
|
// This library is distributed in the hope that it will be useful, /
|
|
// but WITHOUT ANY WARRANTY; without even the implied warranty of /
|
|
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU /
|
|
// Lesser General Public License for more details. /
|
|
// /
|
|
// You should have received a copy of the GNU Lesser General Public /
|
|
// License along with this library. /
|
|
// /
|
|
////////////////////////////////////////////////////////////////////////////////
|
|
//******************************************************************************
|
|
// This header file contains red black tree pooled implementation *
|
|
// - http://www.rsdn.ru/article/alg/binstree.xml *
|
|
// - http://algolist.manual.ru/ds/rbtree.php *
|
|
// - http://rain.ifmo.ru/cat/view.php/vis/trees/red-black-2002 *
|
|
//******************************************************************************
|
|
#ifndef RBTREE_H
|
|
#define RBTREE_H
|
|
|
|
|
|
#define RBT_NODE_RED (1)
|
|
#define RBT_NODE_BLACK (0)
|
|
|
|
template <typename tData_Type, typename tKey_Type>
|
|
class CRBTree
|
|
{
|
|
protected:
|
|
struct sNode
|
|
{
|
|
sNode *pLeft;
|
|
sNode *pRight;
|
|
sNode *pParent;
|
|
tData_Type tData;
|
|
tACHAR bColor;
|
|
};
|
|
|
|
struct tPool_Segment
|
|
{
|
|
sNode *m_pNodes;
|
|
tUINT32 m_dwCount;
|
|
tPool_Segment *m_pNext;
|
|
};
|
|
|
|
tPool_Segment *m_pPool_First;
|
|
sNode *m_pPool_Node_First;
|
|
//count of cell allocated for every pool segment
|
|
tUINT32 m_dwPool_Size;
|
|
|
|
tBOOL m_bData_Free;
|
|
|
|
sNode m_sSentinel;// = { m_pNIL, m_pNIL, 0, RBT_NODE_BLACK, 0};
|
|
sNode *m_pRoot; // = m_pNIL;
|
|
sNode *m_pNIL; // &m_sSentinel
|
|
public:
|
|
////////////////////////////////////////////////////////////////////////////
|
|
//CRBTree
|
|
CRBTree(tUINT32 i_dwPool_Size = 128, tBOOL i_bData_Free = TRUE)
|
|
{
|
|
m_pNIL = &m_sSentinel;
|
|
m_pRoot = m_pNIL;
|
|
|
|
m_sSentinel.bColor = RBT_NODE_BLACK;
|
|
m_sSentinel.pParent = NULL;
|
|
m_sSentinel.tData = NULL;
|
|
m_sSentinel.pLeft = m_pNIL;
|
|
m_sSentinel.pRight = m_pNIL;
|
|
|
|
m_dwPool_Size = i_dwPool_Size;
|
|
m_pPool_First = NULL;
|
|
m_pPool_Node_First = NULL;
|
|
|
|
m_bData_Free = i_bData_Free;
|
|
}//CRBTree
|
|
|
|
|
|
////////////////////////////////////////////////////////////////////////////
|
|
//~CRBTree
|
|
virtual ~CRBTree()
|
|
{
|
|
//delete all tree
|
|
Clear();
|
|
|
|
tPool_Segment *l_pPool_Tmp = NULL;
|
|
while (m_pPool_First)
|
|
{
|
|
l_pPool_Tmp = m_pPool_First;
|
|
m_pPool_First = m_pPool_First->m_pNext;
|
|
|
|
Pool_Segment_Free(l_pPool_Tmp);
|
|
}
|
|
}//~CRBTree
|
|
|
|
|
|
////////////////////////////////////////////////////////////////////////////
|
|
//Push
|
|
tData_Type Push(tData_Type i_pData, tKey_Type i_pKey)
|
|
{
|
|
sNode *l_pCurrent = m_pRoot;
|
|
sNode *l_pParent = NULL;
|
|
sNode *l_pNode = NULL;
|
|
|
|
|
|
//find where node belongs
|
|
while (m_pNIL != l_pCurrent)
|
|
{
|
|
if (Is_Qual(i_pKey, l_pCurrent->tData))
|
|
{
|
|
return (l_pCurrent->tData);
|
|
}
|
|
else
|
|
{
|
|
l_pParent = l_pCurrent;
|
|
l_pCurrent = Is_Key_Less(i_pKey, l_pCurrent->tData) ? l_pCurrent->pLeft : l_pCurrent->pRight;
|
|
}
|
|
}
|
|
|
|
l_pNode = Node_Allocate();
|
|
|
|
if (NULL == l_pNode)
|
|
{
|
|
return NULL;
|
|
}
|
|
|
|
l_pNode->tData = i_pData;
|
|
l_pNode->pParent = l_pParent;
|
|
l_pNode->pLeft = m_pNIL;
|
|
l_pNode->pRight = m_pNIL;
|
|
l_pNode->bColor = RBT_NODE_RED;
|
|
|
|
/* insert node in tree */
|
|
if(l_pParent)
|
|
{
|
|
if(Is_Key_Less(i_pKey, l_pParent->tData))
|
|
{
|
|
l_pParent->pLeft = l_pNode;
|
|
}
|
|
else
|
|
{
|
|
l_pParent->pRight = l_pNode;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
m_pRoot = l_pNode;
|
|
}
|
|
|
|
Fix_Push(l_pNode);
|
|
return l_pNode->tData;
|
|
}//Push
|
|
|
|
|
|
////////////////////////////////////////////////////////////////////////////
|
|
//Del
|
|
void Del(sNode *i_pNode)
|
|
{
|
|
sNode *l_pX = NULL;
|
|
sNode *l_pY = NULL;
|
|
|
|
if ( (NULL == i_pNode)
|
|
|| (m_pNIL == i_pNode)
|
|
)
|
|
{
|
|
return;
|
|
}
|
|
|
|
if (m_bData_Free)
|
|
{
|
|
Data_Release(i_pNode->tData);
|
|
}
|
|
|
|
if ( (m_pNIL == i_pNode->pLeft)
|
|
|| (m_pNIL == i_pNode->pRight)
|
|
)
|
|
{
|
|
//y has a m_pNIL node as a child
|
|
l_pY = i_pNode;
|
|
}
|
|
else
|
|
{
|
|
//find tree successor with a m_pNIL node as a child
|
|
l_pY = i_pNode->pRight;
|
|
while (m_pNIL != l_pY->pLeft)
|
|
{
|
|
l_pY = l_pY->pLeft;
|
|
}
|
|
}
|
|
|
|
//x is y's only child
|
|
if (m_pNIL != l_pY->pLeft)
|
|
{
|
|
l_pX = l_pY->pLeft;
|
|
}
|
|
else
|
|
{
|
|
l_pX = l_pY->pRight;
|
|
}
|
|
|
|
/* remove y from the parent chain */
|
|
l_pX->pParent = l_pY->pParent;
|
|
if (l_pY->pParent)
|
|
{
|
|
if (l_pY == l_pY->pParent->pLeft)
|
|
{
|
|
l_pY->pParent->pLeft = l_pX;
|
|
}
|
|
else
|
|
{
|
|
l_pY->pParent->pRight = l_pX;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
m_pRoot = l_pX;
|
|
}
|
|
|
|
if (l_pY != i_pNode)
|
|
{
|
|
i_pNode->tData = l_pY->tData;
|
|
}
|
|
|
|
if (l_pY->bColor == RBT_NODE_BLACK)
|
|
{
|
|
Fix_Del (l_pX);
|
|
}
|
|
|
|
Node_Free(l_pY);
|
|
}//Del
|
|
|
|
|
|
////////////////////////////////////////////////////////////////////////////
|
|
//Find
|
|
tData_Type Find(tKey_Type i_pKey)
|
|
{
|
|
sNode *l_pCurrent = m_pRoot;
|
|
while (m_pNIL != l_pCurrent)
|
|
{
|
|
if(Is_Qual(i_pKey, l_pCurrent->tData))
|
|
{
|
|
return (l_pCurrent->tData);
|
|
}
|
|
else
|
|
{
|
|
l_pCurrent = Is_Key_Less (i_pKey, l_pCurrent->tData)
|
|
? l_pCurrent->pLeft
|
|
: l_pCurrent->pRight;
|
|
}
|
|
}
|
|
|
|
return NULL;
|
|
}//Find
|
|
|
|
|
|
////////////////////////////////////////////////////////////////////////////
|
|
//Clear
|
|
void Clear()
|
|
{
|
|
if (m_pNIL == m_pRoot)
|
|
{
|
|
return;
|
|
}
|
|
|
|
Clear(m_pRoot);
|
|
m_pRoot = m_pNIL;
|
|
}//Clear
|
|
|
|
|
|
////////////////////////////////////////////////////////////////////////////
|
|
//Get_Depth
|
|
void Get_Depth(tUINT32 *o_pMin, tUINT32 *o_pMax)
|
|
{
|
|
if ( (NULL == o_pMin)
|
|
|| (NULL == o_pMax)
|
|
)
|
|
{
|
|
return;
|
|
}
|
|
|
|
*o_pMin = ((tUINT32)~((tUINT32)0)); //max possible value
|
|
*o_pMax = 0;
|
|
|
|
if (m_pNIL != m_pRoot)
|
|
{
|
|
Get_Depth(m_pRoot, o_pMin, o_pMax, 0);
|
|
}
|
|
}//Get_Depth
|
|
|
|
private:
|
|
////////////////////////////////////////////////////////////////////////////
|
|
//Pool_Segment_Create
|
|
tBOOL Pool_Segment_Create()
|
|
{
|
|
tBOOL l_bReturn = FALSE;
|
|
|
|
tPool_Segment *l_pPool = (tPool_Segment*)MemAlloc(sizeof(tPool_Segment));
|
|
|
|
if (l_pPool)
|
|
{
|
|
memset(l_pPool, 0, sizeof(tPool_Segment));
|
|
l_pPool->m_dwCount = m_dwPool_Size;
|
|
l_pPool->m_pNodes = (sNode*)MemAlloc(sizeof(sNode) * l_pPool->m_dwCount);
|
|
|
|
if (l_pPool->m_pNodes)
|
|
{
|
|
sNode *l_pNode = NULL;
|
|
|
|
memset(l_pPool->m_pNodes,
|
|
0,
|
|
sizeof(tPool_Segment) * l_pPool->m_dwCount
|
|
);
|
|
|
|
l_pNode = l_pPool->m_pNodes;
|
|
|
|
for (tUINT32 l_dwIDX = 1; l_dwIDX < l_pPool->m_dwCount; l_dwIDX++)
|
|
{
|
|
l_pNode->pRight = (l_pNode + 1);
|
|
l_pNode ++;
|
|
}
|
|
|
|
l_bReturn = TRUE;
|
|
l_pPool->m_pNext = m_pPool_First;
|
|
m_pPool_First = l_pPool;
|
|
l_pNode->pRight = m_pPool_Node_First;
|
|
m_pPool_Node_First = l_pPool->m_pNodes;
|
|
}
|
|
}
|
|
|
|
if (FALSE == l_bReturn)
|
|
{
|
|
Pool_Segment_Free(l_pPool);
|
|
}
|
|
|
|
return l_bReturn;
|
|
}//Pool_Segment_Create
|
|
|
|
|
|
////////////////////////////////////////////////////////////////////////////
|
|
//Pool_Segment_Free
|
|
void Pool_Segment_Free(tPool_Segment *io_pPool)
|
|
{
|
|
if (io_pPool)
|
|
{
|
|
if (io_pPool->m_pNodes)
|
|
{
|
|
MemFree(io_pPool->m_pNodes);
|
|
io_pPool->m_pNodes = NULL;
|
|
}
|
|
MemFree(io_pPool);
|
|
}
|
|
}//Pool_Segment_Free
|
|
|
|
|
|
////////////////////////////////////////////////////////////////////////////
|
|
//Clear
|
|
void Clear(sNode *i_pNode)
|
|
{
|
|
if (m_pNIL != i_pNode->pLeft)
|
|
{
|
|
Clear(i_pNode->pLeft);
|
|
}
|
|
|
|
if (m_pNIL != i_pNode->pRight)
|
|
{
|
|
Clear(i_pNode->pRight);
|
|
}
|
|
|
|
if (m_bData_Free)
|
|
{
|
|
Data_Release(i_pNode->tData);
|
|
}
|
|
|
|
if (i_pNode->pParent)
|
|
{
|
|
if (i_pNode == i_pNode->pParent->pRight)
|
|
{
|
|
i_pNode->pParent->pRight = m_pNIL;
|
|
}
|
|
else
|
|
{
|
|
i_pNode->pParent->pLeft = m_pNIL;
|
|
}
|
|
}
|
|
|
|
Node_Free(i_pNode);
|
|
}//Clear
|
|
|
|
|
|
////////////////////////////////////////////////////////////////////////////
|
|
//Get_Depth
|
|
void Get_Depth(sNode *i_pNode,
|
|
tUINT32 *o_pMin,
|
|
tUINT32 *o_pMax,
|
|
tUINT32 i_dwCurrent
|
|
)
|
|
{
|
|
i_dwCurrent ++;
|
|
|
|
if ( (m_pNIL == i_pNode->pLeft)
|
|
&& (m_pNIL == i_pNode->pRight)
|
|
)
|
|
{
|
|
if (i_dwCurrent < (*o_pMin))
|
|
{
|
|
*o_pMin = i_dwCurrent;
|
|
}
|
|
|
|
if (i_dwCurrent > (*o_pMax))
|
|
{
|
|
*o_pMax = i_dwCurrent;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
if (m_pNIL != i_pNode->pLeft)
|
|
{
|
|
Get_Depth(i_pNode->pLeft, o_pMin, o_pMax, i_dwCurrent);
|
|
}
|
|
|
|
if (m_pNIL != i_pNode->pRight)
|
|
{
|
|
Get_Depth(i_pNode->pRight, o_pMin, o_pMax, i_dwCurrent);
|
|
}
|
|
}
|
|
}//Get_Depth
|
|
|
|
|
|
////////////////////////////////////////////////////////////////////////////
|
|
//Rotate_Left
|
|
void Rotate_Left(sNode *i_pNode)
|
|
{
|
|
sNode *l_pNodeR = i_pNode->pRight;
|
|
|
|
i_pNode->pRight = l_pNodeR->pLeft;
|
|
if (m_pNIL != l_pNodeR->pLeft)
|
|
{
|
|
l_pNodeR->pLeft->pParent = i_pNode;
|
|
}
|
|
|
|
if (m_pNIL != l_pNodeR)
|
|
{
|
|
l_pNodeR->pParent = i_pNode->pParent;
|
|
}
|
|
|
|
if (i_pNode->pParent)
|
|
{
|
|
if (i_pNode == i_pNode->pParent->pLeft)
|
|
{
|
|
i_pNode->pParent->pLeft = l_pNodeR;
|
|
}
|
|
else
|
|
{
|
|
i_pNode->pParent->pRight = l_pNodeR;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
m_pRoot = l_pNodeR;
|
|
}
|
|
|
|
l_pNodeR->pLeft = i_pNode;
|
|
if (m_pNIL != i_pNode)
|
|
{
|
|
i_pNode->pParent = l_pNodeR;
|
|
}
|
|
}//Rotate_Left
|
|
|
|
|
|
////////////////////////////////////////////////////////////////////////////
|
|
//Rotate_Right
|
|
void Rotate_Right(sNode *i_pNode)
|
|
{
|
|
sNode *l_pNodeL = i_pNode->pLeft;
|
|
|
|
i_pNode->pLeft = l_pNodeL->pRight;
|
|
if (m_pNIL != l_pNodeL->pRight)
|
|
{
|
|
l_pNodeL->pRight->pParent = i_pNode;
|
|
}
|
|
|
|
if (m_pNIL != l_pNodeL)
|
|
{
|
|
l_pNodeL->pParent = i_pNode->pParent;
|
|
}
|
|
|
|
if (i_pNode->pParent)
|
|
{
|
|
if (i_pNode == i_pNode->pParent->pRight)
|
|
{
|
|
i_pNode->pParent->pRight = l_pNodeL;
|
|
}
|
|
else
|
|
{
|
|
i_pNode->pParent->pLeft = l_pNodeL;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
m_pRoot = l_pNodeL;
|
|
}
|
|
|
|
l_pNodeL->pRight = i_pNode;
|
|
|
|
if (m_pNIL != i_pNode)
|
|
{
|
|
i_pNode->pParent = l_pNodeL;
|
|
}
|
|
}//Rotate_Right
|
|
|
|
|
|
////////////////////////////////////////////////////////////////////////////
|
|
//Fix_Push
|
|
void Fix_Push(sNode *i_pNode)
|
|
{
|
|
while ( (i_pNode != m_pRoot)
|
|
&& (RBT_NODE_RED == i_pNode->pParent->bColor)
|
|
)
|
|
{
|
|
// we have a violation
|
|
if (i_pNode->pParent == i_pNode->pParent->pParent->pLeft)
|
|
{
|
|
sNode *l_pUncle = i_pNode->pParent->pParent->pRight;
|
|
if (RBT_NODE_RED == l_pUncle->bColor)
|
|
{
|
|
i_pNode->pParent->bColor = RBT_NODE_BLACK;
|
|
l_pUncle->bColor = RBT_NODE_BLACK;
|
|
i_pNode->pParent->pParent->bColor = RBT_NODE_RED;
|
|
i_pNode = i_pNode->pParent->pParent;
|
|
}
|
|
else //(RBT_NODE_BLACK == l_pUncle->bColor)
|
|
{
|
|
if (i_pNode == i_pNode->pParent->pRight)
|
|
{
|
|
/* make x a left child */
|
|
i_pNode = i_pNode->pParent;
|
|
Rotate_Left(i_pNode);
|
|
}
|
|
|
|
/* recolor and rotate */
|
|
i_pNode->pParent->bColor = RBT_NODE_BLACK;
|
|
i_pNode->pParent->pParent->bColor = RBT_NODE_RED;
|
|
Rotate_Right(i_pNode->pParent->pParent);
|
|
}
|
|
}
|
|
else //(i_pNode->pParent == i_pNode->pParent->pParent->pRight)
|
|
{
|
|
sNode *l_pUncle = i_pNode->pParent->pParent->pLeft;
|
|
if (RBT_NODE_RED == l_pUncle->bColor)
|
|
{
|
|
i_pNode->pParent->bColor = RBT_NODE_BLACK;
|
|
l_pUncle->bColor = RBT_NODE_BLACK;
|
|
i_pNode->pParent->pParent->bColor = RBT_NODE_RED;
|
|
i_pNode = i_pNode->pParent->pParent;
|
|
}
|
|
else //(RBT_NODE_BLACK == l_pUncle->bColor)
|
|
{
|
|
if (i_pNode == i_pNode->pParent->pLeft)
|
|
{
|
|
i_pNode = i_pNode->pParent;
|
|
Rotate_Right(i_pNode);
|
|
}
|
|
|
|
i_pNode->pParent->bColor = RBT_NODE_BLACK;
|
|
i_pNode->pParent->pParent->bColor = RBT_NODE_RED;
|
|
Rotate_Left(i_pNode->pParent->pParent);
|
|
}
|
|
}
|
|
}
|
|
|
|
m_pRoot->bColor = RBT_NODE_BLACK;
|
|
}//Fix_Push
|
|
|
|
|
|
////////////////////////////////////////////////////////////////////////////
|
|
//Fix_Del
|
|
void Fix_Del(sNode *i_pNode)
|
|
{
|
|
while ( (i_pNode != m_pRoot)
|
|
&& (RBT_NODE_BLACK == i_pNode->bColor)
|
|
)
|
|
{
|
|
if (i_pNode == i_pNode->pParent->pLeft)
|
|
{
|
|
sNode *l_pBrother = i_pNode->pParent->pRight;
|
|
if (RBT_NODE_RED == l_pBrother->bColor)
|
|
{
|
|
l_pBrother->bColor = RBT_NODE_BLACK;
|
|
i_pNode->pParent->bColor = RBT_NODE_RED;
|
|
Rotate_Left(i_pNode->pParent);
|
|
l_pBrother = i_pNode->pParent->pRight;
|
|
}
|
|
|
|
if ( (RBT_NODE_BLACK == l_pBrother->pLeft->bColor)
|
|
&& (RBT_NODE_BLACK == l_pBrother->pRight->bColor)
|
|
)
|
|
{
|
|
l_pBrother->bColor = RBT_NODE_RED;
|
|
i_pNode = i_pNode->pParent;
|
|
}
|
|
else
|
|
{
|
|
if (RBT_NODE_BLACK == l_pBrother->pRight->bColor)
|
|
{
|
|
l_pBrother->pLeft->bColor = RBT_NODE_BLACK;
|
|
l_pBrother->bColor = RBT_NODE_RED;
|
|
Rotate_Right (l_pBrother);
|
|
l_pBrother = i_pNode->pParent->pRight;
|
|
}
|
|
l_pBrother->bColor = i_pNode->pParent->bColor;
|
|
i_pNode->pParent->bColor = RBT_NODE_BLACK;
|
|
l_pBrother->pRight->bColor = RBT_NODE_BLACK;
|
|
Rotate_Left (i_pNode->pParent);
|
|
i_pNode = m_pRoot;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
sNode *l_pBrother = i_pNode->pParent->pLeft;
|
|
if (RBT_NODE_RED == l_pBrother->bColor)
|
|
{
|
|
l_pBrother->bColor = RBT_NODE_BLACK;
|
|
i_pNode->pParent->bColor = RBT_NODE_RED;
|
|
Rotate_Right (i_pNode->pParent);
|
|
l_pBrother = i_pNode->pParent->pLeft;
|
|
}
|
|
if ( (RBT_NODE_BLACK == l_pBrother->pRight->bColor)
|
|
&& (RBT_NODE_BLACK == l_pBrother->pLeft->bColor)
|
|
)
|
|
{
|
|
l_pBrother->bColor = RBT_NODE_RED;
|
|
i_pNode = i_pNode->pParent;
|
|
}
|
|
else
|
|
{
|
|
if (RBT_NODE_BLACK == l_pBrother->pLeft->bColor)
|
|
{
|
|
l_pBrother->pRight->bColor = RBT_NODE_BLACK;
|
|
l_pBrother->bColor = RBT_NODE_RED;
|
|
Rotate_Left (l_pBrother);
|
|
l_pBrother = i_pNode->pParent->pLeft;
|
|
}
|
|
l_pBrother->bColor = i_pNode->pParent->bColor;
|
|
i_pNode->pParent->bColor = RBT_NODE_BLACK;
|
|
l_pBrother->pLeft->bColor = RBT_NODE_BLACK;
|
|
Rotate_Right (i_pNode->pParent);
|
|
i_pNode = m_pRoot;
|
|
}
|
|
}
|
|
}
|
|
|
|
i_pNode->bColor = RBT_NODE_BLACK;
|
|
}//Fix_Del
|
|
|
|
protected:
|
|
////////////////////////////////////////////////////////////////////////////
|
|
// Data_Release
|
|
// override this function in derived class to implement specific data
|
|
// destructor(structures as example)
|
|
virtual tBOOL Data_Release(tData_Type i_pData)
|
|
{
|
|
if (NULL == i_pData)
|
|
{
|
|
return FALSE;
|
|
}
|
|
|
|
delete i_pData;
|
|
return TRUE;
|
|
}// Data_Release
|
|
|
|
|
|
////////////////////////////////////////////////////////////////////////////
|
|
//MemAlloc
|
|
//override this function in derived class to implement own memory allocation
|
|
//mechanism, it will be used everywhere in this class
|
|
virtual void *MemAlloc(size_t i_szSize)
|
|
{
|
|
return new tUINT8[i_szSize];
|
|
}//MemAlloc
|
|
|
|
|
|
////////////////////////////////////////////////////////////////////////////
|
|
//
|
|
//override this function in derived class to implement own memory deallocation
|
|
//mechanism, it will be used everywhere in this class
|
|
virtual void MemFree(void * i_pMemory)
|
|
{
|
|
delete [] ((tUINT8*)i_pMemory);
|
|
}
|
|
|
|
|
|
////////////////////////////////////////////////////////////////////////////
|
|
//Node_Allocate
|
|
virtual sNode *Node_Allocate()
|
|
{
|
|
sNode *l_pReturn = NULL;
|
|
if (NULL == m_pPool_Node_First)
|
|
{
|
|
Pool_Segment_Create();
|
|
}
|
|
|
|
l_pReturn = m_pPool_Node_First;
|
|
|
|
if (m_pPool_Node_First)
|
|
{
|
|
m_pPool_Node_First = m_pPool_Node_First->pRight;
|
|
}
|
|
|
|
return l_pReturn;
|
|
}//Node_Allocate
|
|
|
|
|
|
////////////////////////////////////////////////////////////////////////////
|
|
//Node_Free
|
|
virtual void Node_Free(sNode *i_pNode)
|
|
{
|
|
memset(i_pNode, 0, sizeof(sNode));
|
|
i_pNode->pRight = m_pPool_Node_First;
|
|
m_pPool_Node_First = i_pNode;
|
|
}//Node_Free
|
|
|
|
|
|
////////////////////////////////////////////////////////////////////////////
|
|
// This is abstract functions, you should to implement them //
|
|
////////////////////////////////////////////////////////////////////////////
|
|
|
|
////////////////////////////////////////////////////////////////////////////
|
|
//Return
|
|
//TRUE - if (i_pKey < i_pData::key)
|
|
//FALSE - otherwise
|
|
virtual tBOOL Is_Key_Less(tKey_Type i_pKey, tData_Type i_pData) = 0;
|
|
|
|
////////////////////////////////////////////////////////////////////////////
|
|
//Return
|
|
//TRUE - if (i_pKey == i_pData::key)
|
|
//FALSE - otherwise
|
|
virtual tBOOL Is_Qual(tKey_Type i_pKey, tData_Type i_pData) = 0;
|
|
};
|
|
|
|
|
|
|
|
|
|
////////////////////////////////////////////////////////////////////////////////
|
|
// TEST //
|
|
////////////////////////////////////////////////////////////////////////////////
|
|
|
|
// #include <Windows.h>
|
|
// #include <stdio.h>
|
|
// #include <conio.h>
|
|
//
|
|
// #include "RBTree.h"
|
|
//
|
|
// #define _CRTDBG_MAP_ALLOC
|
|
// #include <crtdbg.h>
|
|
//
|
|
// struct sInt
|
|
// {
|
|
// int val;
|
|
// };
|
|
//
|
|
//
|
|
// class CIntMap:
|
|
// public CRBTree<sInt*, int>
|
|
// {
|
|
// public:
|
|
// CIntMap():
|
|
// CRBTree(1024, FALSE)
|
|
// {
|
|
//
|
|
// }
|
|
// protected:
|
|
// ////////////////////////////////////////////////////////////////////////////
|
|
// //Return
|
|
// //TRUE - if (i_pKey < i_pData::key)
|
|
// //FALSE - otherwise
|
|
// tBOOL Is_Key_Less(int i_iKey, sInt *i_pData)
|
|
// {
|
|
// return (i_iKey < i_pData->val);
|
|
// }
|
|
//
|
|
// ////////////////////////////////////////////////////////////////////////////
|
|
// //Return
|
|
// //TRUE - if (i_pKey == i_pData::key)
|
|
// //FALSE - otherwise
|
|
// virtual tBOOL Is_Qual(int i_iKey, sInt *i_pData)
|
|
// {
|
|
// return (i_iKey == i_pData->val);
|
|
// }
|
|
//
|
|
// };
|
|
//
|
|
//
|
|
// int wmain(int argc, wchar_t* argv[])
|
|
// {
|
|
// CIntMap *l_pMap = new CIntMap();
|
|
// tUINT32 l_dwMax = 1000000;
|
|
// sInt *l_pInt = new sInt[l_dwMax];
|
|
// tUINT32 l_dwMiss = 0;
|
|
//
|
|
//
|
|
// for (tUINT32 l_dwIteration = 0; l_dwIteration < 1000; l_dwIteration++)
|
|
// {
|
|
// l_dwMiss = 0;
|
|
// srand(l_dwIteration);
|
|
//
|
|
// for (tUINT32 l_dwIDX = 0; l_dwIDX < l_dwMax; l_dwIDX++)
|
|
// {
|
|
// l_pInt[l_dwIDX].val = rand()*rand();
|
|
//
|
|
// if (&l_pInt[l_dwIDX] != l_pMap->Push(&l_pInt[l_dwIDX], l_pInt[l_dwIDX].val))
|
|
// {
|
|
// l_dwMiss ++;
|
|
// }
|
|
// }
|
|
//
|
|
// tUINT32 l_dwDMin = 0;
|
|
// tUINT32 l_dwDMax = 0;
|
|
// l_pMap->Get_Depth(&l_dwDMin, &l_dwDMax);
|
|
//
|
|
// printf("Iteration[%d] Miss count = %d, Depth = %d/%d\n",
|
|
// l_dwIteration,
|
|
// l_dwMiss,
|
|
// l_dwDMin,
|
|
// l_dwDMax
|
|
// );
|
|
//
|
|
// if ((l_dwDMin * 2) < l_dwDMax)
|
|
// {
|
|
// printf("Depth error = %d/%d\n", l_dwDMin, l_dwDMax);
|
|
// }
|
|
//
|
|
// l_pMap->Clear();
|
|
//
|
|
// if ((_kbhit()) && (27 == _getwch()))
|
|
// {
|
|
// wprintf(L"... exiting\n");
|
|
// break;
|
|
// }
|
|
// }
|
|
//
|
|
//
|
|
// delete l_pMap;
|
|
//
|
|
// delete [] l_pInt;
|
|
//
|
|
// //#ifndef NDEBUG
|
|
// //
|
|
// //int flag = _CrtSetDbgFlag(_CRTDBG_REPORT_FLAG); // Get current flag
|
|
// //
|
|
// //flag |= _CRTDBG_LEAK_CHECK_DF; // Turn on leak-checking bit
|
|
// //
|
|
// //_CrtSetDbgFlag(flag); // Set flag to the new value
|
|
// //
|
|
// //#endif
|
|
//
|
|
// _CrtDumpMemoryLeaks();
|
|
//
|
|
// return 0;
|
|
// }
|
|
|
|
|
|
#endif //RBTREE_H
|