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

        三年前磕磕盼盼用C语言写过红黑树,这段时间用C++重写了红黑树,修复了之前代码中的一些错误。记得以前的博客里面就写过使用C++写红黑树更容易些,因为可以重用二叉搜索树的C++代码。照例,首先实现二叉搜索树,然后再实现红黑树。

        首先,定义二叉树结点的类,btnode.h:

#ifndef __BTNODE_H__
#define __BTNODE_H__
#include <stdexcept>
#include <typeinfo>

using std::logic_error;

template <typename T>
struct CBinaryTreeNode
{
	enum eColor {
		RED,
		BLACK
	};

	CBinaryTreeNode(const T& val, CBinaryTreeNode<T>* parent = NULL, CBinaryTreeNode<T>* left = NULL, CBinaryTreeNode<T>* right = NULL, eColor color = RED);
	virtual ~CBinaryTreeNode();

	virtual bool operator==(const CBinaryTreeNode<T>& node);
	virtual bool operator<(const CBinaryTreeNode<T>& node);
	virtual bool operator>(const CBinaryTreeNode<T>& node);

	T key;
	CBinaryTreeNode<T> *parent;
	CBinaryTreeNode<T> *left;
	CBinaryTreeNode<T> *right;

	eColor color;
};

template <typename T>
CBinaryTreeNode<T>::CBinaryTreeNode(const T& val, CBinaryTreeNode<T>* parent, CBinaryTreeNode<T>* left, CBinaryTreeNode<T>* right, eColor color)
{
	key = val;
	this->parent = parent;
	this->left = left;
	this->right = right;
	this->color = color;
}

template<typename T>
CBinaryTreeNode<T>::~CBinaryTreeNode()
{

}

template <typename T>
bool CBinaryTreeNode<T>::operator==(const CBinaryTreeNode<T>& node)
{
	if (typeid(*this) != typeid(node))
		throw logic_error("diffrent type objects.");

	return this->key == node.key;
}

template <typename T>
bool CBinaryTreeNode<T>::operator<(const CBinaryTreeNode<T>& node)
{
	if (typeid(*this) != typeid(node))
		throw logic_error("diffrent type objects.");

	return this->key < node.key;
}

template <typename T>
bool CBinaryTreeNode<T>::operator>(const CBinaryTreeNode<T>& node)
{
	if (typeid(*this) != typeid(node))
		throw logic_error("diffrent type objects.");

	return this->key > node.key;
}

#endif
        然后,定义二叉搜索树的类,bst.h:

#ifndef __BST_H__
#define __BST_H__
#include <iostream>
#include "btnode.h"

using std::cout;
using std::endl;

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

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

	protected:
		CBinaryTreeNode<T>* SearchMinOnRightChild(CBinaryTreeNode<T>* val);
		CBinaryTreeNode<T>* Transplant(CBinaryTreeNode<T>* u, CBinaryTreeNode<T>* v);
		void InorderWalk(const CBinaryTreeNode<T>* root) const;

		CBinaryTreeNode<T>* root;
		static CBinaryTreeNode<T> sentinel;
};

template <typename T>
CBinaryTreeNode<T> CBinarySortTree<T>::sentinel(0, &sentinel, &sentinel, &sentinel, CBinaryTreeNode<T>::BLACK);

template <typename T>
CBinarySortTree<T>::CBinarySortTree()
{
	root = &sentinel;
	root->parent = &sentinel;
	root->left = &sentinel;
	root->right = &sentinel;
}

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

	if (root == &sentinel) {
		p = new CBinaryTreeNode<T>(key, &sentinel, &sentinel, &sentinel);
		root = p;
	} else {
		p = root;
		CBinaryTreeNode<T> *parent = &sentinel;
		CBinaryTreeNode<T> *node = new CBinaryTreeNode<T>(key, &sentinel, &sentinel, &sentinel);

		while (p != &sentinel) {
			parent = p;

			if (*p < *node)
				p = p->right;
			else
				p = p->left;
		}

		node->parent = parent;
		if (*parent < *node)
			parent->right = node;
		else
			parent->left = node;

		p = node;
	}

	return p;
}

template <typename T>
CBinaryTreeNode<T>* CBinarySortTree<T>::SearchMinOnRightChild(CBinaryTreeNode<T>* node)
{
	while (node->left != &sentinel)
		node = node->left;

	return node;
}

template <typename T>
CBinaryTreeNode<T>* CBinarySortTree<T>::Transplant(CBinaryTreeNode<T>* u, CBinaryTreeNode<T>* v)
{
	CBinaryTreeNode<T>* d = NULL;

	if (u->parent == &sentinel) {
		d = root;
		root = v;
	} else {
		d = u;
		if (u == u->parent->left)
			u->parent->left = v;
		else
			u->parent->right = v;
	}

	v->parent = u->parent;

	return d;
}

template <typename T>
void CBinarySortTree<T>::Delete(CBinaryTreeNode<T>** del)
{
	CBinaryTreeNode<T>* node = *del;
	CBinaryTreeNode<T>* n = &sentinel; 

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

		if (parent != &sentinel) {
			if (parent->left == node)
				parent->left = &sentinel;
			else
				parent->right = &sentinel;
		} else {
			*del = &sentinel;
			root = &sentinel;
		}

		delete node;
	} else if (node->left == &sentinel && node->right != &sentinel) {
		n = Transplant(node, node->right);
		delete n;
	} else if (node->left != &sentinel && node->right == &sentinel) {
		n = Transplant(node, node->left);
		delete n;
	} else {
		n = SearchMinOnRightChild(node->right);

		if (n->parent != node) {
			Transplant(n, n->right);
			n->right = node->right;
			n->right->parent = n;
		}

		CBinaryTreeNode<T>* temp = Transplant(node, n);
		n->left = node->left;
		n->left->parent = n;

		delete temp;
	}
}

template <typename T>
CBinaryTreeNode<T>* CBinarySortTree<T>::Search(CBinaryTreeNode<T>* node, const T& key) const
{
	if (node != &sentinel) {
		CBinaryTreeNode<T> n(key);

		if (*node < n)
			return Search(node->right, key);
		else if (*node > n)
			return Search(node->left, key);
		else
			return node;
	}

	return NULL;
}

template <typename T>
CBinaryTreeNode<T>* CBinarySortTree<T>::Search(const T& key) const
{
	return Search(root, key);
}

template <typename T>
void CBinarySortTree<T>::InorderWalk() const
{
	InorderWalk(root);
}

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

	if (p != &sentinel) {
		InorderWalk(p->left);
		cout << p->key << ' ';
		InorderWalk(p->right);
	}
}
#endif
        测试二叉搜索树的代码,bst_test.cpp:

#include "bst.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 };

	CBinarySortTree<int> bst;

	cout << "original key: ";
	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)
		bst.Insert(key[i]);

	cout << "after insertion: ";
	bst.InorderWalk();
	cout << endl;

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

	return 0;
}
        红黑树重用了大多数二叉树的接口,将在下一篇介绍。


猜你喜欢

转载自blog.csdn.net/winshining/article/details/50070323