數據結構--紅黑樹簡化版

二叉搜索平衡樹/紅黑樹

總覽

開發過程,經常需要對數據集合進行維護。
維護數據集合的數據結構可統稱爲容器。
樹形結構是集合容器的一種,
二叉搜索平衡樹,又名紅黑樹。
首先是一顆二叉搜索樹,
其具備以下性質:
對任意節點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))
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章