红黑树的C++实现(2)

        因为红黑树首先是二叉所搜树,所以有了二叉搜索树的实现,我们就可以重用部分二叉搜索树的类的接口了,rbt.h:

#ifndef __RBT_H__
#define __RBT_H__
#include "bst.h"

template <typename T>
class CRedBlackTree : public CBinarySortTree<T>
{
	public:
		CRedBlackTree();
		~CRedBlackTree() {}

		virtual CBinaryTreeNode<T>* Insert(const T& key);
		virtual void Delete(CBinaryTreeNode<T>** del);
		virtual void InorderWalk() const;

	private:
		void InsertFixup(CBinaryTreeNode<T>* node);
		void DeleteFixup(CBinaryTreeNode<T>* node);

		void LeftRotate(CBinaryTreeNode<T>* node);
		void RightRotate(CBinaryTreeNode<T>* node);

		void InorderWalk(const CBinaryTreeNode<T>* node) const;
};

template <typename T>
CRedBlackTree<T>::CRedBlackTree() : CBinarySortTree<T>()
{

}

template <typename T>
CBinaryTreeNode<T>* CRedBlackTree<T>::Insert(const T& key)
{
	CBinaryTreeNode<T>* add = CBinarySortTree<T>::Insert(key);

	InsertFixup(add);
	return add;
}

template <typename T>
void CRedBlackTree<T>::Delete(CBinaryTreeNode<T>** del)
{
	CBinaryTreeNode<T>* temp = &CBinarySortTree<T>::sentinel;
	CBinaryTreeNode<T>* node = *del;
	CBinaryTreeNode<T>* fixup = &CBinarySortTree<T>::sentinel;
	enum CBinaryTreeNode<T>::eColor original_color = (*del)->color;

	if (node->left == &CBinarySortTree<T>::sentinel && node->right == &CBinarySortTree<T>::sentinel) {
		CBinaryTreeNode<T>* parent = node->parent;

		if (parent != &CBinarySortTree<T>::sentinel) {
			if (parent->left == node) {
				parent->left = &CBinarySortTree<T>::sentinel;
				fixup = parent->left;
			} else {
				parent->right = &CBinarySortTree<T>::sentinel;
				fixup = parent->right;
			}

			fixup->parent = parent; // 'cause sentinel's parent points to itself
		} else {
			*del = &CBinarySortTree<T>::sentinel;
			this->root = &CBinarySortTree<T>::sentinel;
		}

		temp = node;
	} else if (node->left == &CBinarySortTree<T>::sentinel && node->right != &CBinarySortTree<T>::sentinel) {
		fixup = node->right;
		temp = this->Transplant(node, node->right);
	} else if (node->left != &CBinarySortTree<T>::sentinel && node->right == &CBinarySortTree<T>::sentinel) {
		fixup = node->left;
		temp = this->Transplant(node, node->left);
	} else {
		CBinaryTreeNode<T>* successor = this->SearchMinOnRightChild(node->right);
		original_color = successor->color;
		fixup = successor->right;

		if (successor->parent != node) {
			this->Transplant(successor, successor->right);
			successor->right = node->right;
			successor->right->parent = successor;
		} else
			fixup->parent = successor; // 'cause sentinel's parent points to itself

		temp = this->Transplant(node, successor);
		successor->left = node->left;
		successor->left->parent = successor;
		successor->color = (*del)->color; // remain the original color
	}

	if (original_color == CBinaryTreeNode<T>::BLACK && this->root != &CBinarySortTree<T>::sentinel)
		DeleteFixup(fixup);

	delete temp;
}

template <typename T>
void CRedBlackTree<T>::InorderWalk() const
{
	InorderWalk(this->root);
}

template <typename T>
void CRedBlackTree<T>::InorderWalk(const CBinaryTreeNode<T>* node) const
{
	const CBinaryTreeNode<T>* p = node;

	if (p != &CBinarySortTree<T>::sentinel) {
		InorderWalk(p->left);
		cout << p->key << ((p->color == CBinaryTreeNode<T>::RED) ? " RED" : " BLACK") << endl;
		InorderWalk(p->right);
	}
}

template <typename T>
void CRedBlackTree<T>::InsertFixup(CBinaryTreeNode<T>* node)
{
	CBinaryTreeNode<T>* y = &CBinarySortTree<T>::sentinel;

	while (node->parent != &CBinarySortTree<T>::sentinel && node->parent->color == CBinaryTreeNode<T>::RED) {
		if (node->parent == node->parent->parent->left) {
			y = node->parent->parent->right; // uncle node
			
			if (y->color == CBinaryTreeNode<T>::RED) {
				node->parent->color = CBinaryTreeNode<T>::BLACK;
				y->color = CBinaryTreeNode<T>::BLACK;
				node->parent->parent->color = CBinaryTreeNode<T>::RED;
				node = node->parent->parent;
			} else {
				if (node == node->parent->right) {
					node = node->parent;
					LeftRotate(node);
				}

				node->parent->color = CBinaryTreeNode<T>::BLACK;
				node->parent->parent->color = CBinaryTreeNode<T>::RED;
				RightRotate(node->parent->parent);
			}
		} else { // symmetric to left
			y = node->parent->parent->left; // uncle node
			
			if (y->color == CBinaryTreeNode<T>::RED) {
				node->parent->color = CBinaryTreeNode<T>::BLACK;
				y->color = CBinaryTreeNode<T>::BLACK;
				node->parent->parent->color = CBinaryTreeNode<T>::RED;
				node = node->parent->parent;
			} else {
				if (node == node->parent->left) {
					node = node->parent;
					RightRotate(node);
				}

				node->parent->color = CBinaryTreeNode<T>::BLACK;
				node->parent->parent->color = CBinaryTreeNode<T>::RED;
				LeftRotate(node->parent->parent);
			}
		}
	}

	this->root->color = CBinaryTreeNode<T>::BLACK;
}

template <typename T>
void CRedBlackTree<T>::DeleteFixup(CBinaryTreeNode<T>* node)
{
	CBinaryTreeNode<T>* w = node;

	while (node != this->root && node->color == CBinaryTreeNode<T>::BLACK) {
		if (node == node->parent->left) {
			w = node->parent->right; // brother node
			if (w->color == CBinaryTreeNode<T>::RED) {
				w->color = CBinaryTreeNode<T>::BLACK;
				w->parent->color = CBinaryTreeNode<T>::RED;
				LeftRotate(node->parent);
				w = node->parent->right;
			}

			if (w->left->color == CBinaryTreeNode<T>::BLACK && w->right->color == CBinaryTreeNode<T>::BLACK) {
				w->color = CBinaryTreeNode<T>::RED;
				node = node->parent;
			} else {
				if (w->right->color == CBinaryTreeNode<T>::BLACK) {
					w->left->color = CBinaryTreeNode<T>::BLACK;
					w->color = CBinaryTreeNode<T>::RED;
					RightRotate(w);
					w = node->parent->right;
				}

				w->color = node->parent->color;
				w->right->color = CBinaryTreeNode<T>::BLACK;
				node->parent->color = CBinaryTreeNode<T>::BLACK;
				LeftRotate(node->parent);
				node = this->root;
			}
		} else {
			w = node->parent->left;
			if (w->color == CBinaryTreeNode<T>::RED) {
				w->color = CBinaryTreeNode<T>::BLACK;
				w->parent->color = CBinaryTreeNode<T>::RED;
				RightRotate(node->parent);
				w = node->parent->left;
			}

			if (w->left->color == CBinaryTreeNode<T>::BLACK && w->right->color == CBinaryTreeNode<T>::BLACK) {
				w->color = CBinaryTreeNode<T>::RED;
				node = node->parent;
			} else {
				if (w->left->color == CBinaryTreeNode<T>::BLACK) {
					w->right->color = CBinaryTreeNode<T>::BLACK;
					w->color = CBinaryTreeNode<T>::RED;
					LeftRotate(w);
					w = node->parent->left;
				}

				w->color = node->parent->color;
				w->left->color = CBinaryTreeNode<T>::BLACK;
				node->parent->color = CBinaryTreeNode<T>::BLACK;
				RightRotate(node->parent);
				node = this->root;
			}
		}
	}

	node->color = CBinaryTreeNode<T>::BLACK;
}

template <typename T>
void CRedBlackTree<T>::LeftRotate(CBinaryTreeNode<T>* node)
{
	CBinaryTreeNode<T>* y = node->right;

	node->right = y->left;
	if (y->left != &CBinarySortTree<T>::sentinel)
		y->left->parent = node;

	y->parent = node->parent;

	if (node->parent == &CBinarySortTree<T>::sentinel)
		this->root = y;
	else if (node == node->parent->left)
		node->parent->left = y;
	else
		node->parent->right = y;

	y->left = node;
	node->parent = y;
}

template <typename T>
void CRedBlackTree<T>::RightRotate(CBinaryTreeNode<T>* node)
{
	CBinaryTreeNode<T>* x = node->left;

	node->left = x->right;
	if (x->right != &CBinarySortTree<T>::sentinel)
		x->right->parent = node;

	x->parent = node->parent;

	if (node->parent == &CBinarySortTree<T>::sentinel)
		this->root = x;
	else if (node->parent->left == node)
		node->parent->left = x;
	else
		node->parent->right = x;

	x->right = node;
	node->parent = x;
}

#endif
        这里简要说明一下,红黑树在二叉搜索树的插入和删除操作基础上还有修正操作,而对Insert的修正操作比较简单,只需要操作被插入的结点,所以直接重用了二叉搜索树的Insert,而对Delete的修正操作就比较复杂些,所以这里重新实现了Delete操作,其实逻辑跟二叉搜索树的删除操作大体上相同。

        最后,测试红黑树的代码,rbt_test.cpp:

#include "rbt.h"

int main(int argc, const char **argv)
{
	int key[] = { 12, 1, 9, 2, 0, 11, 7, 19, 4, 15, 18, 5, 14, 13, 10, 16, 6, 3, 8, 17 };

	CRedBlackTree<int> rbt;

	cout << "original key: " << endl;
	for (size_t i = 0; i < sizeof(key) / sizeof(int); ++i)
		cout << key[i] << ' ';

	cout << endl;
	for (size_t i = 0; i < sizeof(key) / sizeof(int); ++i) {
		rbt.Insert(key[i]);

		cout << "after insertion: " << key[i] << endl;
		rbt.InorderWalk();
	}

	cout << endl;

	for (size_t i = 0; i < sizeof(key) / sizeof(int); ++i) {
		CBinaryTreeNode<int>* del = rbt.Search(key[i]);
		if (del) {
			cout << "after " << i + 1 << " time(s) deletion: " << endl;
			rbt.Delete(&del);
			rbt.InorderWalk();
			cout << endl;
		}
	}

	return 0;
}

        同样,验证时使用到如下网址的图片,在此表示感谢:http://saturnman.blog.163.com/blog/static/557611201097221570/

        附:

        C++的一大特性是多态,由于二叉搜索树类是红黑树类的父类,所以,我们可以使用二叉搜索树类的指针或者引用在运行时动态绑定红黑树的成员函数,实现多态,rbt_test.cpp:

#include "rbt.h"

using std::runtime_error;

int main(int argc, const char **argv)
{
	int key[] = { 12, 1, 9, 2, 0, 11, 7, 19, 4, 15, 18, 5, 14, 13, 10, 16, 6, 3, 8, 17 };
	CBinarySortTree<int>* pbst = NULL;
	
	try {
		pbst = new CRedBlackTree<int>();
		if (!pbst)
			throw runtime_error("new object failed.");

		cout << "original key: " << endl;
		for (size_t i = 0; i < sizeof(key) / sizeof(int); ++i)
		cout << key[i] << ' ';

		cout << endl;
		for (size_t i = 0; i < sizeof(key) / sizeof(int); ++i) {
			pbst->Insert(key[i]);

			cout << "after insertion: " << key[i] << endl;
			pbst->InorderWalk();
		}

		cout << endl;

		for (size_t i = 0; i < sizeof(key) / sizeof(int); ++i) {
			CBinaryTreeNode<int>* del = pbst->Search(key[i]);
			if (del) {
				cout << "after " << i + 1 << " time(s) deletion: " << endl;
				pbst->Delete(&del);
				pbst->InorderWalk();
				cout << endl;
			}
		}

		delete pbst;
	} catch (...) {
		if (pbst)
			delete pbst;
	}

	pbst = NULL;

	return 0;
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值