Files
intel-graphics-compiler/3d/common/iStdLib/BinaryTree.h
2018-01-30 10:00:45 -08:00

1654 lines
39 KiB
C++

/*===================== begin_copyright_notice ==================================
Copyright (c) 2017 Intel Corporation
Permission is hereby granted, free of charge, to any person obtaining a
copy of this software and associated documentation files (the
"Software"), to deal in the Software without restriction, including
without limitation the rights to use, copy, modify, merge, publish,
distribute, sublicense, and/or sell copies of the Software, and to
permit persons to whom the Software is furnished to do so, subject to
the following conditions:
The above copyright notice and this permission notice shall be included
in all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
======================= end_copyright_notice ==================================*/
#pragma once
#include "Object.h"
#include "Stack.h"
#include "String.h"
namespace iSTD
{
/*****************************************************************************\
Struct: IsBinaryTreeTypeSupported
\*****************************************************************************/
template<typename T>
struct IsBinaryTreeTypeSupported { enum { value = false }; };
template<>
struct IsBinaryTreeTypeSupported<bool> { enum { value = true }; };
template<>
struct IsBinaryTreeTypeSupported<char> { enum { value = true }; };
template<>
struct IsBinaryTreeTypeSupported<unsigned char> { enum { value = true }; };
template<>
struct IsBinaryTreeTypeSupported<int> { enum { value = true }; };
template<>
struct IsBinaryTreeTypeSupported<unsigned int> { enum { value = true }; };
#ifndef __LP64__ // u/long on linux64 platform is 64-bit type and collides with U/INT64
template<>
struct IsBinaryTreeTypeSupported<long> { enum { value = true }; };
template<>
struct IsBinaryTreeTypeSupported<unsigned long> { enum { value = true }; };
#endif
template<>
struct IsBinaryTreeTypeSupported<float> { enum { value = true }; };
template<>
struct IsBinaryTreeTypeSupported<INT64> { enum { value = true }; };
template<>
struct IsBinaryTreeTypeSupported<UINT64> { enum { value = true }; };
template<typename T>
struct IsBinaryTreeTypeSupported<T*> { enum { value = true }; };
/*****************************************************************************\
Template Parameters
\*****************************************************************************/
#define BinaryTreeTemplateList class KeyType, class ElementType, class CAllocatorType
#define CBinaryTreeType CBinaryTree<KeyType, ElementType, CAllocatorType>
/*****************************************************************************\
Class:
CBinaryTree
Description:
Represents an unbalanced binary search tree
\*****************************************************************************/
template<BinaryTreeTemplateList>
class CBinaryTree : public CObject<CAllocatorType>
{
public:
CBinaryTree( void );
virtual ~CBinaryTree( void );
bool Add(
const KeyType &key,
const ElementType &element );
bool Get(
const KeyType &key,
ElementType &element ) const;
bool GetNext(
KeyType &key,
ElementType &element );
bool GetMin(
ElementType &element ) const;
bool GetMax(
ElementType &element ) const;
bool GetMin(
KeyType &key,
ElementType &element ) const;
bool GetMax(
KeyType &key,
ElementType &element ) const;
bool Remove(
const KeyType &key );
bool Remove(
const KeyType &key,
ElementType &element );
bool RemoveMin(
ElementType &element );
bool RemoveMax(
ElementType &element );
bool RemoveMin(
KeyType &key,
ElementType &element );
bool RemoveMax(
KeyType &key,
ElementType &element );
void RemoveAll( void );
bool IsEmpty( void ) const;
DWORD GetCount( void ) const;
void DebugPrint( void ) const;
C_ASSERT( IsBinaryTreeTypeSupported<ElementType>::value == true );
protected:
struct SNode
{
KeyType m_Key;
ElementType m_Element;
#ifdef _DEBUG
DWORD m_GetCount;
#endif
SNode* m_RightNode;
SNode* m_LeftNode;
};
bool AddElement(
SNode* &pTree,
const KeyType &key,
const ElementType &element );
bool GetElement(
SNode* pTree,
const KeyType &key,
ElementType &element ) const;
bool GetMinElement(
SNode* pTree,
KeyType &key,
ElementType &element ) const;
bool GetMaxElement(
SNode* pTree,
KeyType &key,
ElementType &element ) const;
bool GetNextElement(
SNode* pTree,
KeyType &key,
ElementType &element );
bool RemoveElement(
SNode* &pTree,
const KeyType &key,
ElementType &element );
bool RemoveMinElement(
SNode* &pTree,
KeyType &key,
ElementType &element );
bool RemoveMaxElement(
SNode* &pTree,
KeyType &key,
ElementType &element );
bool AddTree(
SNode* &pTree,
SNode* pNewTree );
void DeleteTree(
SNode* &pTree );
void DebugPrintTree(
const SNode* pTree,
const DWORD depth ) const;
SNode* CreateNode(
const KeyType &key,
const ElementType &element );
SNode* RemoveMinNode(
SNode* &pTree );
SNode* RemoveMaxNode(
SNode* &pTree );
void DeleteNode(
SNode* &pNode );
SNode* m_pTree;
DWORD m_Count;
#ifdef _DEBUG
DWORD m_AddCount;
DWORD m_RemoveCount;
DWORD m_MaxDepth;
#endif
DECL_DEBUG_MUTEX( m_InstanceNotThreadSafe )
};
/*****************************************************************************\
Function:
CBinaryTree Constructor
Description:
Initializes internal data
Input:
none
Output:
none
\*****************************************************************************/
template<BinaryTreeTemplateList>
CBinaryTreeType::CBinaryTree( void )
: CObject<CAllocatorType>()
{
m_pTree = NULL;
m_Count = 0;
#ifdef _DEBUG
m_AddCount = 0;
m_RemoveCount = 0;
m_MaxDepth = 0;
#endif
INIT_DEBUG_MUTEX( m_InstanceNotThreadSafe );
}
/*****************************************************************************\
Function:
CBinaryTree Destructor
Description:
Deletes internal data
Input:
none
Output:
none
\*****************************************************************************/
template<BinaryTreeTemplateList>
CBinaryTreeType::~CBinaryTree( void )
{
DeleteTree( m_pTree );
DELETE_DEBUG_MUTEX( m_InstanceNotThreadSafe );
}
/*****************************************************************************\
Function:
CBinaryTree::Add
Description:
Adds an element to the binary tree
Input:
const KeyType &key - key which determines sorting order of element
const ElementType &element - element to add to binary tree
Output:
bool - SUCCESS or FAIL
\*****************************************************************************/
template<BinaryTreeTemplateList>
bool CBinaryTreeType::Add(
const KeyType &key,
const ElementType &element )
{
ACQUIRE_DEBUG_MUTEX_WRITE( m_InstanceNotThreadSafe );
const bool success = AddElement( m_pTree, key, element );
ASSERT( success );
RELEASE_DEBUG_MUTEX_WRITE( m_InstanceNotThreadSafe );
return success;
}
/*****************************************************************************\
Function:
CBinaryTree::Get
Description:
Gets the element in the binary tree
Input:
const KeyType &key - key which determines sorting order of element
Output:
ElementType &element - element in binary tree
bool - SUCCESS or FAIL
\*****************************************************************************/
template<BinaryTreeTemplateList>
bool CBinaryTreeType::Get(
const KeyType &key,
ElementType &element ) const
{
ACQUIRE_DEBUG_MUTEX_READ( m_InstanceNotThreadSafe );
const bool success = GetElement( m_pTree, key, element );
RELEASE_DEBUG_MUTEX_READ( m_InstanceNotThreadSafe );
return success;
}
/*****************************************************************************\
Function:
CBinaryTree::GetMin
Description:
Gets the "minimum" element in the binary tree
Input:
none
Output:
ElementType &element - element in binary tree
bool - SUCCESS or FAIL
\*****************************************************************************/
template<BinaryTreeTemplateList>
bool CBinaryTreeType::GetMin(
ElementType &element ) const
{
ACQUIRE_DEBUG_MUTEX_READ( m_InstanceNotThreadSafe );
KeyType key;
const bool success = GetMinElement( m_pTree, key, element );
ASSERT( success );
RELEASE_DEBUG_MUTEX_READ( m_InstanceNotThreadSafe );
return success;
}
/*****************************************************************************\
Function:
CBinaryTree::GetMax
Description:
Gets the "maximum" element in the binary tree
Input:
none
Output:
ElementType &element - element in binary tree
bool - SUCCESS or FAIL
\*****************************************************************************/
template<BinaryTreeTemplateList>
bool CBinaryTreeType::GetMax(
ElementType &element ) const
{
ACQUIRE_DEBUG_MUTEX_READ( m_InstanceNotThreadSafe );
KeyType key;
const bool success = GetMaxElement( m_pTree, key, element );
ASSERT( success );
RELEASE_DEBUG_MUTEX_READ( m_InstanceNotThreadSafe );
return success;
}
/*****************************************************************************\
Function:
CBinaryTree::GetNext
Description:
Gets the next element in the binary tree
Input:
none
Output:
ElementType &element - element in binary tree
bool - SUCCESS or FAIL
\*****************************************************************************/
template<BinaryTreeTemplateList>
bool CBinaryTreeType::GetNext(
KeyType &key,
ElementType &element )
{
ACQUIRE_DEBUG_MUTEX_READ( m_InstanceNotThreadSafe );
const bool success = GetNextElement( m_pTree, key, element );
RELEASE_DEBUG_MUTEX_READ( m_InstanceNotThreadSafe );
return success;
}
/*****************************************************************************\
Function:
CBinaryTree::GetMin
Description:
Gets the "minimum" element in the binary tree
Input:
none
Output:
KeyType &key - key of the minimum element
ElementType &element - element in binary tree
bool - SUCCESS or FAIL
\*****************************************************************************/
template<BinaryTreeTemplateList>
bool CBinaryTreeType::GetMin(
KeyType &key,
ElementType &element ) const
{
ACQUIRE_DEBUG_MUTEX_READ( m_InstanceNotThreadSafe );
const bool success = GetMinElement( m_pTree, key, element );
ASSERT( success );
RELEASE_DEBUG_MUTEX_READ( m_InstanceNotThreadSafe );
return success;
}
/*****************************************************************************\
Function:
CBinaryTree::GetMax
Description:
Gets the "maximum" element in the binary tree
Input:
none
Output:
KeyType &key - key of the minimum element
ElementType &element - element in binary tree
bool - SUCCESS or FAIL
\*****************************************************************************/
template<BinaryTreeTemplateList>
bool CBinaryTreeType::GetMax(
KeyType &key,
ElementType &element ) const
{
ACQUIRE_DEBUG_MUTEX_READ( m_InstanceNotThreadSafe );
const bool success = GetMaxElement( m_pTree, key, element );
ASSERT( success );
RELEASE_DEBUG_MUTEX_READ( m_InstanceNotThreadSafe );
return success;
}
/*****************************************************************************\
Function:
CBinaryTree::Remove
Description:
Removes an element from the binary tree
Input:
const KeyType &key - key which determines sorting order of element
Output:
bool - SUCCESS or FAIL
\*****************************************************************************/
template<BinaryTreeTemplateList>
bool CBinaryTreeType::Remove(
const KeyType &key )
{
ACQUIRE_DEBUG_MUTEX_WRITE( m_InstanceNotThreadSafe );
ElementType element;
const bool success = RemoveElement( m_pTree, key, element );
ASSERT( success );
RELEASE_DEBUG_MUTEX_WRITE( m_InstanceNotThreadSafe );
return success;
}
/*****************************************************************************\
Function:
CBinaryTree::Remove
Description:
Removes an element from the binary tree
Input:
const KeyType &key - key which determines sorting order of element
Output:
ElementType &element - element in binary tree
bool - SUCCESS or FAIL
\*****************************************************************************/
template<BinaryTreeTemplateList>
bool CBinaryTreeType::Remove(
const KeyType &key,
ElementType &element )
{
ACQUIRE_DEBUG_MUTEX_WRITE( m_InstanceNotThreadSafe );
const bool success = RemoveElement( m_pTree, key, element );
ASSERT( success );
RELEASE_DEBUG_MUTEX_WRITE( m_InstanceNotThreadSafe );
return success;
}
/*****************************************************************************\
Function:
CBinaryTree::RemoveMin
Description:
Removes the minimum element from the binary tree
Input:
none
Output:
ElementType &element - element in binary tree
bool - SUCCESS or FAIL
\*****************************************************************************/
template<BinaryTreeTemplateList>
bool CBinaryTreeType::RemoveMin(
ElementType &element )
{
ACQUIRE_DEBUG_MUTEX_WRITE( m_InstanceNotThreadSafe );
KeyType key;
const bool success = RemoveMinElement( m_pTree, key, element );
ASSERT( success );
RELEASE_DEBUG_MUTEX_WRITE( m_InstanceNotThreadSafe );
return success;
}
/*****************************************************************************\
Function:
CBinaryTree::RemoveMax
Description:
Removes the maximum element from the binary tree
Input:
none
Output:
ElementType &element - element in binary tree
bool - SUCCESS or FAIL
\*****************************************************************************/
template<BinaryTreeTemplateList>
bool CBinaryTreeType::RemoveMax(
ElementType &element )
{
ACQUIRE_DEBUG_MUTEX_WRITE( m_InstanceNotThreadSafe );
KeyType key;
const bool success = RemoveMaxElement( m_pTree, key, element );
ASSERT( success );
RELEASE_DEBUG_MUTEX_WRITE( m_InstanceNotThreadSafe );
return success;
}
/*****************************************************************************\
Function:
CBinaryTree::RemoveMin
Description:
Removes the minimum element from the binary tree
Input:
none
Output:
KeyType &key - key of the minimum element
ElementType &element - element in binary tree
bool - SUCCESS or FAIL
\*****************************************************************************/
template<BinaryTreeTemplateList>
bool CBinaryTreeType::RemoveMin(
KeyType &key,
ElementType &element )
{
ACQUIRE_DEBUG_MUTEX_WRITE( m_InstanceNotThreadSafe );
const bool success = RemoveMinElement( m_pTree, key, element );
ASSERT( success );
RELEASE_DEBUG_MUTEX_WRITE( m_InstanceNotThreadSafe );
return success;
}
/*****************************************************************************\
Function:
CBinaryTree::RemoveMax
Description:
Removes the maximum element from the binary tree
Input:
none
Output:
KeyType &key - key of the minimum element
ElementType &element - element in binary tree
bool - SUCCESS or FAIL
\*****************************************************************************/
template<BinaryTreeTemplateList>
bool CBinaryTreeType::RemoveMax(
KeyType &key,
ElementType &element )
{
ACQUIRE_DEBUG_MUTEX_WRITE( m_InstanceNotThreadSafe );
const bool success = RemoveMaxElement( m_pTree, key, element );
ASSERT( success );
RELEASE_DEBUG_MUTEX_WRITE( m_InstanceNotThreadSafe );
return success;
}
/*****************************************************************************\
Function:
CBinaryTree::RemoveAll
Description:
Removes all elements from the binary tree
Input:
void
Output:
void
\*****************************************************************************/
template<BinaryTreeTemplateList>
void CBinaryTreeType::RemoveAll( void )
{
ACQUIRE_DEBUG_MUTEX_WRITE( m_InstanceNotThreadSafe );
DeleteTree( m_pTree );
#ifdef _DEBUG
m_RemoveCount += m_Count;
#endif
m_Count = 0;
RELEASE_DEBUG_MUTEX_WRITE( m_InstanceNotThreadSafe );
}
/*****************************************************************************\
Function:
CBinaryTree::IsEmpty
Description:
Determines if the binary tree is empty
Input:
void
Output:
bool
\*****************************************************************************/
template<BinaryTreeTemplateList>
bool CBinaryTreeType::IsEmpty( void ) const
{
const bool isEmpty = ( m_pTree == NULL );
return isEmpty;
}
/*****************************************************************************\
Function:
CBinaryTree::GetCount
Description:
Returns the number of nodes in the tree
Input:
void
Output:
DWORD
\*****************************************************************************/
template<BinaryTreeTemplateList>
DWORD CBinaryTreeType::GetCount( void ) const
{
const DWORD count = m_Count;
return count;
}
/*****************************************************************************\
Function:
CBinaryTree::DebugPrint
Description:
Prints the tree to std output for debug only
Input:
void
Output:
void
\*****************************************************************************/
template<BinaryTreeTemplateList>
void CBinaryTreeType::DebugPrint( void ) const
{
#ifdef _DEBUG
if( m_pTree )
{
DPF( GFXDBG_STDLIB, "%s\n", __FUNCTION__ );
DPF( GFXDBG_STDLIB, "\tAddress = %p\n", this );
DPF( GFXDBG_STDLIB, "\tCount = %d\n", m_Count );
DPF( GFXDBG_STDLIB, "\tAddCount = %d\n", m_AddCount );
DPF( GFXDBG_STDLIB, "\tRemoveCount = %d\n", m_RemoveCount );
DPF( GFXDBG_STDLIB, "\tMaxDepth = %d\n", m_MaxDepth );
DebugPrintTree( m_pTree, 0 );
}
#endif
}
/*****************************************************************************\
Function:
CBinaryTree::AddElement
Description:
Adds an element to the tree
Input:
SNode* &pTree - pointer to tree to add element
const KeyType &key - key which determines sorting order of element
const ElementType &element - element to add
Output:
bool - SUCCESS or FAIL
\*****************************************************************************/
template<BinaryTreeTemplateList>
bool CBinaryTreeType::AddElement(
SNode* &pTree,
const KeyType &key,
const ElementType &element )
{
SNode** ppNode = &pTree;
SNode* pNode = *ppNode;
#ifdef _DEBUG
DWORD depth = 1;
#endif
while( pNode )
{
// Two elements should not have the same key
if( pNode->m_Key == key )
{
if( pNode->m_Element == element )
{
// the identical node already exists in the tree
return true;
}
else
{
ASSERT(0);
return false;
}
}
// Add element to left sub-tree
else if( key < pNode->m_Key )
{
ppNode = &(pNode->m_LeftNode);
#ifdef _DEBUG
++depth;
#endif
}
// Add element to right sub-tree
else
{
ppNode = &(pNode->m_RightNode);
#ifdef _DEBUG
++depth;
#endif
}
pNode = *ppNode;
}
pNode = CreateNode( key, element );
if( pNode )
{
*ppNode = pNode;
#ifdef _DEBUG
++m_AddCount;
m_MaxDepth = iSTD::Max<DWORD>( m_MaxDepth, depth );
#endif
return true;
}
else
{
return false;
}
}
/*****************************************************************************\
Function:
CBinaryTree::GetElement
Description:
Gets the element from a tree
Input:
SNode* pTree - pointer to tree to search
const KeyType &key - key which determines sorting order of element
Output:
ElementType &element - element found
bool - SUCCESS or FAIL
\*****************************************************************************/
template<BinaryTreeTemplateList>
bool CBinaryTreeType::GetElement(
SNode* pTree,
const KeyType &key,
ElementType &element ) const
{
SNode* pNode = pTree;
while( pNode )
{
// Do keys match?
if( pNode->m_Key == key )
{
// Element found
element = pNode->m_Element;
#ifdef _DEBUG
pNode->m_GetCount++;
#endif
return true;
}
// Search left sub-tree
else if( key < pNode->m_Key )
{
pNode = pNode->m_LeftNode;
}
// Search right sub-tree
else
{
pNode = pNode->m_RightNode;
}
}
// Could not find the element
return false;
}
/*****************************************************************************\
Function:
CBinaryTree::GetMinElement
Description:
Gets the "minimum" element from a sub-tree
Input:
SNode* pTree - pointer to sub-tree to search
Output:
KeyType &key - key of element
ElementType &element - element found
bool - SUCCESS or FAIL
\*****************************************************************************/
template<BinaryTreeTemplateList>
bool CBinaryTreeType::GetMinElement(
SNode* pTree,
KeyType &key,
ElementType &element ) const
{
SNode* pNode = pTree;
while( pNode )
{
if( pNode->m_LeftNode )
{
pNode = pNode->m_LeftNode;
}
else
{
key = pNode->m_Key;
element = pNode->m_Element;
#ifdef _DEBUG
pNode->m_GetCount++;
#endif
return true;
}
}
return false;
}
/*****************************************************************************\
Function:
CBinaryTree::GetMaxElement
Description:
Gets the "maximum" element from a sub-tree
Input:
SNode* pTree - pointer to sub-tree to search
Output:
KeyType &key - key of element
ElementType &element - element found
bool - SUCCESS or FAIL
\*****************************************************************************/
template<BinaryTreeTemplateList>
bool CBinaryTreeType::GetMaxElement(
SNode* pTree,
KeyType &key,
ElementType &element ) const
{
SNode* pNode = pTree;
while( pNode )
{
if( pNode->m_RightNode )
{
pNode = pNode->m_RightNode;
}
else
{
key = pNode->m_Key;
element = pNode->m_Element;
#ifdef _DEBUG
pNode->m_GetCount++;
#endif
return true;
}
}
return false;
}
/*****************************************************************************\
Function:
CBinaryTree::GetNextElement
Description:
Gets the next element from a sub-tree
Input:
SNode* pTree - pointer to sub-tree to search
Output:
KeyType &key - key of element
ElementType &element - element found
bool - SUCCESS or FAIL
\*****************************************************************************/
template<BinaryTreeTemplateList>
bool CBinaryTreeType::GetNextElement(
SNode* pTree,
KeyType &key,
ElementType &element )
{
static const DWORD prev_count = 1024;
DWORD prev_pos = 0;
SNode* pNode = pTree;
SNode* prev[ prev_count ];
prev[ prev_pos ] = 0;
while( pNode )
{
// Do keys match?
if( pNode->m_Key == key )
{
// Element found
if( pNode->m_RightNode )
{
// there is right child - return it or leftmost node of it's subtree
pNode = pNode->m_RightNode;
while( pNode->m_LeftNode )
{
pNode = pNode->m_LeftNode;
}
key = pNode->m_Key;
element = pNode->m_Element;
return true;
}
else
{
// there is no right child
// must traverse up as long as node is right child of it's parent
// ...and parent is not NULL
while( prev[ prev_pos ]!=0
&& prev[ prev_pos ]->m_RightNode == pNode )
{
pNode = prev[ prev_pos ];
--prev_pos;
}
if( prev[ prev_pos ]==0 )
{
// node is root - there is no 'next'
return false;
}
else
{ // node is not root - it has to be left child of it's parent
key = prev[ prev_pos ]->m_Key;
element = prev[ prev_pos ]->m_Element;
return true;
}
}
}
// Search left sub-tree
else if( key < pNode->m_Key )
{
++prev_pos;
ASSERT( prev_pos < prev_count );
prev[ prev_pos ] = pNode;
pNode = pNode->m_LeftNode;
}
// Search right sub-tree
else
{
++prev_pos;
ASSERT( prev_pos < prev_count );
prev[ prev_pos ] = pNode;
pNode = pNode->m_RightNode;
}
}
// Could not find the element
return false;
}
/*****************************************************************************\
Function:
CBinaryTree::RemoveElement
Description:
Deletes the element from a sub-tree
Input:
SNode* &pTree - pointer to sub-tree to search
const KeyType &key - key which determines sorting order of element
Output:
ElementType &element - element found
bool - SUCCESS or FAIL
\*****************************************************************************/
template<BinaryTreeTemplateList>
bool CBinaryTreeType::RemoveElement(
SNode* &pTree,
const KeyType &key,
ElementType &element )
{
SNode** ppNode = &pTree;
SNode* pNode = *ppNode;
while( pNode )
{
// Do keys match?
if( pNode->m_Key == key )
{
// Cache the pointer to the node containing the element
SNode* pRemoveNode = pNode;
if( pRemoveNode->m_LeftNode &&
pRemoveNode->m_RightNode )
{
pNode = RemoveMaxNode( pRemoveNode->m_LeftNode );
ASSERT( pNode );
if( pNode )
{
ASSERT( pNode->m_LeftNode == NULL );
pNode->m_LeftNode = pRemoveNode->m_LeftNode;
ASSERT( ( pNode->m_LeftNode )
? !( pNode->m_Key < pNode->m_LeftNode->m_Key )
: 1 );
ASSERT( pNode->m_RightNode == NULL );
pNode->m_RightNode = pRemoveNode->m_RightNode;
ASSERT( ( pNode->m_RightNode )
? ( pNode->m_Key < pNode->m_RightNode->m_Key )
: 1 );
}
pRemoveNode->m_LeftNode = NULL;
pRemoveNode->m_RightNode = NULL;
}
else if( pRemoveNode->m_LeftNode )
{
pNode = pRemoveNode->m_LeftNode;
pRemoveNode->m_LeftNode = NULL;
}
else if( pRemoveNode->m_RightNode )
{
pNode = pRemoveNode->m_RightNode;
pRemoveNode->m_RightNode = NULL;
}
else
{
pNode = NULL;
}
// Return the element
element = pRemoveNode->m_Element;
// Delete the node
DeleteNode( pRemoveNode );
*ppNode = pNode;
#ifdef _DEBUG
++m_RemoveCount;
#endif
return true;
}
// Search left sub-tree
else if( key < pNode->m_Key )
{
ppNode = &(pNode->m_LeftNode);
}
// Search right sub-tree
else
{
ppNode = &(pNode->m_RightNode);
}
pNode = *ppNode;
}
return false;
}
/*****************************************************************************\
Function:
CBinaryTree::RemoveMinElement
Description:
Deletes the minimum element from a sub-tree
Input:
SNode* &pTree - pointer to sub-tree to search
Output:
KeyType &key - key of element
ElementType &element - element found
bool - SUCCESS or FAIL
\*****************************************************************************/
template<BinaryTreeTemplateList>
bool CBinaryTreeType::RemoveMinElement(
SNode* &pTree,
KeyType &key,
ElementType &element )
{
SNode** ppNode = &pTree;
SNode* pNode = *ppNode;
while( pNode )
{
if( pNode->m_LeftNode )
{
ppNode = &(pNode->m_LeftNode);
pNode = *ppNode;
}
else
{
// Cache the pointer to the node containing the element
SNode* pRemoveNode = pNode;
pNode = pRemoveNode->m_RightNode;
pRemoveNode->m_RightNode = NULL;
// Return the key and element
key = pRemoveNode->m_Key;
element = pRemoveNode->m_Element;
// Delete the node
DeleteNode( pRemoveNode );
*ppNode = pNode;
#ifdef _DEBUG
++m_RemoveCount;
#endif
return true;
}
}
return false;
}
/*****************************************************************************\
Function:
CBinaryTree::RemoveMaxElement
Description:
Deletes the maximum element from a sub-tree
Input:
SNode* &pTree - pointer to sub-tree to search
Output:
KeyType &key - key of element
ElementType &element - element found
bool - SUCCESS or FAIL
\*****************************************************************************/
template<BinaryTreeTemplateList>
bool CBinaryTreeType::RemoveMaxElement(
SNode* &pTree,
KeyType &key,
ElementType &element )
{
SNode** ppNode = &pTree;
SNode* pNode = *ppNode;
while( pNode )
{
if( pNode->m_RightNode )
{
ppNode = &(pNode->m_RightNode);
pNode = *ppNode;
}
else
{
// Cache the pointer to the node containing the element
SNode* pRemoveNode = pNode;
pNode = pRemoveNode->m_LeftNode;
pRemoveNode->m_LeftNode = NULL;
// Return the key and element
key = pRemoveNode->m_Key;
element = pRemoveNode->m_Element;
// Delete the node
DeleteNode( pRemoveNode );
*ppNode = pNode;
#ifdef _DEBUG
++m_RemoveCount;
#endif
return true;
}
}
return false;
}
/*****************************************************************************\
Function:
CBinaryTree::AddTree
Description:
Adds a sub-tree
Input:
SNode* &pTree - pointer to sub-tree to add to
SNode* &pNewTree - pointer to sub-tree to add
Output:
bool
\*****************************************************************************/
template<BinaryTreeTemplateList>
bool CBinaryTreeType::AddTree(
SNode* &pTree,
SNode* pNewTree )
{
SNode** ppNode = &pTree;
SNode* pNode = *ppNode;
while( pNode )
{
// Two elements should not have the same key
if( pNode->m_Key == pNewTree->m_Key )
{
ASSERT( pNode->m_Element == pNewTree->m_Element );
return false;
}
// Add element to left sub-tree
else if( pNewTree->m_Key < pNode->m_Key )
{
ppNode = &(pNode->m_LeftNode);
}
// Add element to right sub-tree
else
{
ppNode = &(pNode->m_RightNode);
}
pNode = *ppNode;
}
*ppNode = pNewTree;
return true;
}
/*****************************************************************************\
Function:
CBinaryTree::DeleteTree
Description:
Recursive function to delete a sub-tree
Input:
SNode* &pTree - pointer to sub-tree to delete
Output:
void
\*****************************************************************************/
template<BinaryTreeTemplateList>
void CBinaryTreeType::DeleteTree( SNode* &pTree )
{
while( pTree )
{
SNode* pNode = RemoveMinNode( pTree );
DeleteNode( pNode );
}
}
/*****************************************************************************\
Function:
CBinaryTree::DebugPrintTree
Description:
Recursive function to debug a sub-tree
Input:
const SNode* tree - pointer to sub-tree to debug
const DWORD depth - current node depth
Output:
void
\*****************************************************************************/
template<BinaryTreeTemplateList>
void CBinaryTreeType::DebugPrintTree(
const SNode* pTree,
const DWORD depth ) const
{
#ifdef _DEBUG
if( pTree )
{
// Debug right sub-tree
if( pTree->m_RightNode )
{
DebugPrintTree( pTree->m_RightNode, depth + 1 );
}
iSTD::CString<CAllocatorType> strIndent;
strIndent = "\t";
DWORD i = 0;
for( i = 0; i < depth; ++i )
{
strIndent += " ";
}
iSTD::CString<CAllocatorType> strKeyData;
strKeyData = "{ ";
//DWORD* pKeyData = (DWORD*)&(pTree->m_Key);
//for( i = 0; i < sizeof(KeyType) / sizeof(DWORD); ++i )
//{
// strKeyData.AppendFormatted( "0x%08x ", pKeyData[i] );
//}
strKeyData += "}";
iSTD::CString<CAllocatorType> strElementData;
strElementData = "{ ";
//DWORD* pElementData = (DWORD*)&(pTree->m_Element);
//for( i = 0; i < sizeof(ElementType) / sizeof(DWORD); ++i )
//{
// strElementData.AppendFormatted( "0x%08x ", pElementData[i] );
//}
strElementData += "}";
DPF( GFXDBG_STDLIB, "%sBinaryTreeNode[%u].Key = %s\n",
(const char*)strIndent,
depth,
(const char*)strKeyData );
DPF( GFXDBG_STDLIB, "%sBinaryTreeNode[%u].Element = %s\n",
(const char*)strIndent,
depth,
(const char*)strElementData );
DPF( GFXDBG_STDLIB, "%sBinaryTreeNode[%u].GetCount = %d\n",
(const char*)strIndent,
depth,
pTree->m_GetCount );
// Debug left sub-tree
if( pTree->m_LeftNode )
{
DebugPrintTree( pTree->m_LeftNode, depth + 1 );
}
}
#endif
}
/*****************************************************************************\
Function:
CBinaryTree::CreateNode
Description:
Creates a node
Input:
const KeyType &key - key which determines sorting order of element
const ElementType &element - element in binary tree
Output:
SNode* - node created
\*****************************************************************************/
template<BinaryTreeTemplateList>
typename CBinaryTreeType::SNode* CBinaryTreeType::CreateNode(
const KeyType &key,
const ElementType &element )
{
// Create node to add element here
SNode* pNode = (SNode*)CAllocatorType::Allocate( sizeof(SNode) );
ASSERT( pNode );
if( pNode )
{
pNode->m_Key = key;
pNode->m_Element = element;
pNode->m_RightNode = NULL;
pNode->m_LeftNode = NULL;
#ifdef _DEBUG
pNode->m_GetCount = 0;
#endif
++m_Count;
}
return pNode;
}
/*****************************************************************************\
Function:
CBinaryTree::RemoveMinNode
Description:
Removes the min node from the tree
Input:
SNode* &pTree - tree to remove min node from
Output:
SNode* - node removed
\*****************************************************************************/
template<BinaryTreeTemplateList>
typename CBinaryTreeType::SNode* CBinaryTreeType::RemoveMinNode(
SNode* &pTree )
{
SNode** ppNode = &pTree;
SNode* pNode = *ppNode;
while( pNode )
{
if( pNode->m_LeftNode )
{
ppNode = &(pNode->m_LeftNode);
pNode = *ppNode;
}
else
{
// Cache the pointer to the node containing the element
SNode* pRemoveNode = pNode;
pNode = pRemoveNode->m_RightNode;
pRemoveNode->m_RightNode = NULL;
*ppNode = pNode;
return pRemoveNode;
}
}
return NULL;
}
/*****************************************************************************\
Function:
CBinaryTree::RemoveMaxNode
Description:
Removes the max node from the tree
Input:
SNode* &pTree - tree to remove max node from
Output:
SNode* - node removed
\*****************************************************************************/
template<BinaryTreeTemplateList>
typename CBinaryTreeType::SNode* CBinaryTreeType::RemoveMaxNode(
SNode* &pTree )
{
SNode** ppNode = &pTree;
SNode* pNode = *ppNode;
while( pNode )
{
if( pNode->m_RightNode )
{
ppNode = &(pNode->m_RightNode);
pNode = *ppNode;
}
else
{
// Cache the pointer to the node containing the element
SNode* pRemoveNode = pNode;
pNode = pRemoveNode->m_LeftNode;
pRemoveNode->m_LeftNode = NULL;
*ppNode = pNode;
return pRemoveNode;
}
}
return NULL;
}
/*****************************************************************************\
Function:
CBinaryTree::DeleteNode
Description:
Deletes a node
Input:
SNode* node - node to delete
Output:
void
\*****************************************************************************/
template<BinaryTreeTemplateList>
void CBinaryTreeType::DeleteNode( SNode* &pNode )
{
CAllocatorType::Deallocate( pNode );
--m_Count;
}
} // iSTD