RED BLACK TREE가 등장한 이유
#pragma once
#include <assert.h>
#include <functional>
enum NODE_COLOR
{
NC_RED,
NC_BLACK
};
template <typename Key, typename Value>
struct _tagRBBPair
{
Key first;
Value second;
};
template <typename Key, typename Value>
class CRBBTreeNode
{
template <typename Key, typename Value>
friend class CRBBTree;
template <typename Key, typename Value>
friend class CRBBTreeIterator;
private:
CRBBTreeNode()
{
m_pParent = m_pLeft = m_pRight = nullptr;
m_pNext = m_pPrev = nullptr;
m_eColor = NC_RED;
}
~CRBBTreeNode()
{
}
private:
CRBBTreeNode<Key, Value>* m_pParent;
CRBBTreeNode<Key, Value>* m_pLeft;
CRBBTreeNode<Key, Value>* m_pRight;
CRBBTreeNode<Key, Value>* m_pNext;
CRBBTreeNode<Key, Value>* m_pPrev;
public:
Key first;
Value second;
NODE_COLOR m_eColor;
};
template <typename Key, typename Value>
class CRBBTreeIterator
{
template <typename Key, typename Value>
friend class CRBBTree;
public:
CRBBTreeIterator()
{
m_pNode = nullptr;
}
~CRBBTreeIterator()
{
}
private:
CRBBTreeNode<Key, Value>* m_pNode;
public:
bool operator == (const CRBBTreeIterator<Key, Value>& iter)
{
return m_pNode == iter.m_pNode;
}
bool operator != (const CRBBTreeIterator<Key, Value>& iter)
{
return m_pNode != iter.m_pNode;
}
CRBBTreeIterator<Key, Value>& operator ++ ()
{
m_pNode = m_pNode->m_pNext;
return *this;
}
CRBBTreeIterator<Key, Value> operator ++ (int)
{
m_pNode = m_pNode->m_pNext;
return *this;
}
CRBBTreeIterator<Key, Value>& operator -- ()
{
m_pNode = m_pNode->m_pPrev;
return *this;
}
CRBBTreeIterator<Key, Value> operator -- (int)
{
m_pNode = m_pNode->m_pPrev;
return *this;
}
CRBBTreeNode<Key, Value>* operator -> ()
{
return m_pNode;
}
};
template <typename Key, typename Value>
class CRBBTree
{
public:
CRBBTree()
{
m_pRoot = nullptr;
m_pBegin = new NODE;
m_pEnd = new NODE;
m_pBegin->m_pNext = m_pEnd;
m_pEnd->m_pParent = m_pBegin;
m_iSize = 0;
Nil = new NODE;
Nil->m_eColor = NC_BLACK;
}
~CRBBTree()
{
clear();
delete m_pBegin;
delete m_pEnd;
delete Nil;
}
private:
typedef CRBBTreeNode<Key, Value> NODE;
typedef CRBBTreeNode<Key, Value>* PNODE;
public:
typedef _tagRBBPair<Key, Value> Pair;
typedef CRBBTreeIterator<Key, Value> iterator;
private:
PNODE m_pRoot;
PNODE m_pBegin;
PNODE m_pEnd;
PNODE Nil;
int m_iSize;
function<void(const Key&, const Value&, NODE_COLOR)> m_OutputFunc;
public:
void SetOutputFunc(void(*pFunc)(const Key&, const Value&, NODE_COLOR))
{
m_OutputFunc = bind(pFunc, placeholders::_1, placeholders::_2, placeholders::_3);
}
template <typename T>
void SetOutputFunc(T* pObj, void(T::*pFunc)(const Key&, const Value&, NODE_COLOR))
{
m_OutputFunc = bind(pFunc, pObj, placeholders::_1, placeholders::_2, placeholders::_3);
}
public:
void insert(const Pair& pair)
{
if (!m_pRoot)
{
m_pRoot = new NODE;
m_pRoot->first = pair.first;
m_pRoot->second = pair.second;
m_pBegin->m_pNext = m_pRoot;
m_pRoot->m_pPrev = m_pBegin;
m_pRoot->m_pNext = m_pEnd;
m_pEnd->m_pPrev = m_pRoot;
m_pRoot->m_eColor = NC_BLACK;
m_pRoot->m_pLeft = Nil;
m_pRoot->m_pRight = Nil;
}
else
{
PNODE pNewNode = insert(pair, m_pRoot);
insertBalance(pNewNode);
}
m_pRoot->m_eColor = NC_BLACK;
++m_iSize;
}
int size() const
{
return m_iSize;
}
bool empty() const
{
return m_iSize == 0;
}
iterator begin() const
{
iterator iter;
iter.m_pNode = m_pBegin->m_pNext;
return iter;
}
iterator end() const
{
iterator iter;
iter.m_pNode = m_pEnd;
return iter;
}
iterator find(const Key& key) const
{
if (empty())
return end();
PNODE pNode = find(key, m_pRoot);
if (!pNode)
return end();
iterator iter;
iter.m_pNode = pNode;
return iter;
}
iterator erase(iterator& iter)
{
if (empty() || iter == end())
return end();
if (iter.m_pNode->m_pLeft == Nil && iter.m_pNode->m_pRight == Nil)
{
if (!iter.m_pNode->m_pParent)
{
m_pRoot = nullptr;
delete iter.m_pNode;
--m_iSize;
return end();
}
else
{
if (iter.m_pNode->m_pParent->m_pLeft == iter.m_pNode)
{
iter.m_pNode->m_pParent->m_pLeft = Nil;
}
else
{
iter.m_pNode->m_pParent->m_pRight = Nil;
}
PNODE pNext = iter.m_pNode->m_pNext;
PNODE pPrev = iter.m_pNode->m_pPrev;
pNext->m_pPrev = pPrev;
pPrev->m_pNext = pNext;
delete iter.m_pNode;
--m_iSize;
iter.m_pNode = pNext;
return iter;
}
}
bool bLeft = false;
PNODE pDeleteNode = nullptr;
if (iter.m_pNode->m_pLeft != Nil)
{
bLeft = true;
pDeleteNode = FindLeftMax(iter.m_pNode->m_pLeft);
}
else
pDeleteNode = FindRightMin(iter.m_pNode->m_pRight);
NODE_COLOR eDeleteColor = iter.m_pNode->m_eColor;
iter.m_pNode->first = pDeleteNode->first;
iter.m_pNode->second = pDeleteNode->second;
iter.m_pNode->m_eColor = pDeleteNode->m_eColor;
iterator iter1;
iter1.m_pNode = iter.m_pNode;
if (bLeft)
iter1.m_pNode = iter.m_pNode->m_pNext;
PNODE pDeleteChild = nullptr;
if (pDeleteNode->m_pLeft != Nil)
pDeleteChild = pDeleteNode->m_pLeft;
else
pDeleteChild = pDeleteNode->m_pRight;
pDeleteChild->m_pParent = pDeleteNode->m_pParent;
if (pDeleteNode == pDeleteNode->m_pParent->m_pLeft)
pDeleteNode->m_pParent->m_pLeft = pDeleteChild;
else
pDeleteNode->m_pParent->m_pRight = pDeleteChild;
if (eDeleteColor == NC_BLACK)
erase(iter.m_pNode);
PNODE pPrev = pDeleteNode->m_pPrev;
PNODE pNext = pDeleteNode->m_pNext;
pPrev->m_pNext = pNext;
pNext->m_pPrev = pPrev;
delete pDeleteNode;
--m_iSize;
return iter1;
}
void clear()
{
clear(m_pRoot);
m_pRoot = nullptr;
m_iSize = 0;
m_pBegin->m_pNext = m_pEnd;
m_pEnd->m_pPrev = m_pBegin;
}
void PreOrder()
{
_PreOrder(m_pRoot);
}
void InOrder()
{
_InOrder(m_pRoot);
}
void PostOrder()
{
_PostOrder(m_pRoot);
}
private:
void _PreOrder(PNODE pNode)
{
if (pNode == nullptr || pNode == Nil)
return;
m_OutputFunc(pNode->first, pNode->second, pNode->m_eColor);
_PreOrder(pNode->m_pLeft);
_PreOrder(pNode->m_pRight);
}
void _InOrder(PNODE pNode)
{
if (pNode == nullptr || pNode == Nil)
return;
_InOrder(pNode->m_pLeft);
m_OutputFunc(pNode->first, pNode->second, pNode->m_eColor);
_InOrder(pNode->m_pRight);
}
void _PostOrder(PNODE pNode)
{
if (pNode == nullptr || pNode == Nil)
return;
_PostOrder(pNode->m_pLeft);
_PostOrder(pNode->m_pRight);
m_OutputFunc(pNode->first, pNode->second, pNode->m_eColor);
}
private:
PNODE insert(const Pair& pair, PNODE pNode)
{
if (!pNode || pNode == Nil)
return nullptr;
if (pNode->first > pair.first)
{
if (!pNode->m_pLeft || pNode->m_pLeft == Nil)
{
PNODE pNewNode = new NODE;
pNewNode->first = pair.first;
pNewNode->second = pair.second;
pNewNode->m_pParent = pNode;
pNode->m_pLeft = pNewNode;
PNODE pPrev = pNode->m_pPrev;
pPrev->m_pNext = pNewNode;
pNewNode->m_pPrev = pPrev;
pNewNode->m_pNext = pNode;
pNode->m_pPrev = pNewNode;
pNewNode->m_pLeft = Nil;
pNewNode->m_pRight = Nil;
return pNewNode;
}
else
{
return insert(pair, pNode->m_pLeft);
}
}
if (!pNode->m_pRight || pNode->m_pRight == Nil)
{
PNODE pNewNode = new NODE;
pNewNode->first = pair.first;
pNewNode->second = pair.second;
pNewNode->m_pParent = pNode;
pNode->m_pRight = pNewNode;
PNODE pNext = pNode->m_pNext;
pNext->m_pPrev = pNewNode;
pNewNode->m_pNext = pNext;
pNewNode->m_pPrev = pNode;
pNode->m_pNext = pNewNode;
pNewNode->m_pLeft = Nil;
pNewNode->m_pRight = Nil;
return pNewNode;
}
return insert(pair, pNode->m_pRight);
}
PNODE find(const Key& key, PNODE pNode) const
{
if (!pNode || pNode == Nil)
return nullptr;
if (pNode->first == key)
return pNode;
else if (pNode->first > key)
return find(key, pNode->m_pLeft);
return find(key, pNode->m_pRight);
}
PNODE FindLeftMax(PNODE pNode) const
{
if (!pNode->m_pRight || pNode->m_pLeft == Nil)
return pNode;
return FindLeftMax(pNode->m_pRight);
}
PNODE FindRightMin(PNODE pNode) const
{
if (!pNode->m_pLeft || pNode->m_pLeft == Nil)
return pNode;
return FindRightMin(pNode->m_pLeft);
}
void clear(PNODE pNode)
{
if (!pNode || pNode == Nil)
return;
clear(pNode->m_pLeft);
clear(pNode->m_pRight);
delete pNode;
}
void RotationLeft(PNODE pNode)
{
PNODE pRight = pNode->m_pRight;
PNODE pLeftChild = pRight->m_pLeft;
PNODE pParent = pNode->m_pParent;
if (pParent)
{
if (pParent->m_pLeft == pNode)
{
pParent->m_pLeft = pRight;
pRight->m_pParent = pParent;
}
else
{
pParent->m_pRight = pRight;
pRight->m_pParent = pParent;
}
}
else
{
m_pRoot = pRight;
pRight->m_pParent = nullptr;
}
pNode->m_pRight = pLeftChild;
if (pLeftChild && pLeftChild != Nil)
pLeftChild->m_pParent = pNode;
pRight->m_pLeft = pNode;
pNode->m_pParent = pRight;
}
void RotationRight(PNODE pNode)
{
PNODE pLeft = pNode->m_pLeft;
PNODE pRightChild = pLeft->m_pRight;
PNODE pParent = pNode->m_pParent;
if (pParent)
{
if (pParent->m_pLeft == pNode)
{
pParent->m_pLeft = pLeft;
pLeft->m_pParent = pParent;
}
else
{
pParent->m_pRight = pLeft;
pLeft->m_pParent = pParent;
}
}
else
{
m_pRoot = pLeft;
pLeft->m_pParent = nullptr;
}
pNode->m_pLeft = pRightChild;
if (pRightChild && pRightChild != Nil)
pRightChild->m_pParent = pNode;
pLeft->m_pRight = pNode;
pNode->m_pParent = pLeft;
}
void insertBalance(PNODE pNode)
{
if (!pNode || pNode == Nil || pNode == m_pRoot || !pNode->m_pParent->m_pParent ||
!pNode->m_pParent)
return;
else if (pNode->m_pParent->m_eColor == NC_BLACK)
return;
if (pNode->m_pParent == pNode->m_pParent->m_pParent->m_pLeft)
{
PNODE pUncle = nullptr;
if (pNode->m_pParent == pNode->m_pParent->m_pParent->m_pLeft)
pUncle = pNode->m_pParent->m_pParent->m_pRight;
else
pUncle = pNode->m_pParent->m_pParent->m_pLeft;
if (pUncle->m_eColor == NC_RED)
{
pNode->m_pParent->m_eColor = NC_BLACK;
pUncle->m_eColor = NC_BLACK;
pNode->m_pParent->m_pParent->m_eColor = NC_RED;
insertBalance(pNode->m_pParent->m_pParent);
}
else
{
if (pNode == pNode->m_pParent->m_pRight)
{
RotationLeft(pNode->m_pParent);
pNode = pNode->m_pLeft;
}
pNode->m_pParent->m_eColor = NC_BLACK;
pNode->m_pParent->m_pParent->m_eColor = NC_RED;
RotationRight(pNode->m_pParent->m_pParent);
}
}
else
{
PNODE pUncle = nullptr;
if (pNode->m_pParent == pNode->m_pParent->m_pParent->m_pLeft)
pUncle = pNode->m_pParent->m_pParent->m_pRight;
else
pUncle = pNode->m_pParent->m_pParent->m_pLeft;
if (pUncle->m_eColor == NC_RED)
{
pNode->m_pParent->m_eColor = NC_BLACK;
pUncle->m_eColor = NC_BLACK;
pNode->m_pParent->m_pParent->m_eColor = NC_RED;
insertBalance(pNode->m_pParent->m_pParent);
}
else
{
if (pNode == pNode->m_pParent->m_pLeft)
{
RotationRight(pNode->m_pParent);
pNode = pNode->m_pRight;
}
pNode->m_pParent->m_eColor = NC_BLACK;
pNode->m_pParent->m_pParent->m_eColor = NC_RED;
RotationLeft(pNode->m_pParent->m_pParent);
}
}
}
void erase(PNODE pNode)
{
PNODE pSibling = nullptr;
while (pNode != m_pRoot && pNode->m_eColor == NC_BLACK)
{
if (pNode == pNode->m_pParent->m_pLeft)
{
pSibling = pNode->m_pParent->m_pRight;
if (pSibling->m_eColor == NC_RED)
{
pSibling->m_eColor = NC_BLACK;
pNode->m_pParent->m_eColor = NC_RED;
RotationLeft(pNode->m_pParent);
pSibling = pNode->m_pParent->m_pRight;
}
if (pSibling->m_pLeft->m_eColor == NC_BLACK &&
pSibling->m_pRight->m_eColor == NC_BLACK)
{
if (pSibling != Nil)
pSibling->m_eColor = NC_RED;
if (pNode->m_pParent->m_eColor == NC_RED)
{
pNode->m_pParent->m_eColor = NC_BLACK;
break;
}
pNode = pNode->m_pParent;
continue;
}
else if (pSibling->m_pLeft->m_eColor == NC_RED)
{
if (pSibling != Nil)
pSibling->m_eColor = NC_RED;
pSibling->m_pLeft->m_eColor = NC_BLACK;
RotationRight(pSibling);
}
else if (pSibling->m_pRight->m_eColor == NC_RED)
{
if (pSibling != Nil)
pSibling->m_eColor = pNode->m_pParent->m_eColor;
pNode->m_pParent->m_eColor = NC_BLACK;
pSibling->m_pRight->m_eColor = NC_BLACK;
RotationLeft(pNode->m_pParent);
}
break;
}
else
{
pSibling = pNode->m_pParent->m_pLeft;
if (pSibling->m_eColor == NC_RED)
{
pSibling->m_eColor = NC_BLACK;
pNode->m_pParent->m_eColor = NC_RED;
RotationRight(pNode->m_pParent);
pSibling = pNode->m_pParent->m_pLeft;
}
if (pSibling->m_pLeft->m_eColor == NC_BLACK &&
pSibling->m_pRight->m_eColor == NC_BLACK)
{
if (pSibling != Nil)
pSibling->m_eColor = NC_RED;
if (pNode->m_pParent->m_eColor == NC_RED)
{
pNode->m_pParent->m_eColor = NC_BLACK;
break;
}
pNode = pNode->m_pParent;
continue;
}
else if (pSibling->m_pRight->m_eColor == NC_RED)
{
if (pSibling != Nil)
pSibling->m_eColor = NC_RED;
pSibling->m_pRight->m_eColor = NC_BLACK;
RotationLeft(pSibling);
}
else if (pSibling->m_pLeft->m_eColor == NC_RED)
{
if (pSibling != Nil)
pSibling->m_eColor = pNode->m_pParent->m_eColor;
pNode->m_pParent->m_eColor = NC_BLACK;
pSibling->m_pLeft->m_eColor = NC_BLACK;
RotationRight(pNode->m_pParent);
}
break;
}
}
}
public:
static Pair make_pair(const Key& key, const Value& value)
{
Pair pair;
pair.first = key;
pair.second = value;
return pair;
}
};