红黑树(RBT)
红黑树(RBT)
红黑树是基于二叉搜索树(BST)的一种平衡树
红黑树是把树中的结点定义为红黑两种颜色, 并通过规则确保从根节点到叶结点的最长路径的长度不超过最短路径的两倍
在C++的STL中, set、multiset、map、multimap等数据结构都是基于红黑树实现的
规则:
- 每个结点color必须是红色或黑色
- 根结点必须是黑色的
- 树中不允许两个红结点互为父子关系
- 空结点:终端节点/哨兵结点,默认黑色:黑哨兵
- 从树中任意结点向下出发,到其所有可能到达的各个终端结点的各条路径上,黑结点的数目必须完全相同
红黑树的查找、删除、插入的时间复杂度都是log2n
插入:
删除:
一个算是规律的地方:旋转的时候两个结点一定交换颜色
代码:
#include <iostream> #include <queue> #include <stack> using std::cin; using std::cout; using std::endl; using std::queue; using std::stack; class RBT { private: typedef bool color; const bool RED; const bool BLACK; const int LEFT; const int RIGHT; const int ROOT; typedef struct Node { int value; color c; struct Node *pRChild; struct Node *pLChild; struct Node *pFather; }Node, *root; root rbt; public: RBT() : RED(1), BLACK(0), LEFT(1), RIGHT(0), ROOT(2) // 构造函数, 初始化成员变量 { rbt = NULL; } ~RBT() // 析构函数, 释放空间 { if (rbt == nullptr) return ; Free_Memory(rbt); } private: void Free_Memory(root Root) // 释放内存 { if (Root == nullptr) return; Free_Memory(Root->pLChild); // 后序遍历 Free_Memory(Root->pRChild); delete Root; Root = nullptr; } Node *Create_Node(int value) // 创建结点 { Node *pNode = (Node *)malloc(sizeof(Node)); pNode->value = value; pNode->c = RED; pNode->pLChild = NULL; pNode->pRChild = NULL; pNode->pFather = NULL; return pNode; } color Get_Node_Color(const Node *pNode) // 获取结点颜色 { if (pNode == NULL) return BLACK; else return pNode->c; } Node *Get_Insert_Pos(int value) // 返回查找结点的父亲结点 { Node *pFather = rbt; while (1) { if (value < pFather->value) { if (pFather->pLChild == nullptr) { break; } else { pFather = pFather->pLChild; } } else if (value > pFather->value) { if (pFather->pRChild == nullptr) { break; } else { pFather = pFather->pRChild; } } else { pFather = pFather->pFather; break; } } return pFather; } void Left_rotate(Node *pNode) // 左旋 { if (pNode == NULL || pNode->pRChild == NULL) { cout << "Left rotate argument error" << endl; return; } root pRoot = pNode->pRChild; pNode->pRChild = pRoot->pLChild; if (pNode->pRChild != nullptr) pNode->pRChild->pFather = pNode; pRoot->pFather = pNode->pFather; pRoot->pLChild = pNode; pNode->pFather = pRoot; if (pRoot->pFather != nullptr) { if (pRoot->value > pRoot->pFather->value) { pRoot->pFather->pRChild = pRoot; } else { pRoot->pFather->pLChild = pRoot; } } } void Right_rotate(Node *pNode) // 右旋 { if (pNode == NULL || pNode->pLChild == NULL) { cout << "Right rotate argument error" << endl; return; } root pRoot = pNode->pLChild; pNode->pLChild = pRoot->pRChild; if (pNode->pLChild != nullptr) pNode->pLChild->pFather = pNode; pRoot->pFather = pNode->pFather; pRoot->pRChild = pNode; pNode->pFather = pRoot; if (pRoot->pFather != nullptr) { if (pRoot->value > pRoot->pFather->value) { pRoot->pFather->pRChild = pRoot; } else { pRoot->pFather->pLChild = pRoot; } } } void Insert_Adjustment(Node *pNode) // 插入结点 { // 如果树是空的 if (rbt == NULL) { pNode->c = BLACK; rbt = pNode; } else { // 找到插入位置的父亲结点 Node *pFather = Get_Insert_Pos(pNode->value); // 父亲结点是黑色, 直接插入 pNode->pFather = pFather; if (pNode->value < pFather->value) { pFather->pLChild = pNode; } else { pFather->pRChild = pNode; } // 父亲结点是红色 if (Get_Node_Color(pFather) == RED) { Node *pGrandFather = pFather->pFather; Node *pUncle = nullptr; // 找到叔叔结点 if (pFather->value < pFather->pFather->value) { pUncle = pFather->pFather->pRChild; } else { pUncle = pFather->pFather->pLChild; } // 叔叔结点是红色 if (Get_Node_Color(pUncle) == RED) { // 叔叔结点、父亲结点、爷爷结点变色 pFather->c = BLACK; pUncle->c = BLACK; pGrandFather->c = RED; // 如果爷爷结点是根节点, 结束 if (pGrandFather == rbt) { pGrandFather->c = BLACK; // ----------------不要忘记将根节点置为黑色---------------------- return ; } // 将爷爷结点作为新结点插入 else { Insert_Adjustment(pGrandFather); } } // 叔叔结点是黑色, 判断旋转的情况 else { // 爷爷结点右旋, 交换爷爷结点和父亲结点的颜色 if (pNode == pFather->pLChild && pFather == pGrandFather->pLChild) { pFather->c = BLACK; pGrandFather->c = RED; Right_rotate(pGrandFather); if (pGrandFather == rbt) // -------------------不要忘记更换根节点---------------------------- rbt = pFather; } // 爷爷结点左旋, 交换爷爷结点和父亲结点的颜色 else if (pNode == pFather->pRChild && pFather == pGrandFather->pRChild) { pFather->c = BLACK; pGrandFather->c = RED; Left_rotate(pGrandFather); if (pGrandFather == rbt) // -------------------不要忘记更换根节点---------------------------- rbt = pFather; } // 父亲结点左旋, 再次调用Adjustment, 或者父亲结点左旋, 爷爷结点左旋, 交换爷爷结点和父亲结点的颜色 else if (pNode == pFather->pLChild && pFather == pGrandFather->pRChild) { Right_rotate(pFather); Insert_Adjustment(pFather); } else { Left_rotate(pFather); Insert_Adjustment(pFather); } } } } } void LDR_(root Root) // 中序遍历 { if (Root == nullptr) return ; LDR_(Root->pLChild); cout << Root->value << ' '; if (Get_Node_Color(Root) == RED) cout << "RED" << endl; else cout << "BLACK" << endl; LDR_(Root->pRChild); } Node *Find(int value) // 查找 { if (rbt == nullptr) return nullptr; Node *pNode = rbt; while (pNode) { if (value > pNode->value) pNode = pNode->pRChild; else if (value < pNode->value) pNode = pNode->pLChild; else break; } return pNode; } Node *Find_Max(Node *Root) { Node *pMin = Root; while (pMin->pRChild) { pMin = pMin->pRChild; } return pMin; } int Left_Right_Child(const Node *pNode) // 判断当前结点是根/父亲结点的左/右 { if (pNode->pFather == nullptr) return ROOT; else { if (pNode == pNode->pFather->pLChild) { return LEFT; } else return RIGHT; } } void Delete_Adjustment(Node *pDel) { if (rbt == nullptr || pDel == nullptr) return ; Node *pFather = pDel->pFather; Node *pBrother = nullptr; if (pFather->pLChild == pDel) pBrother = pFather->pRChild; else pBrother = pFather->pLChild; if (Get_Node_Color(pBrother) == RED) // 兄弟结点是红色, 侄子和父亲都是黑色 { // 旋转一次, 交换父亲和兄弟结点的颜色 pFather->c = RED; pBrother->c = BLACK; if (Left_Right_Child(pBrother) == LEFT) // 兄弟在左侧, 父亲右旋 { Right_rotate(pFather); } else // 兄弟在右侧, 父亲左旋 { Left_rotate(pFather); } Delete_Adjustment(pDel); // 重新讨论父亲结点 } else // 兄弟结点是黑色 { if (Get_Node_Color(pBrother->pLChild) == BLACK && Get_Node_Color(pBrother->pRChild) == BLACK) // 侄子结点都是黑色 { if (Get_Node_Color(pFather) == RED) { pFather->c = BLACK; pBrother->c = RED; return ; // ----------------------处理结束----------------------- } else { pBrother->c = RED; if (pFather == rbt) return ; // ----------------------处理结束----------------------- Delete_Adjustment(pFather); } } else // 侄子结点中存在红色 { if (Left_Right_Child(pBrother) == LEFT) // 兄弟在左侧 { if (Get_Node_Color(pBrother->pLChild) == RED) // 左左, 父亲右旋 { pBrother->c = pFather->c; pFather->c = BLACK; pBrother->pLChild->c = BLACK; Right_rotate(pFather); } else // 左右 { pBrother->c = RED; pBrother->pRChild->c = BLACK; Left_rotate(pBrother); Delete_Adjustment(pDel); } } else // 兄弟在右侧 { if (Get_Node_Color(pBrother->pRChild) == RED) // 右右, 父亲左旋 { pBrother->c = pFather->c; pFather->c = BLACK; pBrother->pRChild->c = BLACK; Left_rotate(pFather); } else // 右左, 右旋 { pBrother->c = RED; pBrother->pLChild->c = BLACK; Right_rotate(pBrother); Delete_Adjustment(pDel); } } } } } /* void SQT_() { // 判断队列是否为空 if (q.size() == 0) return ; // 从队列取出结点 const Node *pNode = q.front(); q.pop(); cout << pNode->value << endl; if (pNode->pLChild != NULL) { q.push(pNode->pLChild); } if (pNode->pRChild != NULL) { q.push(pNode->pRChild); } SQT_(); } */ public: void insert(int value) { Node *pNode = Create_Node(value); Insert_Adjustment(pNode); } void LDR() // 中序遍历 { if (rbt == NULL) return ; else { LDR_(rbt); } } void Delete_Node(int value) { // 找到删除结点 Node *pDel = Find(value); if (pDel == nullptr) return ; if (pDel->pLChild && pDel->pRChild) // 两个子结点 { // 找到左子树的最右替换当前的删除结点 Node *pMax = Find_Max(pDel->pLChild); int Temp = pDel->value; pDel->value = pMax->value; pDel = pMax; pDel->value = Temp; } if (pDel->pLChild && pDel->pRChild == NULL || pDel->pLChild == nullptr && pDel->pRChild) // 一个子结点 { int Mark = Left_Right_Child(pDel); // 被删除结点在左或右 if (Mark == ROOT) // 根节点 { if (pDel->pLChild) { rbt = pDel->pLChild; } else { rbt = pDel->pRChild; } rbt->c = BLACK; rbt->pFather = nullptr; delete pDel; pDel = NULL; } else if (Mark == LEFT) // 左结点 { if (pDel->pLChild) { pDel->pFather->pLChild = pDel->pLChild; pDel->pLChild->pFather = pDel->pFather; pDel->pLChild->c = BLACK; } else { pDel->pFather->pLChild = pDel->pRChild; pDel->pLChild->pFather = pDel->pFather; pDel->pLChild->c = BLACK; } delete pDel; pDel = nullptr; } else if (Mark == RIGHT) // 右结点 { if (pDel->pLChild) { pDel->pFather->pRChild = pDel->pLChild; pDel->pLChild->pFather = pDel->pFather; pDel->pLChild->c = BLACK; } else { pDel->pFather->pRChild = pDel->pRChild; pDel->pRChild->pFather = pDel->pFather; pDel->pRChild->c = BLACK; } delete pDel; pDel = nullptr; } return ; } if (pDel->pLChild == nullptr && pDel->pRChild == nullptr && Get_Node_Color(pDel) == RED) // 红叶子结点 { if (Left_Right_Child(pDel) == LEFT) { pDel->pFather->pLChild = nullptr; } else { pDel->pFather->pRChild = nullptr; } delete pDel; pDel = nullptr; return ; } if (pDel == rbt && pDel->pLChild == nullptr && pDel->pRChild == nullptr) // 单根 { rbt = nullptr; delete pDel; pDel = nullptr; return ; } Delete_Adjustment(pDel); // 判断删除黑色结点的情况, 兄弟, 父亲, 侄子的情况, 并调整 if (Left_Right_Child(pDel) == LEFT) { pDel->pFather->pLChild = nullptr; } else { pDel->pFather->pRChild = nullptr; } // 释放被删除的黑色叶子 delete pDel; pDel = nullptr; } /*void Sequence_Traversal() // 广度遍历, 递归 { if (rbt == NULL) return ; q.push(rbt); SQT_(); }*/ void Sequence_Traversal() // 两个指针, 进行层序遍历, 每一层在一行 { if (rbt == NULL) return ; queue<Node *> q; // 用于广度遍历 Node *pCurrent = nullptr; Node *pNext = nullptr; q.push(rbt); pCurrent = rbt; while (q.size()) { Node *pNode = q.front(); q.pop(); cout << pNode->value << ' '; if (pNode->pLChild != NULL) { q.push(pNode->pLChild); pNext = pNode->pLChild; } if (pNode->pRChild != NULL) { q.push(pNode->pRChild); pNext = pNode->pRChild; } if (pCurrent == pNode) { pCurrent = pNext; cout << endl; } } } void VLR_() // 非递归前序遍历 { if (rbt == nullptr) return ; stack<Node *> s; root pRoot = rbt; while (1) { if (pRoot != nullptr) { cout << pRoot->value << endl; s.push(pRoot); pRoot = pRoot->pLChild; } else { if (s.size() == 0) break; pRoot = s.top()->pRChild; s.pop(); } } } void LDR_() // 非递归中序遍历 { if (rbt == nullptr) return; stack<Node *> s; root pRoot = rbt; while (1) { if (pRoot) { s.push(pRoot); pRoot = pRoot->pLChild; } else { if (s.size() == 0) break; pRoot = s.top(); s.pop(); cout << pRoot->value << endl; pRoot = pRoot->pRChild; } } } void LRD_() // 非递归后序遍历 { if (rbt == nullptr) return ; stack<Node *> s; Node *pRoot = rbt; Node *pLast = NULL; while (1) { if (pRoot != nullptr) { s.push(pRoot); pRoot = pRoot->pLChild; } else { if (s.size() == 0) break; pRoot = s.top(); if (pRoot->pRChild != nullptr) { if (pLast != pRoot->pRChild) { pRoot = pRoot->pRChild; } else { if (s.size() == 0) break; s.pop(); pLast = pRoot; cout << pRoot->value << endl; pRoot = nullptr; } } else { if (s.size() == 0) break; s.pop(); pLast = pRoot; cout << pRoot->value << endl; pRoot = nullptr; } } } } }; int main() { { RBT rbt; int a[] = { 16, 3, 7, 11, 9, 26, 18, 14, 15 }; rbt.insert(16); rbt.insert(3); rbt.insert(7); rbt.insert(11); rbt.insert(9); rbt.insert(26); rbt.insert(18); rbt.insert(14); rbt.insert(15); rbt.insert(13); rbt.Delete_Node(16); rbt.Sequence_Traversal(); cout << "-------------" << endl; rbt.LDR(); cout << "-------------" << endl; rbt.LRD_(); } system("pause"); return 0; }