C++ 红黑树的实现

红黑树性质及实现详细介绍:

http://zh.wikipedia.org/zh/%E7%BA%A2%E9%BB%91%E6%A0%91

代码部分:

 头文件

// RBTree.h: interface for the CRBTree class.
//
//

#if !defined(AFX_RBTREE_H__9C701E48_A116_4AE0_8736_B5F45F530AF5__INCLUDED_)
#define AFX_RBTREE_H__9C701E48_A116_4AE0_8736_B5F45F530AF5__INCLUDED_

#if _MSC_VER > 1000
#pragma once
#endif // _MSC_VER > 1000

#define BLACK 0
#define RED   1
#define NULL  0
typedef int BOOL;

typedef struct RBTreeNode
{
	int key;
	int color;
	struct RBTreeNode *parent, *left, *right;
	RBTreeNode(){}
	RBTreeNode(int k):key(k){  // 创建新结点默认颜色为红色
		color = RED;
		parent = NULL;
		left = NULL;
		right = NULL;}
}RBTree, RBTreeNode;


class CRBTree  
{
public:
	CRBTree();
	virtual ~CRBTree();

	void RB_InitLeafNode();
	BOOL RB_Insert(int keyVal);
	BOOL RB_Delete(int keyVal);
	RBTreeNode *RB_Find(int keyVal);
	void RB_Print();
	int RB_GetSize()const { return m_Size; }
private:
	void RB_Insert_FixedUp(RBTreeNode *&pNode);
	void RB_Del_FixedUp(RBTreeNode *&pNode);
	void RB_Left_Rotate(RBTreeNode *&pNode);
	void RB_Right_Rotate(RBTreeNode *&pNode);
	void RB_Print(RBTreeNode *&pNode);
	void RB_SwapTwoNodes(RBTreeNode *&pNode1, RBTreeNode *&pNode2);
	void RB_EmptyTree(RBTreeNode *&pNode);
private:
	RBTree *m_root;  //根结点
	RBTreeNode *m_NIL; // 空结点
	int m_Size;
};

#endif // !defined(AFX_RBTREE_H__9C701E48_A116_4AE0_8736_B5F45F530AF5__INCLUDED_)


 

实现文件

// RBTree.cpp: implementation of the CRBTree class.
//
//
#include <iostream>
#include "RBTree.h"
using namespace std;

//
// Construction/Destruction
//
// 构造函数
CRBTree::CRBTree()
{
	m_root = m_NIL = NULL;
	m_Size = 0;
}

// 析构函数
CRBTree::~CRBTree()
{
	RB_EmptyTree(m_root);
	delete m_NIL;
	m_root = m_NIL = NULL;
	cout << "Empty the tree!\n";
}

// 初始化叶子结点
void CRBTree::RB_InitLeafNode()
{
	m_root = new RBTree(-1);
	m_NIL = new RBTreeNode(-1);
	m_NIL->color = BLACK;  // 叶子结点颜色都为黑色
	m_NIL->parent = NULL;
	m_NIL->left = m_NIL->right = NULL;
	m_root = m_NIL;
	m_root->parent = m_NIL;
}

// 插入树结点
BOOL CRBTree::RB_Insert( int keyVal )
{
	RBTreeNode *pNewNode = new RBTreeNode(keyVal);
	pNewNode->left = m_NIL;
	pNewNode->right = m_NIL;
	RBTreeNode *pNode = m_root;
	RBTreeNode *pPreNode = m_NIL;
	while(pNode != m_NIL)  // 树不为空
	{
		pPreNode = pNode;
		if (keyVal < pNode->key)
		{
			pNode = pNode->left;
		}
		else if (keyVal > pNode->key)
		{
			pNode = pNode->right;
		}
		else{
			delete pNewNode;
			return 0;
		}
	}
	pNewNode->parent = pPreNode;
	if (pPreNode == m_NIL)  // 树为空
	{
		pNewNode->color = BLACK;
		m_root = pNewNode;
	}
	else
	{
		if (keyVal < pPreNode->key)
		{
			pPreNode->left = pNewNode;
		}
		else
			pPreNode->right = pNewNode;
	}
	m_Size++;
	cout << "Insert "<< m_Size << " node: " << keyVal << " succeeded!\n";
	RB_Insert_FixedUp(pNewNode);
	return 1;
}

// 删除树结点
BOOL CRBTree::RB_Delete( int keyVal )
{
	RBTreeNode *pDelNode, *pPreNode = m_NIL;
	if (m_root == m_NIL)
	{
		return 0;
	}
// 	pDelNode = m_root;
// 	while(pDelNode != m_NIL)
// 	{
// 		if (keyVal < pDelNode->key)
// 		{
// 			pPreNode = pDelNode;
// 			pDelNode = pDelNode->left;
// 		}
// 		else if (keyVal > pDelNode->key)
// 		{
// 			pPreNode = pDelNode;
// 			pDelNode = pDelNode->right;
// 		}
// 		else
// 			break;
// 	}
	pDelNode = RB_Find(keyVal);
	if (pDelNode == NULL)
	{
		return 0; // 没有此结点
	}
	pPreNode = pDelNode->parent;
	//从该结点的左子树找出最大的结点或从右子树找出最小的结点, 两者的值进行替换
	RBTreeNode *pTemp;
	RBTreeNode *pDelChild;
	if (pDelNode->left != m_NIL && pDelNode->right != m_NIL)
	{ // 有两个子结点,查找左子树
		pTemp = pDelNode->left;
		while(pTemp->right != m_NIL)
		{
			pTemp = pTemp->right;
		}

		RB_SwapTwoNodes(pTemp, pDelNode);
	
		pDelChild = pTemp->left;
		pDelChild->parent = pTemp->parent;
		if (pTemp->parent->left == pTemp)
		{
			pTemp->parent->left = pDelChild;
		}
		else
			pTemp->parent->right = pDelChild;
	}
	else if (pDelNode->left == m_NIL && pDelNode->right == m_NIL)
	{ // 要删除的结点是叶子结点
		if (pPreNode == m_NIL)
		{
			delete m_root;
			m_root = m_NIL;
			m_Size--;
			return 1;
		}
		else
		{
			if (pDelNode == pDelNode->parent->left)
			{
				pPreNode->left = m_NIL;
			}
			else
				pPreNode->right = m_NIL;
			pDelChild = m_NIL;
			pDelChild->parent = pDelNode->parent;
			pTemp = pDelNode;
		}
	}
	else // 有一个子结点
	{ 
		if (pDelNode->left != m_NIL)
		{
			pDelChild = pDelNode->left;
		}
		else 
		{
			pDelChild = pDelNode->right;
		}
		if (pDelChild == pPreNode->left)
		{
			pDelChild->parent = pPreNode;
			pPreNode->left = pDelChild;
		}
		else
		{
			pDelChild->parent = pPreNode;
			pPreNode->right = pDelChild;
		}
		pTemp = pDelNode;	
	}
	if (pTemp->color == BLACK)
	{
		RB_Del_FixedUp(pDelChild);
	}
	cout << "Deleted node: " << pTemp->key << endl;
	delete pTemp;
	m_Size--;
	return 1;
}

// 查找指定结点,成功 放回该结点,否则返回NULL
RBTreeNode * CRBTree::RB_Find( int keyVal )
{
	RBTreeNode *pNode;
	if (m_root == m_NIL)
	{
		return NULL;
	}
	pNode = m_root;
	while(pNode != m_NIL)
	{
		if (keyVal < pNode->key)
		{
			pNode = pNode->left;
		}
		else if (keyVal > pNode->key)
		{
			pNode = pNode->right;
		}
		else{
			cout << "Find node: " << keyVal << "succeeded!\n";
			return pNode;
		}
	}
	return NULL;
}

// 插入结点后形成的新结构不满足红黑树性质和对其进行处理
void CRBTree::RB_Insert_FixedUp( RBTreeNode *&pNode )
{
	while (pNode->parent->color == RED)
	{
		RBTreeNode *pNodeParent = pNode->parent;
		RBTreeNode *pNodePaBro;
		if (pNodeParent->parent->left == pNodeParent) 
			pNodePaBro = pNodeParent->parent->right;
		else
			pNodePaBro = pNodeParent->parent->left;
		if (pNodePaBro->color == RED)
		{  // 父结点和叔结点都是红色 ==>> 父--黑  叔--黑  祖父--红
			pNodeParent->color = BLACK;
			pNodePaBro->color = BLACK;
			pNodeParent->parent->color = RED;
			pNode = pNode->parent->parent;
			if (pNode == m_NIL)
			{
				m_root->color = BLACK;
				return ;
			}
		}
		/// 红父 黑叔结点 或者没有叔结点
		else if(pNodeParent->parent->left == pNodeParent && pNodeParent->left == pNode)
		{
			pNodeParent->color = BLACK;
			pNodeParent->parent->color = RED;
			RB_Right_Rotate(pNode->parent->parent);
			break;
		}
		else if (pNodeParent->parent->left == pNodeParent && pNodeParent->right == pNode)
		{
			pNode = pNode->parent;
			RB_Left_Rotate(pNode);
		}
		else if (pNodeParent->parent->right == pNodeParent && pNodeParent->left == pNode)
		{
			pNode = pNode->parent;
			RB_Right_Rotate(pNode);
		}
		else 
		{
			pNodeParent->color = BLACK;
			pNodeParent->parent->color = RED;
			RB_Left_Rotate(pNode->parent->parent);
			break;
		}
	}// while
	m_root->color = BLACK;
}

// 删除结点后形成的新结构不满足红黑树性质和对其进行处理
void CRBTree::RB_Del_FixedUp( RBTreeNode *&pNode )
{
	int nLRFlag;
	RBTreeNode *pBroNode;
	while(pNode != m_root && pNode->color == BLACK)
	{
		if (pNode->parent->left == pNode)
		{
			nLRFlag = 0;
			pBroNode = pNode->parent->right;
		}
		else 
		{
			nLRFlag = 1;
			pBroNode = pNode->parent->left;
		}
		
		//1 父-red  无兄 子-red  ==>> 子-black
		//2 父-black  兄-red  ==>> 父-red 兄-black 旋转父结点 
		if (pBroNode->color == RED)
		{
			pNode->parent->color = BLACK;
			pBroNode->color = BLACK;
			if (nLRFlag == 0)
			{
				RB_Left_Rotate(pNode->parent);
			}
			else
				RB_Right_Rotate(pNode->parent);
		}
		//3 兄-black  两黑侄  ==>>	兄=红 子=黑 红父=黑 往上遍历(黑父)
		else if (pBroNode->left->color == BLACK && pBroNode->right->color == BLACK)
		{
			pNode->color = BLACK;
			pBroNode->color = RED;
			pNode->parent->color = BLACK;
			pNode = pNode->parent;  // 往上遍历
		}
		//4 兄-black  左黑侄右红侄  ==>> 兄=父色 父=黑 侄=黑 (子=黑) 左旋转父节点
		else if (pBroNode->left->color == BLACK && pBroNode->right->color == RED)
		{
			if (nLRFlag == 0)
			{
				pBroNode->color = pNode->parent->color;
				pNode->parent->color = BLACK;
				pNode->color = BLACK;
				pBroNode->right->color = BLACK;				
				RB_Left_Rotate(pNode->parent);
				break;
			}
			else 
			{
				RBTreeNode *pPa = pNode->parent;
				pBroNode->left->color = pNode->parent->color;
				pNode->parent->color = BLACK;
				RB_Left_Rotate(pBroNode);
				RB_Right_Rotate(pPa);
				break;
			}	
		}
		//5	兄-black  左红侄右黑侄  ==>> 侄=父色 父=黑 右旋转兄 左旋转父
		else if (pBroNode->left->color == RED && pBroNode->right->color == BLACK)
		{
			
			if (nLRFlag == 0)
			{
				RBTreeNode *pPa = pNode->parent;
				pBroNode->left->color = pNode->parent->color;
				pNode->parent->color = BLACK;
				RB_Right_Rotate(pBroNode);
				RB_Left_Rotate(pPa);
				break;
			}
			else 
			{
				pBroNode->color = pNode->parent->color;
				pNode->parent->color = BLACK;
				pNode->color = BLACK;
				pBroNode->right->color = BLACK;				
				RB_Right_Rotate(pNode->parent);
				break;
			}	
		}
		else  //两红侄的情况 转换成一黑一红的情况
		{
			if (nLRFlag == 0)
			{
				pBroNode->left->color = BLACK;
			}
			else
			{
				pBroNode->right->color = BLACK;
			}	
		}
	}
	pNode->color = BLACK;  //子 ==> black
	return;
}

// 左旋处理
void CRBTree::RB_Left_Rotate( RBTreeNode *&pNode )
{
	RBTreeNode *pNodeA = pNode->parent;
	RBTreeNode *pNodeB = pNode->right;
	pNode->right = pNodeB->left;
	pNodeB->left->parent = pNode;
	pNodeB->left = pNode;
	pNode->parent = pNodeB;

	if (pNode == pNodeA->left)
	{  // 父子不同边
		pNodeA->left = pNodeB;
		pNodeB->parent = pNodeA;
	}
	else if (pNode = pNodeA->right)
	{
		pNodeA->right = pNodeB;
		pNodeB->parent = pNodeA;
	}
	else // m_root == m_NIL
	{
		if (pNodeA == m_NIL)
		{  // pNode 原本为根结点
			pNodeB->parent = m_NIL;
			m_root = pNodeB;
		}
	}
	cout << "RB_Left_Rotate()\n";
}

// 右旋处理函数
void CRBTree::RB_Right_Rotate( RBTreeNode *&pNode )
{
	RBTreeNode *pNodeA = pNode->parent;
	RBTreeNode *pNodeB = pNode->left;
	pNode->left = pNodeB->right;
	pNodeB->right->parent = pNode;
	pNodeB->right = pNode;
	pNode->parent = pNodeB;
	
	if (pNode == pNodeA->right)
	{  // 父子不同边
		pNodeA->right = pNodeB;
		pNodeB->parent = pNodeA;
	}
	else if (pNode = pNodeA->left)
	{
		pNodeA->left = pNodeB;
		pNodeB->parent = pNodeA;
	}
	else // m_root == m_NIL
	{
		if (pNodeA == m_NIL)
		{  // pNodeA 原本为父结点
			pNodeB->parent = m_NIL;
			m_root = pNodeB;
		}
	}
	cout << "RB_Right_Rotate()\n";
}

void CRBTree::RB_Print()
{
	if (m_root == m_NIL)
	{
		cout << "树为空!\n";
		return ;
	}
	RB_Print(m_root);
	cout << endl;
}

void CRBTree::RB_Print( RBTreeNode *&pNode )
{
	if (pNode != m_NIL)
	{
		cout << pNode->key << "(" << pNode->color << ")  ";
		RB_Print(pNode->left);
		RB_Print(pNode->right);
	}
}

void CRBTree::RB_SwapTwoNodes( RBTreeNode *&pNode1, RBTreeNode *&pNode2 )
{
	int t = pNode1->key;
	pNode1->key = pNode2->key;
	pNode2->key = t;
}

void CRBTree::RB_EmptyTree( RBTreeNode *&pNode )
{
	if (pNode != m_NIL)
	{
		RB_EmptyTree(pNode->left);
		RB_EmptyTree(pNode->right);
		delete pNode;
	}
}


 

测试文件

//
//
#include <iostream>
#include "RBTree.h"
#include <Windows.h>
#include <ctime>
using namespace std;

void time_Test();
void Fun_Test();
int main()
{
	cout << "红黑树RBTree测试程序 !\n";
	Fun_Test();
	return 0;
}

void Fun_Test()
{
	CRBTree tree;
	tree.RB_InitLeafNode();
 	tree.RB_Insert(10);
 	tree.RB_Insert(14);
 	tree.RB_Insert(4);
 	tree.RB_Insert(12);
	tree.RB_Insert(11);
	tree.RB_Insert(13);
 	tree.RB_Insert(7);
 	tree.RB_Insert(16);
 	tree.RB_Print();
 	tree.RB_Delete(14);
 	tree.RB_Delete(10);
 	Sleep(1000);
	tree.RB_Print();
}

void time_Test()
{
	CRBTree tree;
	clock_t t_insert, t_print, t_find;
	int nArrNodes[50000];
	tree.RB_InitLeafNode();
	srand((unsigned)time(NULL));
//	srand(0);
	t_insert = clock();
	for (int i = 0; i < 50000; i++)
	{
		nArrNodes[i] = rand()%10000000 +1;
		while (1)
		{
			if (tree.RB_Find(nArrNodes[i]) == NULL)
			{
				tree.RB_Insert(nArrNodes[i]);
				break;
			}
			else
				nArrNodes[i] = rand()%10000000 +1;
		}
	}
	t_insert = clock() - t_insert;
	t_print = clock();
	
	tree.RB_Print();
	t_print = clock() - t_print;
	t_find = clock();
	tree.RB_Find(32725);
	t_find = clock() - t_find;
	cout << "The tree nodes count is: " << tree.RB_GetSize() << endl;
	cout << "Insert data need time: " << t_insert << "ms." << endl;
	cout << "Print data need time: " << t_print << "ms." << endl;
	cout << "Find one data need time: " << t_find << "ms." << endl;
}


 

当然,我可以帮你实现一个基于红黑树的Map数据结构。下面是一个简单的C++代码示例: ```cpp #include <iostream> enum Color { RED, BLACK }; template <typename K, typename V> struct Node { K key; V value; Color color; Node* left; Node* right; Node* parent; // 构造函数 Node(const K& k, const V& v, Color c = RED) : key(k), value(v), color(c), left(nullptr), right(nullptr), parent(nullptr) {} }; template <typename K, typename V> class RBTreeMap { public: RBTreeMap() : root(nullptr) {} // 向红黑树中插入键值对 void insert(const K& key, const V& value) { Node<K, V>* node = new Node<K, V>(key, value); if (root == nullptr) { root = node; node->color = BLACK; } else { Node<K, V>* curr = root; Node<K, V>* parent = nullptr; while (curr != nullptr) { parent = curr; if (key < curr->key) curr = curr->left; else if (key > curr->key) curr = curr->right; else { curr->value = value; // 更新值 return; } } node->parent = parent; if (key < parent->key) parent->left = node; else parent->right = node; insertFixup(node); } } // 查找指定键的值 V find(const K& key) const { Node<K, V>* curr = root; while (curr != nullptr) { if (key < curr->key) curr = curr->left; else if (key > curr->key) curr = curr->right; else return curr->value; } return V(); // 未找到,返回默认值 } private: Node<K, V>* root; // 对红黑树进行修复以维持红黑树的性质 void insertFixup(Node<K, V>* node) { while (node->parent != nullptr && node->parent->color == RED) { if (node->parent == node->parent->parent->left) { Node<K, V>* uncle = node->parent->parent->right; if (uncle != nullptr && uncle->color == RED) { node->parent->color = BLACK; uncle->color = BLACK; node->parent->parent->color = RED; node = node->parent->parent; } else { if (node == node->parent->right) { node = node->parent; rotateLeft(node); } node->parent->color = BLACK; node->parent->parent->color = RED; rotateRight(node->parent->parent); } } else { Node<K, V>* uncle = node->parent->parent->left; if (uncle != nullptr && uncle->color == RED) { node->parent->color = BLACK; uncle->color = BLACK; node->parent->parent->color = RED; node = node->parent->parent; } else { if (node == node->parent->left) { node = node->parent; rotateRight(node); } node->parent->color = BLACK; node->parent->parent->color = RED; rotateLeft(node->parent->parent); } } } root->color = BLACK; } // 左旋 void rotateLeft(Node<K, V>* node) { Node<K, V>* rightChild = node->right; node->right = rightChild->left; if (rightChild->left != nullptr) rightChild->left->parent = node; rightChild->parent = node->parent; if (node->parent == nullptr) root = rightChild; else if (node == node->parent->left) node->parent->left = rightChild; else node->parent->right = rightChild; rightChild->left = node; node->parent = rightChild; } // 右旋 void rotateRight(Node<K, V>* node) { Node<K, V>* leftChild = node->left; node->left = leftChild->right; if (leftChild->right != nullptr) leftChild->right->parent = node; leftChild->parent = node->parent; if (node->parent == nullptr) root = leftChild; else if (node == node->parent->left) node->parent->left = leftChild; else node->parent->right = leftChild; leftChild->right = node; node->parent = leftChild; } }; int main() { RBTreeMap<int, std::string> map; map.insert(1, "one"); map.insert(2, "two"); map.insert(3, "three"); map.insert(4, "four"); std::cout << map.find(2) << std::endl; // 输出: two std::cout << map.find(5) << std::endl; // 输出: 空字符串(默认值) return 0; } ``` 这个示例使用红黑树实现了一个简单的Map数据结构。你可以使用`insert`方法向Map中插入键值对,使用`find`方法查找指定键的值。注意,这只是一个简单的实现,还可以根据需要进行扩展和优化。
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值