二叉搜索平衡樹/紅黑樹
總覽
開發過程,經常需要對數據集合進行維護。
維護數據集合的數據結構可統稱爲容器。
樹形結構是集合容器的一種,
二叉搜索平衡樹,又名紅黑樹。
首先是一顆二叉搜索樹,
其具備以下性質:
對任意節點t,Key[t]表示節點內元素的鍵值。
對於樹中任意節點p,
若其左孩子存在,設爲l,則有Key[l] < Key[p]
若其右孩子存在,設爲r,則有Key[r] > Key[p]
其次,通過對樹設置以下約束,來讓樹成爲一顆平衡的二叉樹,
具體的約束爲:
1. 任意節點,具備紅色或黑色二選一的顏色標記
2. 根節點顏色固定爲黑色
3. 若父節點爲紅色,則其子節點必須爲黑色
4. 對於任意節點,其左右子樹的黑高一致
對於一顆二叉搜索平衡,樹的高度不超過k * lg(n)。
在此基礎上,
可以在集合的插入,刪除,查找 三個方面,
均達到O(lg(n))的時間複雜度。
紅黑樹是使用最廣泛的一種數據結構,具有非常大的實際應用價值。
接口設計
template<typename Key, typename Value>
class SortedBalanceBinaryTree
{
public:
enum Color
{
BLACK = 1,
RED,
BLACKBLACK,
};
class Pair
{
public:
Pair()
{
}
Pair(const Key& key_, const Value& value_)
{
m_nKey = key_;
m_nValue = value_;
}
~Pair()
{
}
public:
Key m_nKey;
Value m_nValue;
};
class Node
{
public:
Pair GetPair()
{
return m_nPair;
}
private:
Node()
{
m_pParent = nullptr;
m_pLeftChild = nullptr;
m_pRightChild = nullptr;
m_nColor = Color::RED;
}
Node(const Pair& nPair_)
{
m_nPair = nPair_;
m_pParent = nullptr;
m_pLeftChild = nullptr;
m_pRightChild = nullptr;
m_nColor = Color::RED;
}
~Node()
{
}
private:
Node* m_pParent;
Node* m_pLeftChild;
Node* m_pRightChild;
Pair m_nPair;
Color m_nColor;
friend class SortedBalanceBinaryTree;
};
SortedBalanceBinaryTree();
~SortedBalanceBinaryTree();
SortedBalanceBinaryTree(const SortedBalanceBinaryTree& minTree_);
SortedBalanceBinaryTree& operator=(const SortedBalanceBinaryTree& minTree_);
void PreVisit(std::function<void(Node*)> travelFunction_, Node* pRoot_ = nullptr) const;
void PostVisit(std::function<void(Node*)> travelFunction_, Node* pRoot_ = nullptr) const;
void Visit(std::function<void(Node*)> travelFunction_, Node* pRoot_ = nullptr) const;
Node* Min(Node* pRoot_ = nullptr) const;
Node* Max(Node* pRoot_ = nullptr) const;
Node* Pre(Node *pNode_) const;
Node* Suc(Node *pNode_) const;
bool Search(const Key& key_, Value& value_, Node* pRoot_ = nullptr) const;
Node* Search(const Key& key_, Node* pRoot_ = nullptr) const;
bool Add(const Pair& nPair_);
void Delete(const Key& key_, Node* pRoot_ = nullptr);
void DeleteAll();
Node* GetRoot() const;
Array::DynArray<Pair> GetArray() const
{
Array::DynArray<Pair> _arrContain;
PreVisit([&_arrContain](Node* pNode_)
{
_arrContain.Add(pNode_->m_nPair);
});
return _arrContain;
}
private:
void Delete(Node* pNode_);
bool AdjustForParentColor(Node *pAdjustedNode_);
Node* LeftRotate(Node *pNode_);
Node* RightRotate(Node *pNode_);
void AdjustForBlackBlack(Node *pBlackBlackNode_);
void AdjustForBlackHeight(Node *pNode_);
bool CheckValid() const;
int GetBlackHeight(Node *pNode_) const;
private:
Node* m_pRoot;
};
實現
添加
template<typename Key, typename Value>
bool SortedBalanceBinaryTree<Key, Value>::Add(const Pair& nPair_)
{
Node *_pNewNode = nullptr;
try
{
_pNewNode = new Node();
}
catch (...)
{
_pNewNode = nullptr;
throw "out of memory";
}
_pNewNode->m_nPair = nPair_;
if (m_pRoot == nullptr)
{
m_pRoot = _pNewNode;
m_pRoot->m_nColor = Color::BLACK;
return true;
}
Node* _pNode = m_pRoot;
while (true)
{
if (_pNode->m_nPair.m_nKey > _pNewNode->m_nPair.m_nKey)
{
if (_pNode->m_pLeftChild == nullptr)
{
_pNode->m_pLeftChild = _pNewNode;
_pNewNode->m_pParent = _pNode;
break;
}
else
{
_pNode = _pNode->m_pLeftChild;
}
}
else if (_pNode->m_nPair.m_nKey < _pNewNode->m_nPair.m_nKey)
{
if (_pNode->m_pRightChild == nullptr)
{
_pNode->m_pRightChild = _pNewNode;
_pNewNode->m_pParent = _pNode;
break;
}
else
{
_pNode = _pNode->m_pRightChild;
}
}
else
{
if (_pNewNode)
{
delete _pNewNode;
_pNewNode = nullptr;
}
return false;
}
}
if (_pNewNode->m_pParent->m_nColor == Color::RED)
{
AdjustForParentColor(_pNewNode);
}
return true;
}
刪除
template<typename Key, typename Value>
void SortedBalanceBinaryTree<Key, Value>::Delete(
const Key& key_,
Node* pRoot_)
{
Node *_pRoot = nullptr;
if (pRoot_ == nullptr)
{
_pRoot = m_pRoot;
}
else
{
_pRoot = pRoot_;
}
if (_pRoot == nullptr)
{
return;
}
Node* _pNode = Search(key_, _pRoot);
if (_pNode == nullptr)
{
return;
}
Delete(_pNode);
}
template<typename Key, typename Value>
void SortedBalanceBinaryTree<Key, Value>::Delete(Node* pNode_)
{
Node* _pNode = pNode_;
if(_pNode == nullptr)
{
throw "input error";
}
if (_pNode->m_pLeftChild == nullptr
&& _pNode->m_pRightChild == nullptr)
{
if (_pNode->m_pParent == nullptr)
{
delete _pNode;
_pNode = nullptr;
m_pRoot = nullptr;
return;
}
if (_pNode->m_pParent->m_pLeftChild == _pNode)
{
_pNode->m_pParent->m_pLeftChild = nullptr;
bool _bNeedAdjust = _pNode->m_nColor == Color::BLACK;
Node* _pParent = _pNode->m_pParent;
delete _pNode;
_pNode = nullptr;
if (_bNeedAdjust)
{
AdjustForBlackHeight(_pParent);
}
return;
}
else
{
_pNode->m_pParent->m_pRightChild = nullptr;
bool _bNeedAdjust = _pNode->m_nColor == Color::BLACK;
Node* _pParent = _pNode->m_pParent;
delete _pNode;
_pNode = nullptr;
if (_bNeedAdjust)
{
AdjustForBlackHeight(_pParent);
}
return;
}
}
else if (_pNode->m_pLeftChild != nullptr
&& _pNode->m_pRightChild == nullptr)
{
Node *_pMovingNode = Max(_pNode->m_pLeftChild);
_pNode->m_nPair = _pMovingNode->m_nPair;
Delete(_pMovingNode);
}
else if (_pNode->m_pLeftChild == nullptr
&& _pNode->m_pRightChild != nullptr)
{
Node *_pMovingNode = Min(_pNode->m_pRightChild);
_pNode->m_nPair = _pMovingNode->m_nPair;
Delete(_pMovingNode);
}
else
{
Node *_pMovingNode = Max(_pNode->m_pLeftChild);
_pNode->m_nPair = _pMovingNode->m_nPair;
Delete(_pMovingNode);
}
return;
}
平衡調節
LeftRotate
template<typename Key, typename Value>
typename SortedBalanceBinaryTree<Key, Value>::Node* SortedBalanceBinaryTree<Key, Value>::LeftRotate(
Node *pNode_)
{
Node *_pRight = pNode_->m_pRightChild;
if (_pRight == nullptr)
{
return pNode_;
}
Node *_pLeft = pNode_->m_pLeftChild;
Node *_pRightLeft = _pRight->m_pLeftChild;
Node *_pRightRight = _pRight->m_pRightChild;
Node *_pParent = pNode_->m_pParent;
if (_pParent == nullptr)
{
m_pRoot = _pRight;
}
else if (_pParent->m_pLeftChild == pNode_)
{
_pParent->m_pLeftChild = _pRight;
}
else
{
_pParent->m_pRightChild = _pRight;
}
_pRight->m_pParent = _pParent;
_pRight->m_pLeftChild = pNode_;
_pRight->m_pRightChild = _pRightRight;
pNode_->m_pParent = _pRight;
pNode_->m_pLeftChild = _pLeft;
pNode_->m_pRightChild = _pRightLeft;
if (_pRightLeft != nullptr)
{
_pRightLeft->m_pParent = pNode_;
}
return _pRight;
}
RightRotate
template<typename Key, typename Value>
typename SortedBalanceBinaryTree<Key, Value>::Node * SortedBalanceBinaryTree<Key, Value>::RightRotate(
Node *pNode_)
{
Node *_pLeft = pNode_->m_pLeftChild;
if (_pLeft == nullptr)
{
return pNode_;
}
Node *_pRight = pNode_->m_pRightChild;
Node *_pLeftLeft = _pLeft->m_pLeftChild;
Node *_pLeftRight = _pLeft->m_pRightChild;
Node *_pParent = pNode_->m_pParent;
if (_pParent == nullptr)
{
m_pRoot = _pLeft;
}
else if (_pParent->m_pLeftChild == pNode_)
{
_pParent->m_pLeftChild = _pLeft;
}
else
{
_pParent->m_pRightChild = _pLeft;
}
_pLeft->m_pParent = _pParent;
_pLeft->m_pLeftChild = _pLeftLeft;
_pLeft->m_pRightChild = pNode_;
pNode_->m_pParent = _pLeft;
pNode_->m_pLeftChild = _pLeftRight;
pNode_->m_pRightChild = _pRight;
if (_pLeftRight != nullptr)
{
_pLeftRight->m_pParent = pNode_;
}
return _pLeft;
}
AdjustForParentColor
template<typename Key, typename Value>
bool SortedBalanceBinaryTree<Key, Value>::AdjustForParentColor(
Node *pNode_)
{
if(pNode_ == nullptr
|| pNode_->m_nColor != Color::RED
|| pNode_->m_pParent == nullptr
|| pNode_->m_pParent->m_nColor != Color::RED)
{
throw "input error";
}
Node *_pNode = pNode_;
Node *_pParent = nullptr;
Node *_pGrandFather = nullptr;
Color _nColor = Color::RED;
while (true)
{
if (_pNode != nullptr)
{
_pParent = _pNode->m_pParent;
}
if (_pParent != nullptr)
{
_pGrandFather = _pParent->m_pParent;
}
if (_pNode == nullptr
|| _pParent == nullptr
|| _pParent->m_nColor == Color::BLACK
|| _pGrandFather == nullptr)
{
break;
}
if (_pNode == _pParent->m_pLeftChild
&& _pParent == _pGrandFather->m_pLeftChild)
{
_pNode = RightRotate(_pGrandFather);
_pNode->m_pLeftChild->m_nColor = (Color::BLACK);
}
else if (_pNode == _pParent->m_pLeftChild
&& _pParent == _pGrandFather->m_pRightChild
&& _pGrandFather->m_pLeftChild == nullptr)
{
_pGrandFather = LeftRotate(_pGrandFather);
LeftRotate(_pGrandFather->m_pLeftChild);
_pGrandFather = RightRotate(_pGrandFather);
_pGrandFather->m_nColor = Color::BLACK;
_pGrandFather->m_pLeftChild->m_nColor = Color::RED;
break;
}
else if (_pNode == _pParent->m_pLeftChild
&& _pParent == _pGrandFather->m_pRightChild
&& _pGrandFather->m_pLeftChild)
{
RightRotate(_pParent);
_pNode = LeftRotate(_pGrandFather);
_pNode->m_pRightChild->m_nColor = (Color::BLACK);
}
else if (_pNode == _pParent->m_pRightChild
&& _pParent == _pGrandFather->m_pLeftChild
&& _pGrandFather->m_pRightChild == nullptr)
{
LeftRotate(_pParent);
_pNode = RightRotate(_pGrandFather);
_pNode->m_nColor = Color::BLACK;
_pNode->m_pRightChild->m_nColor = Color::RED;
break;
}
else if (_pNode == _pParent->m_pRightChild
&& _pParent == _pGrandFather->m_pLeftChild
&& _pGrandFather->m_pRightChild)
{
LeftRotate(_pParent);
_pNode = RightRotate(_pGrandFather);
_pNode->m_pLeftChild->m_nColor = (Color::BLACK);
}
else if (_pNode == _pParent->m_pRightChild
&& _pGrandFather->m_pRightChild == _pParent)
{
_pNode = LeftRotate(_pGrandFather);
_pNode->m_pRightChild->m_nColor = (Color::BLACK);
}
else
{
assert(false);
}
}
m_pRoot->m_nColor = Color::BLACK;
return true;
}
AdjustForBlackHeight
template<typename Key, typename Value>
void SortedBalanceBinaryTree<Key, Value>::AdjustForBlackHeight(
Node *pNode_)
{
if (pNode_ == nullptr)
{
assert(false);
return;
}
if (pNode_->m_pLeftChild == nullptr
&& pNode_->m_pRightChild != nullptr)
{
if (pNode_->m_nColor == Color::RED)
{
Node *_pTemp = LeftRotate(pNode_);
if (_pTemp->m_pLeftChild->m_pRightChild != nullptr)
{
AdjustForParentColor(_pTemp->m_pLeftChild->m_pRightChild);
}
assert(CheckValid());
}
else if (pNode_->m_nColor == Color::BLACK)
{
if (pNode_->m_pRightChild->m_nColor == Color::RED)
{
Node *_pTemp = LeftRotate(pNode_);
LeftRotate(_pTemp->m_pLeftChild);
_pTemp->m_nColor = Color::BLACK;
_pTemp->m_pLeftChild->m_pLeftChild->m_nColor = Color::RED;
if (_pTemp->m_pLeftChild->m_pLeftChild->m_pRightChild != nullptr)
{
assert(_pTemp->m_pLeftChild->m_pLeftChild->m_pRightChild->m_nColor == Color::RED);
AdjustForParentColor(_pTemp->m_pLeftChild->m_pLeftChild->m_pRightChild);
assert(CheckValid());
}
else
{
assert(CheckValid());
}
}
else if (pNode_->m_pRightChild->m_nColor == Color::BLACK)
{
Node *_pTemp = LeftRotate(pNode_);
if (_pTemp->m_pRightChild != nullptr)
{
assert(_pTemp->m_pRightChild->m_nColor == Color::RED);
_pTemp->m_pRightChild->m_nColor = Color::BLACK;
assert(CheckValid());
}
else
{
if (_pTemp->m_pLeftChild->m_pRightChild != nullptr)
{
assert(_pTemp->m_pLeftChild->m_pRightChild->m_nColor == Color::RED);
LeftRotate(_pTemp->m_pLeftChild);
_pTemp = RightRotate(_pTemp);
_pTemp->m_nColor = Color::BLACK;
assert(_pTemp->m_pLeftChild->m_nColor == Color::BLACK);
assert(_pTemp->m_pRightChild->m_nColor == Color::BLACK);
assert(CheckValid());
}
else
{
_pTemp->m_pLeftChild->m_nColor = Color::RED;
_pTemp->m_nColor = Color::BLACKBLACK;
AdjustForBlackBlack(_pTemp);
assert(CheckValid());
}
}
}
else
{
assert(false);
throw "The right child of the adjust node not has a right color";
}
}
else
{
assert(false);
throw "The adjust node not has a right color";
}
}
else if (pNode_->m_pLeftChild != nullptr
&& pNode_->m_pRightChild == nullptr)
{
if (pNode_->m_nColor == Color::RED)
{
Node *_pTemp = RightRotate(pNode_);
if (_pTemp->m_pRightChild->m_pLeftChild != nullptr)
{
AdjustForParentColor(_pTemp->m_pRightChild->m_pLeftChild);
}
assert(CheckValid());
}
else if (pNode_->m_nColor == Color::BLACK)
{
if (pNode_->m_pLeftChild->m_nColor == Color::RED)
{
Node *_pTemp = RightRotate(pNode_);
RightRotate(_pTemp->m_pRightChild);
_pTemp->m_nColor = Color::BLACK;
_pTemp->m_pRightChild->m_pRightChild->m_nColor = Color::RED;
if (_pTemp->m_pRightChild->m_pRightChild->m_pLeftChild != nullptr)
{
AdjustForParentColor(_pTemp->m_pRightChild->m_pRightChild->m_pLeftChild);
assert(CheckValid());
}
else
{
assert(CheckValid());
}
}
else if (pNode_->m_pLeftChild->m_nColor == Color::BLACK)
{
Node *_pTemp = RightRotate(pNode_);
if (_pTemp->m_pLeftChild)
{
assert(_pTemp->m_pLeftChild->m_nColor == Color::RED);
_pTemp->m_pLeftChild->m_nColor = Color::BLACK;
assert(CheckValid());
}
else
{
if (_pTemp->m_pRightChild->m_pLeftChild)
{
assert(_pTemp->m_pRightChild->m_pLeftChild->m_nColor == Color::RED);
RightRotate(_pTemp->m_pRightChild);
_pTemp = LeftRotate(_pTemp);
_pTemp->m_nColor = Color::BLACK;
assert(_pTemp->m_pLeftChild->m_nColor == Color::BLACK);
assert(_pTemp->m_pRightChild->m_nColor == Color::BLACK);
assert(CheckValid());
}
else
{
_pTemp->m_pRightChild->m_nColor = Color::RED;
_pTemp->m_nColor = Color::BLACKBLACK;
AdjustForBlackBlack(_pTemp);
assert(CheckValid());
}
}
}
else
{
assert(false);
throw "The left child of the adjust node not has a right color";
}
}
else
{
assert(false);
throw "The adjust node not has a right color";
}
}
else
{
assert(false);
throw "The adjust node has no child";
}
assert(CheckValid());
}
AdjustForBlackBlack
template<typename Key, typename Value>
void SortedBalanceBinaryTree<Key, Value>::AdjustForBlackBlack(
Node *pNode_)
{
assert(pNode_
&& pNode_->m_nColor == Color::BLACKBLACK);
Node *_pParent = nullptr;
bool _bFirst = true;
while (true)
{
if (pNode_)
{
_pParent = pNode_->m_pParent;
}
if (pNode_ == nullptr
|| _pParent == nullptr
|| pNode_->m_nColor != Color::BLACKBLACK)
{
break;
}
if (pNode_ == _pParent->m_pLeftChild
&& _pParent->m_nColor == Color::BLACK
&& _pParent->m_pRightChild->m_nColor == Color::BLACK)
{
if (_pParent->m_pRightChild->m_pLeftChild->m_nColor == Color::BLACK)
{
_pParent = LeftRotate(_pParent);
_pParent->m_nColor = Color::BLACKBLACK;
_pParent->m_pLeftChild->m_pLeftChild->m_nColor = Color::BLACK;
_pParent->m_pLeftChild->m_nColor = Color::RED;
pNode_ = _pParent;
}
else if (_pParent->m_pRightChild->m_pLeftChild->m_nColor == Color::RED
&& _pParent->m_pRightChild->m_pRightChild->m_nColor == Color::RED)
{
_pParent = LeftRotate(_pParent);
LeftRotate(_pParent->m_pLeftChild);
_pParent->m_pLeftChild->m_pLeftChild->m_pLeftChild->m_nColor = Color::BLACK;
_pParent->m_pLeftChild->m_pLeftChild->m_nColor = Color::RED;
_pParent->m_pLeftChild->m_nColor = Color::BLACK;
_pParent->m_pRightChild->m_nColor = Color::BLACK;
break;
}
else if (_pParent->m_pRightChild->m_pLeftChild->m_nColor == Color::RED
&& _pParent->m_pRightChild->m_pRightChild->m_nColor == Color::BLACK)
{
RightRotate(_pParent->m_pRightChild);
_pParent = LeftRotate(_pParent);
_pParent->m_pLeftChild->m_pLeftChild->m_nColor = Color::BLACK;
_pParent->m_nColor = Color::BLACK;
break;
}
else
{
assert(false);
throw "unexpected action";
}
}
else if (pNode_ == _pParent->m_pLeftChild
&& _pParent->m_nColor == Color::BLACK
&& _pParent->m_pRightChild->m_nColor == Color::RED)
{
if (_pParent->m_pRightChild->m_pLeftChild->m_pLeftChild->m_nColor == Color::BLACK)
{
_pParent = LeftRotate(_pParent);
_pParent->m_nColor = Color::BLACK;
LeftRotate(_pParent->m_pLeftChild);
_pParent->m_pLeftChild->m_pLeftChild->m_pLeftChild->m_nColor = Color::BLACK;
_pParent->m_pLeftChild->m_pLeftChild->m_nColor = Color::RED;
break;
}
else
{
_pParent = LeftRotate(_pParent);
RightRotate(_pParent->m_pLeftChild->m_pRightChild);
LeftRotate(_pParent->m_pLeftChild);
_pParent->m_nColor = Color::BLACK;
_pParent->m_pLeftChild->m_pLeftChild->m_pLeftChild->m_nColor = Color::BLACK;
break;
}
}
else if (pNode_ == _pParent->m_pLeftChild
&& _pParent->m_nColor == Color::RED)
{
_pParent = LeftRotate(_pParent);
_pParent->m_nColor = Color::BLACK;
_pParent->m_pLeftChild->m_nColor = Color::RED;
_pParent->m_pLeftChild->m_pLeftChild->m_nColor = Color::BLACK;
if (_pParent->m_pLeftChild->m_pRightChild->m_nColor == Color::RED)
{
AdjustForParentColor(_pParent->m_pLeftChild->m_pRightChild);
}
break;
}
else if (pNode_ == _pParent->m_pRightChild
&& _pParent->m_nColor == Color::BLACK
&& _pParent->m_pLeftChild->m_nColor == Color::BLACK)
{
if (_pParent->m_pLeftChild->m_pRightChild->m_nColor == Color::BLACK)
{
_pParent = RightRotate(_pParent);
_pParent->m_pRightChild->m_pRightChild->m_nColor = Color::BLACK;
_pParent->m_pRightChild->m_nColor = Color::RED;
_pParent->m_nColor = Color::BLACKBLACK;
pNode_ = _pParent;
}
else if (_pParent->m_pLeftChild->m_pRightChild->m_nColor == Color::RED)
{
LeftRotate(_pParent->m_pLeftChild);
_pParent = RightRotate(_pParent);
_pParent->m_nColor = Color::BLACK;
_pParent->m_pRightChild->m_pRightChild->m_nColor = Color::BLACK;
break;
}
else
{
assert(false);
throw "unexpected situation";
}
}
else if (pNode_ == _pParent->m_pRightChild
&& _pParent->m_nColor == Color::BLACK
&& _pParent->m_pLeftChild->m_nColor == Color::RED)
{
if (_pParent->m_pLeftChild->m_pRightChild->m_pRightChild->m_nColor == Color::BLACK)
{
_pParent = RightRotate(_pParent);
RightRotate(_pParent->m_pRightChild);
_pParent->m_pRightChild->m_pRightChild->m_pRightChild->m_nColor = Color::BLACK;
_pParent->m_pRightChild->m_pRightChild->m_nColor = Color::RED;
_pParent->m_nColor = Color::BLACK;
break;
}
else
{
_pParent = RightRotate(_pParent);
LeftRotate(_pParent->m_pRightChild->m_pLeftChild);
RightRotate(_pParent->m_pRightChild);
_pParent->m_nColor = Color::BLACK;
_pParent->m_pRightChild->m_pRightChild->m_pRightChild->m_nColor = Color::BLACK;
break;
}
}
else if (pNode_ == _pParent->m_pRightChild
&& _pParent->m_nColor == Color::RED)
{
_pParent = RightRotate(_pParent);
_pParent->m_pRightChild->m_pRightChild->m_nColor = Color::BLACK;
if (_pParent->m_pRightChild->m_pLeftChild->m_nColor == Color::RED)
{
AdjustForParentColor(_pParent->m_pRightChild->m_pLeftChild);
}
break;
}
else
{
assert(false);
throw "unexpected situation";
}
}
m_pRoot->m_nColor = Color::BLACK;
assert(CheckValid());
}
正確性證明
證明紅黑樹的高度不會超出k*lg(n)
設根節點左子樹黑高爲lbh,
則左子樹節點個數 >= 2^0 + 2^1 + ... + 2^(lbh-1) = 2^(lbh) - 1
對右子樹同理。
設樹的節點樹爲n
n = 左子樹節點總數 + 右子樹節點總數 + 1
n >= 2^(lbh+1) - 1
設樹的黑高爲h,有h=lbh+1
h <= lg(n+1)
設左子樹實際高度爲lh,右子樹實際高度爲rh,
有lh <= 2*lbh
設二叉樹實際高度爲:
th = max(lh, rh) + 1
th <= 2lg(n+1) + 1
得證。
證明添加算法正確性
添加算法分兩部分。
一部分爲尋找插入位置,並執行元素插入。
此部分正確性在二叉搜索樹中已經證明。
新插入節點默認顏色爲紅色。
如果父親節點也爲紅色。
此時不滿足,父紅則子黑的性質。
而紅黑樹的其他性質均滿足。
此時,執行AdjustForParentColor,完成平衡調節
AdjustForParentColor
算法輸入:
pNode_指向紅色節點,其父親節點顏色也爲紅。
算法前提:
pNode_所在紅黑樹,
除了pNode_及其父節點不滿足父紅則子黑性質,
其他性質均滿足。
算法目標:
對紅黑樹進行調節,使紅黑樹所有性質均滿足。
算法採用while循環實現,利用循環不變式證明正確性。
循環不變式:
_pNode存在且顏色爲紅色,
其父親節點存在且顏色爲紅色,
其祖父節點存在。
_pNode所在紅黑樹,
除了_pNode及其父節點不滿足父紅則子黑性質,
其他性質均滿足。
證明:
初始時,循環不變式成立。
第k次迭代時,
依據循環不變式,
第1,...,k-1次迭代後,循環不變式依然成立。
1. 若
_pNode是父親左孩子,
且父親是祖父左孩子,
執行
_pNode=基於祖父的右旋,
設置_pNode左孩子顏色爲黑色。
這樣操作後,
_pNode節點爲紅色
只有
_pNode父節點存在且爲紅色,
_pNode祖父節點存在
同時滿足時,
再次進入下次循環,此時循環不變式滿足。
若上述不同時滿足,
我們只需跳出循環,
並設置根節點爲黑色,即可讓紅黑樹所有性質均滿足。
2. 若
_pNode是父親左孩子,
且父親是祖父右孩子,
且祖父左孩子不存在
易於證明,
通過算法中旋轉和顏色賦值操作,
可使紅黑樹所有性質均得到滿足。
此時跳出循環。
3. 若
_pNode是父親左孩子,
且父親是祖父右孩子,
且祖父左孩子存在。
易於證明,
通過算法中旋轉和顏色賦值操作,
這樣操作後,
_pNode節點爲紅色
只有
_pNode父節點存在且爲紅色,
_pNode祖父節點存在
同時滿足時,
再次進入下次循環,
此時循環不變式滿足,但_pNode指向更高位置的節點。
若上述不同時滿足,
我們只需跳出循環,
並設置根節點爲黑色,即可讓紅黑樹所有性質均滿足。
4. 若
_pNode是其父親右孩子,
其父親是其祖父左孩子,
祖父右孩子不存在,
則易於證明,
按算法中旋轉和顏色賦值處理後,
可以使紅黑樹所有性質均滿足,跳出循環。
5. 若
_pNode是父親右孩子,
且父親是祖父左孩子,
且祖父右孩子存在,
則易於證明,
按算法中旋轉和顏色賦值處理後,
只有
_pNode父節點存在且爲紅色,
_pNode祖父節點存在
同時滿足時,
再次進入下次循環,
此時循環不變式滿足,但_pNode指向更高位置的節點。
若上述不同時滿足,
我們只需跳出循環,
並設置根節點爲黑色,即可讓紅黑樹所有性質均滿足。
6. 若
_pNode是其父親右孩子,
且其父親是其祖父右孩子,
則易於證明,
按算法中旋轉和顏色賦值處理後,
只有
_pNode父節點存在且爲紅色,
_pNode祖父節點存在
同時滿足時,
再次進入下次循環,
此時循環不變式滿足,但_pNode指向更高位置的節點。
若上述不同時滿足,
我們只需跳出循環,
並設置根節點爲黑色,即可讓紅黑樹所有性質均滿足。
每次循環,必然處於6種情形之一,
綜合,第k次循環迭代中,
要麼直接得到結果。
要麼維持循環不變式且節點上移。
因爲樹的高度是有限的,故,即使在最壞情況下,
上述迭代也會在有限次上移後,達到終止條件。
算法正確性得證。
上述分析過程,
由於確立插入位置是從樹根向下的尋找過程,
顏色調節是從低向上的旋轉調節過程。
可知,時間複雜度爲Θ(lg(n))
證明刪除算法正確性
尋找刪除元素並刪除正確性,
參考二叉搜索樹的分析。
區別於二叉搜索樹的是,
若
最終刪除節點爲黑色,
且節點父節點存在,
則需要執行AdjustForBlackHeight對紅黑樹進行調節,
來使樹滿足紅黑樹的性質。
AdjustForBlackHeight
算法輸入:
pNode_
算法前提:
pNode_一個子樹爲空子樹,
另一個子樹爲黑高爲1的子樹。
pNode_所代表的紅黑樹中,
除了pNode_左右子樹黑高不一樣外,
其餘紅黑樹的性質均滿足。
算法目標:
通過旋轉調節和顏色賦值使,紅黑樹所有性質均滿足。
依據算法內容,採用直接證明法。
1. 若
pNode_左孩子爲空,右孩子存在
1.1. 若pNode_顏色爲紅色
易於知道,在AdjustForParentColor正確下,
調節後,紅黑樹性質均滿足。
AdjustForParentColor最壞下時間複雜度爲O(lg(n))
1.2. 若pNode_顏色爲黑色
1.2.1. 若pNode_右孩子爲紅色
此時執行算法的旋轉和顏色賦值後,
如指定孩子不存在,則調節結束。所有性質均已滿足。
如指定孩子存在,
在AdjustForParentColor正確下,
調節後,紅黑樹性質均滿足。
此情形下,最壞情況下時間複雜度爲O(lg(n))
1.2.2. 若pNode_右孩子爲黑色
易於證明,算法處理中,
某些情形下,可以直接完成性質調整。
特別注意一類情形下,
將_pTemp顏色設置爲黑黑,令該節點黑高爲2.
此時,紅黑樹所有性質均滿足,
只有_pTemp節點顏色須爲紅色或黑色,不滿足。
執行AdjustForBlackBlack,針對這種情況進行調節。
若AdjustForBlackBlack正確下,
綜合可知,此時算法正確。
1.2.3. 若pNode_右孩子顏色既不是紅色又不是黑色,
報錯,返回。
1.3. 若pNode_顏色不爲黑色也不爲紅色
報錯,返回。
2. 若
pNode_左孩子存在,pNode_右孩子爲空
可按1中類似分析和證明
3. 若
pNode_左右孩子均存在或均不存在,
報錯,返回。
AdjustForBlackBlack
算法輸入:
pNode_
算法前提:
pNode_指向節點顏色爲黑黑。
除了pNode_節點顏色不滿足紅黑樹限制外,
紅黑樹的其餘性質對於任意節點均滿足。
算法目標:
通過執行節點旋轉和顏色賦值,
來使紅黑樹的性質全部被滿足。
算法通過while循環實現,採用循環不變式來證明。
循環不變式:
pNode_指向節點顏色爲黑黑。
除了pNode_節點顏色不滿足紅黑樹限制外,
紅黑樹的其餘性質對於任意節點均滿足。
證明:
初始時,循環不變式滿足。
對第k次迭代,
依據循環不變式性質,
第1,...,k-1次迭代後,
循環不變式仍然滿足。
如果節點父親不存在,
則節點爲根節點,
此時跳出循環,
並設置其顏色爲黑色可以完成調節。
1. 若
pNode_爲其父親左孩子
且其父親顏色爲黑色
且其父親右孩子顏色爲黑色
1.1. 其父親右孩子的左孩子顏色爲黑色
經過算法中旋轉和顏色賦值處理,
使處理後,循環不變式仍然滿足。
但pNode_指向了更高層的節點。
1.2. 其父親右孩子的左孩子顏色爲紅色,且其父親右孩子的右孩子顏色爲紅色
經過算法中旋轉和顏色賦值處理後,
可以立即完成調節。算法終止。
1.3. 其父親右孩子的左孩子顏色爲紅色,且其父親右孩子的右孩子顏色爲黑色
經過算法中旋轉和顏色賦值處理後,
可以立即完成調節。算法終止。
1.4. 其他
報異常,終止。
2. 若
pNode_爲其父親左孩子,
且其父親顏色爲黑色,
且其父親右孩子顏色爲紅色
2.1. 其父親右孩子的左孩子的左孩子顏色爲黑色
經過算法中旋轉和顏色賦值處理後,
可以立即完成調節。算法終止。
2.2. 其父親右孩子的左孩子的左孩子顏色爲紅色
經過算法中旋轉和顏色賦值處理後,
可以立即完成調節。算法終止。
3. 若
pNode_爲取父親左孩子,
且其父親顏色爲紅色
經過算法中旋轉和顏色賦值處理後,
要麼轉化爲 只有父紅子紅這一性質不滿足,
要麼直接得到結果。
AdjustForParentColor正確性之前已經證明。
故此類情形下,可以完成紅黑樹性質的調整。
4. 若
pNode_爲其父親右孩子,
且其父親顏色爲黑色,
其父親左孩子顏色爲黑色
4.1. 若其父親左孩子的右孩子顏色爲黑色
經過算法中旋轉和顏色賦值處理,
使處理後,循環不變式仍然滿足。
但pNode_指向了更高層的節點。
4.2.若其父親左孩子的右孩子顏色爲紅色
經過算法中旋轉和顏色賦值處理後,
可以立即完成調節。算法終止。
4.3.其他
異常,終止
5. 若
pNode_爲其父親右孩子,
其父親顏色爲黑色,
其父親左孩子顏色爲紅色
5.1. 若 其父親左孩子的右孩子的右孩子顏色爲黑色
經過算法中旋轉和顏色賦值處理後,
可以立即完成調節。算法終止。
5.2. 若 其父親左孩子的右孩子的右孩子顏色爲紅色
經過算法中旋轉和顏色賦值處理後,
可以立即完成調節。算法終止。
5.3. 其他
異常,終止。
6. 若
pNode_爲其父親右孩子,
且其父親顏色爲紅色
經過算法中旋轉和顏色賦值處理後,
要麼轉化爲 只有父紅子紅這一性質不滿足,
要麼直接得到結果。
AdjustForParentColor正確性之前已經證明。
故此類情形下,可以完成紅黑樹性質的調整。
7. 其他
異常,終止
綜合,第k次循環迭代後,
要麼立即完成調整。
要麼轉換爲求解另一問題。
要麼維持循環不變式。
且,循環不變式維持下,節點會不斷上升。
因爲樹的高度是有限的,
故最壞情況下,也能在有限次迭代後,得到結果。
算法成立。
時間複雜度
添加算法時間複雜度
時間複雜度爲Θ(lg(n))
刪除算法時間複雜度
算法分爲兩個部分,
找到最終要刪除元素是一部分。
對刪除節點後的樹進行調節是另一部分。
第一部分是下降的過程,第二部分是上升的過程。
因爲樹的高度不會超出k*lg(n),故即使在最壞下刪除算法的時間複雜度爲O(lg(n))