C++ 红黑树的实现

来源:互联网 发布:red flag linux 下载 编辑:程序博客网 时间:2024/06/05 14:33

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

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  0typedef 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;}elsepPreNode->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;}elsepTemp->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;}elsepPreNode->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;}// 查找指定结点,成功 放回该结点,否则返回NULLRBTreeNode * 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;elsepNodePaBro = 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;}}// whilem_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);}elseRB_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;  //子 ==> blackreturn;}// 左旋处理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;}elsenArrNodes[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;}