commit 81c191e15f3510c60776d96bdd743fa99a1eb967 Author: Lenyiin <569963146@qq.com> Date: Thu Sep 19 02:07:52 2024 +0800 博客 https://blog.lenyiin.com/rbtree/ 的代码仓库 diff --git a/Linux/AVLTree.hpp b/Linux/AVLTree.hpp new file mode 100644 index 0000000..db9697b --- /dev/null +++ b/Linux/AVLTree.hpp @@ -0,0 +1,352 @@ +#pragma once +#include + +using namespace std; + +namespace Lenyiin +{ + template + struct AVLTreeNode + { + AVLTreeNode *_left; + AVLTreeNode *_right; + AVLTreeNode *_parent; + + int _bf; + pair _kv; + + // 普通构造 + AVLTreeNode(const pair &kv) + : _left(nullptr), _right(nullptr), _parent(nullptr), _bf(0), _kv(kv) + { + } + }; + + template + class AVLTree + { + private: + typedef AVLTreeNode Node; + + public: + bool Insert(const pair &kv) + { + // 1. 先按搜索树的规则进行插入 + if (_root == nullptr) + { + _root = new Node(kv); + return true; + } + + Node *parent = nullptr; + Node *cur = _root; + while (cur) + { + if (cur->_kv.first > kv.first) + { + parent = cur; + cur = cur->_left; + } + else if (cur->_kv.first < kv.first) + { + parent = cur; + cur = cur->_right; + } + else + { + return false; + } + } + + // 找到位置 + cur = new Node(kv); + if (parent->_kv.first > kv.first) + { + parent->_left = cur; + cur->_parent = parent; + } + else + { + parent->_right = cur; + cur->_parent = parent; + } + + // 2. 更新平衡因子 + while (parent) + { + if (cur == parent->_right) + { + parent->_bf++; // 插在右边,平衡因子++ + } + else + { + parent->_bf--; // 插在左边,平衡因子-- + } + + if (parent->_bf == 0) + { + // 说明 parent 所在的子树的高度不变,更新结束 + break; + } + else if (parent->_bf == 1 || parent->_bf == -1) + { + // 说明 parent 所在的子树的高度变了,继续往上更新 + cur = parent; + parent = parent->_parent; + } + else if (parent->_bf == 2 || parent->_bf == -2) + { + // parent 所在的子树出现问题了,需要旋转处理一下 + // 1. 旋转前提是保持它依旧是搜索二叉树 + // 2. 旋转成平衡树 + if (parent->_bf == 2) + { + if (cur->_bf == 1) + { + // 左旋 + RotateL(parent); + } + else if (cur->_bf == -1) + { + // 右左双旋 + RotateRL(parent); + } + } + else if (parent->_bf == -2) + { + if (cur->_bf == -1) + { + // 右旋 + RotateR(parent); + } + else if (cur->_bf == 1) + { + // 左右双旋 + RotateLR(parent); + } + } + + // 旋转完成后, parent 所在的树的高度恢复到了,插入节点前高度 + // 如果是子树,对上一层没有影响,更新结束 + break; + } + } + + return true; + } + + // 左单旋 + void RotateL(Node *parent) + { + Node *ppNode = parent->_parent; + Node *subR = parent->_right; + Node *subRL = subR->_left; + + parent->_right = subRL; + if (subRL) + { + subRL->_parent = parent; + } + subR->_left = parent; + parent->_parent = subR; + + // 1. 原来 parent 是这棵树的根,现在 subR 是根 + if (parent == _root) + { + _root = subR; + subR->_parent = nullptr; + } + // 2. parent 为根的树只是整棵树中的子树,改变链接关系,那么 subR 要顶替他的位置 + else + { + if (ppNode->_left == parent) + { + ppNode->_left = subR; + } + else + { + ppNode->_right = subR; + } + subR->_parent = ppNode; + } + + parent->_bf = subR->_bf = 0; + } + + // 右单旋 + void RotateR(Node *parent) + { + Node *ppNode = parent->_parent; + Node *subL = parent->_left; + Node *subLR = subL->_right; + + parent->_left = subLR; + if (subLR) + { + subLR->_parent = parent; + } + subL->_right = parent; + parent->_parent = subL; + + if (parent == _root) + { + _root = subL; + subL->_parent = nullptr; + } + else + { + if (ppNode->_left == parent) + { + ppNode->_left = subL; + } + else + { + ppNode->_right = subL; + } + subL->_parent = ppNode; + } + parent->_bf = subL->_bf = 0; + } + + // 右左双旋 + void RotateRL(Node *parent) + { + Node *subR = parent->_right; + Node *subRL = subR->_left; + int bf = subRL->_bf; + + RotateR(parent->_right); + RotateL(parent); + + if (bf == -1) + { + parent->_bf = 0; + subR->_bf = 1; + subRL->_bf = 0; + } + else if (bf == 1) + { + parent->_bf = -1; + subR->_bf = 0; + subRL->_bf = 0; + } + else if (bf == 0) + { + parent->_bf = 0; + subR->_bf = 0; + subRL->_bf = 0; + } + } + + // 左右双旋 + void RotateLR(Node *parent) + { + Node *subL = parent->_left; + Node *subLR = subL->_right; + int bf = subLR->_bf; + + RotateL(subL); + RotateR(parent); + + if (bf == 1) + { + parent->_bf = 0; + subL->_bf = -1; + subLR->_bf = 0; + } + else if (bf == -1) + { + parent->_bf = 1; + subL->_bf = 0; + subLR->_bf = 0; + } + else if (bf == 0) + { + parent->_bf = 0; + subL->_bf = 0; + subLR->_bf = 0; + } + } + + // 中序遍历 + void _InOrder(Node *root) + { + if (root == nullptr) + { + return; + } + + _InOrder(root->_left); + cout << root->_kv.first << ":" << root->_kv.second << endl; + _InOrder(root->_right); + } + + void InOrder() + { + _InOrder(_root); + cout << endl; + } + + // 获取树的高度 + int Height(Node *root) + { + if (root == nullptr) + { + return 0; + } + + int leftHeight = Height(root->_left); + int rightHeight = Height(root->_right); + + return leftHeight > rightHeight ? leftHeight + 1 : rightHeight + 1; + } + + // 判断是否是平衡二叉树 + bool _IsBalance(Node *root) + { + if (root == nullptr) + { + return true; + } + + int leftHeight = Height(root->_left); + int rightHeight = Height(root->_right); + if (abs(leftHeight - rightHeight) > 1) + { + return false; + } + + return _IsBalance(root->_left) && _IsBalance(root->_right); + } + + bool IsBalance() + { + return _IsBalance(_root); + } + + // 查找 + Node *Find(const Node *root) + { + Node *cur = _root; + while (cur) + { + if (cur->_kv.first > root->_kv.first) + { + cur = cur->_left; + } + else if (cur->_kv.first < root->_kv.first) + { + cur = cur->_right; + } + else + { + return cur; + } + } + return nullptr; + } + + private: + Node *_root = nullptr; + }; +} \ No newline at end of file diff --git a/Linux/Main.cc b/Linux/Main.cc new file mode 100644 index 0000000..696dedf --- /dev/null +++ b/Linux/Main.cc @@ -0,0 +1,100 @@ +#include "RBTree.hpp" +#include "AVLTree.hpp" + +using namespace Lenyiin; + +void test_RBTree() +{ + // int a[] = {16, 3, 7, 11, 9, 26, 18, 14, 15}; + int a[] = {4, 2, 6, 1, 3, 5, 15, 7, 16, 14}; + RBTree t; + for (const auto &e : a) + { + t.Insert(std::make_pair(e, e)); + } + + t.PreOrder(); + t.InOrder(); + t.PostOrder(); + t.LevelOrder(); + + std::cout << "IsRBTree ? " << t.IsRBTree() << std::endl; + + auto node = t.Find(5); + if (node != nullptr) + { + std::cout << node->_kv.first << std::endl; + } + else + { + std::cout << "没找到" << std::endl; + } + + auto pre = t.FindPredecessor(node); + if (pre != nullptr) + { + std::cout << node->_kv.first << " 的前驱节点是: " << pre->_kv.first << std::endl; + } + else + { + std::cout << "前驱节点为空" << std::endl; + } + + auto suc = t.FindSuccessor(node); + if (suc != nullptr) + { + std::cout << node->_kv.first << " 的后继节点是: " << suc->_kv.first << std::endl; + } + else + { + std::cout << "后继节点为空" << std::endl; + } + + t.Erase(7); + t.LevelOrder(); + std::cout << "IsRBTree ? " << t.IsRBTree() << std::endl; + + t.Erase(15); + t.LevelOrder(); + std::cout << "IsRBTree ? " << t.IsRBTree() << std::endl; +} + +void testRB_AVLTree() +{ + const int n = 100000; + std::vector v; + v.reserve(n); + srand(time(0)); + for (size_t i = 0; i < n; i++) + { + v.push_back(rand()); + } + + RBTree rbtree; + AVLTree avltree; + + size_t begin1 = clock(); + for (const auto &e : v) + { + rbtree.Insert(std::make_pair(e, e)); + } + size_t end1 = clock(); + + size_t begin2 = clock(); + for (const auto &e : v) + { + avltree.Insert(std::make_pair(e, e)); + } + size_t end2 = clock(); + + std::cout << "红黑树测试时间:" << end1 - begin1 << std::endl; + std::cout << "AVL 测试时间:\t" << end2 - begin2 << std::endl; +} + +int main() +{ + test_RBTree(); + testRB_AVLTree(); + + return 0; +} \ No newline at end of file diff --git a/Linux/Makefile b/Linux/Makefile new file mode 100644 index 0000000..cd6faa6 --- /dev/null +++ b/Linux/Makefile @@ -0,0 +1,6 @@ +main:Main.cc + g++ -o $@ $^ + +.PHONY:clean +clean: + rm -f main \ No newline at end of file diff --git a/Linux/RBTree.hpp b/Linux/RBTree.hpp new file mode 100644 index 0000000..15a3e2c --- /dev/null +++ b/Linux/RBTree.hpp @@ -0,0 +1,846 @@ +#pragma once + +#include +#include +#include +#include + +namespace Lenyiin +{ + enum Colour + { + RED, + BLACK + }; + + template + struct RBTreeNode + { + RBTreeNode *_left; + RBTreeNode *_right; + RBTreeNode *_parent; + + std::pair _kv; + Colour _colour; + + RBTreeNode(const std::pair &kv) + : _left(nullptr), _right(nullptr), _parent(nullptr), _kv(kv), _colour(RED) + { + } + }; + + template + class RBTree + { + private: + typedef RBTreeNode Node; + + // 左单旋 + void RotateL(Node *parent) + { + Node *ppNode = parent->_parent; + Node *subR = parent->_right; + Node *subRL = subR->_left; + + parent->_right = subRL; + if (subRL) + { + subRL->_parent = parent; + } + subR->_left = parent; + parent->_parent = subR; + + // 1. 原来 parent 是这棵树的根, 现在 subR 是根 + if (parent == _root) + { + _root = subR; + subR->_parent = nullptr; + } + // 2. parent 为根的树只是整棵树中的子树, 改变链接关系, 那么 subR 要顶替他的位置 + else + { + if (ppNode->_left == parent) + { + ppNode->_left = subR; + } + else + { + ppNode->_right = subR; + } + subR->_parent = ppNode; + } + } + + // 右单旋 + void RotateR(Node *parent) + { + Node *ppNode = parent->_parent; + Node *subL = parent->_left; + Node *subLR = subL->_right; + + parent->_left = subLR; + if (subLR) + { + subLR->_parent = parent; + } + subL->_right = parent; + parent->_parent = subL; + + if (parent == _root) + { + _root = subL; + subL->_parent = nullptr; + } + else + { + if (ppNode->_left == parent) + { + ppNode->_left = subL; + } + else + { + ppNode->_right = subL; + } + subL->_parent = ppNode; + } + } + + // 删除整个红黑树 + void DeleteTree(Node *root) + { + if (root == nullptr) + { + return; + } + + // 递归删除左子树 + DeleteTree(root->_left); + // 递归删除右子树 + DeleteTree(root->_right); + + // 删除当前节点 + delete root; + } + + public: + RBTree(Node *root = nullptr) + : _root(root) + { + } + + ~RBTree() + { + DeleteTree(_root); + } + + // 1. 空树。插入结点做根,把他变黑。 + // 2. 插入红色节点,他的父亲是黑色的,结束。 + // 3. 插入红色节点,他的父亲是红色的,可以推断他的祖父存在且一定为黑色。关键看叔叔 + // a. 如果叔叔存在且为红,把父亲和叔叔变黑,祖父变红,继续往上处理。 + // b. 如果叔叔存在且为黑,或者不存在。旋转(单旋 or 双旋)+ 变色 + bool Insert(const std::pair &kv) + { + // 1. 按照搜索树的规则进行插入 + // 如果树为空,直接将新节点设为根节点,并染成黑色 + if (_root == nullptr) + { + _root = new Node(kv); + _root->_colour = BLACK; // 根节点是黑色的 + return true; + } + + // 遍历树找到插入位置 + Node *parent = nullptr; + Node *cur = _root; + while (cur) + { + if (cur->_kv.first > kv.first) + { + parent = cur; + cur = cur->_left; + } + else if (cur->_kv.first < kv.first) + { + parent = cur; + cur = cur->_right; + } + else + { + return false; // 待插入的节点已经存在 + } + } + + // 找到位置 插入新节点 + cur = new Node(kv); + if (parent->_kv.first > kv.first) + { + parent->_left = cur; + cur->_parent = parent; + } + else + { + parent->_right = cur; + cur->_parent = parent; + } + + // 插入调整 + InsertFixUp(parent, cur); + + return true; + } + + void InsertFixUp(Node *parent, Node *cur) + { + // 调整结点颜色 + // 新结点给红的还是黑的? 红色 + // 1. 空树。插入结点做根, 把他变黑。 + // 2. 插入红色节点, 他的父亲是黑色的, 结束。 + // 3. 插入红色节点, 他的父亲是红色的, 可以推断他的祖父存在且一定为黑色。关键看叔叔 + // a. 如果叔叔存在且为红, 把父亲和叔叔变黑, 祖父变红, 继续往上处理。 + // b. 如果叔叔存在且为黑, 或者不存在。旋转(单旋 or 双旋)+ 变色 + while (parent && parent->_colour == RED) + { + // 关键看叔叔 + Node *grandfather = parent->_parent; + if (grandfather->_left == parent) + { + Node *uncle = grandfather->_right; + + // 情况1: uncle 存在, 且为红 + if (uncle && uncle->_colour == RED) + { + parent->_colour = uncle->_colour = BLACK; + grandfather->_colour = RED; + + // 继续向上调整 + cur = grandfather; + parent = cur->_parent; + } + // 情况 2 or 情况 3 : uncle 不存在 or uncle 存在且为黑 + else + { + // 情况 3: 双旋 -> 变成单旋 + if (cur == parent->_right) + { + RotateL(parent); + std::swap(parent, cur); + } + + // 第二种情况 (ps: 有可能是第三种情况变过来的) + RotateR(grandfather); + grandfather->_colour = RED; + parent->_colour = BLACK; + + break; + } + } + else + { + Node *uncle = grandfather->_left; + + // 情况1: uncle 存在, 且为红 + if (uncle && uncle->_colour == RED) + { + parent->_colour = BLACK; + uncle->_colour = BLACK; + grandfather->_colour = RED; + + // 继续向上调整 + cur = grandfather; + parent = cur->_parent; + } + // 情况2 or 情况3: uncle 不存在 or uncle 存在且为黑 + else + { + // 情况3: 双旋 -> 变为单旋 + if (cur == parent->_left) + { + RotateR(parent); + std::swap(parent, cur); + } + + // 第二种情况 (ps: 有可能是第三种情况变来的) + RotateL(grandfather); + grandfather->_colour = RED; + parent->_colour = BLACK; + + break; + } + } + } + + // 保证根节点为黑色 + _root->_colour = BLACK; + } + + // 删除操作 + bool Erase(const K &key) + { + // 查找节点 + Node *nodeToDelete = _root; + while (nodeToDelete) + { + if (nodeToDelete->_kv.first > key) + { + nodeToDelete = nodeToDelete->_left; + } + else if (nodeToDelete->_kv.first < key) + { + nodeToDelete = nodeToDelete->_right; + } + else + { + break; // 找到待删除的节点 + } + } + + // 如果未找到节点 + if (nodeToDelete == nullptr) + { + return false; + } + + // 执行删除操作 + Node *parent, *child; + Colour originalColour = nodeToDelete->_colour; + + if (nodeToDelete->_left == nullptr) + { + child = nodeToDelete->_right; + parent = nodeToDelete->_parent; + Transplant(nodeToDelete, nodeToDelete->_right); + } + else if (nodeToDelete->_right == nullptr) + { + child = nodeToDelete->_left; + parent = nodeToDelete->_parent; + Transplant(nodeToDelete, nodeToDelete->_left); + } + else + { + Node *successor = Minimum(nodeToDelete->_right); + originalColour = successor->_colour; + child = successor->_right; + if (successor->_parent == nodeToDelete) + { + parent = successor; + } + else + { + Transplant(successor, successor->_right); + successor->_right = nodeToDelete->_right; + successor->_right->_parent = successor; + parent = successor->_parent; + } + Transplant(nodeToDelete, successor); + successor->_left = nodeToDelete->_left; + successor->_left->_parent = successor; + successor->_colour = nodeToDelete->_colour; + } + + delete nodeToDelete; + + // 如果删除的节点是黑色,需要进行调整 + if (originalColour == BLACK) + { + EraseFixUp(child, parent); + } + + return true; + } + + void EraseFixUp(Node *x, Node *parent) + { + while (x != _root && (x == nullptr || x->_colour == BLACK)) + { + if (x == parent->_left) + { + Node *w = parent->_right; + // 情况1: x的兄弟节点w是红色的 + if (w->_colour == RED) + { + w->_colour = BLACK; + parent->_colour = RED; + RotateL(parent); + w = parent->_right; + } + // 情况2: x的兄弟节点w是黑色的,且w的两个子节点都是黑色的 + if ((w->_left == nullptr || w->_left->_colour == BLACK) && + (w->_right == nullptr || w->_right->_colour == BLACK)) + { + w->_colour = RED; + x = parent; + parent = x->_parent; + } + else + { + // 情况3: w是黑色的,并且w的左子节点是红色,右子节点是黑色 + if (w->_right == nullptr || w->_right->_colour == BLACK) + { + if (w->_left) + w->_left->_colour = BLACK; + w->_colour = RED; + RotateR(w); + w = parent->_right; + } + // 情况4: w是黑色的,并且w的右子节点是红色 + if (w) + { + w->_colour = parent->_colour; + parent->_colour = BLACK; + if (w->_right) + w->_right->_colour = BLACK; + RotateL(parent); + } + x = _root; + break; + } + } + else + { + Node *w = parent->_left; + // 情况1: x的兄弟节点w是红色的 + if (w->_colour == RED) + { + w->_colour = BLACK; + parent->_colour = RED; + RotateR(parent); + w = parent->_left; + } + // 情况2: x的兄弟节点w是黑色的,且w的两个子节点都是黑色的 + if ((w->_left == nullptr || w->_left->_colour == BLACK) && + (w->_right == nullptr || w->_right->_colour == BLACK)) + { + w->_colour = RED; + x = parent; + parent = x->_parent; + } + else + { + // 情况3: w是黑色的,并且w的右子节点是红色,左子节点是黑色 + if (w->_left == nullptr || w->_left->_colour == BLACK) + { + if (w->_right) + { + w->_right->_colour = BLACK; + } + w->_colour = RED; + RotateL(w); + w = parent->_left; + } + // 情况4: w是黑色的,并且w的左子节点是红色 + if (w) + { + w->_colour = parent->_colour; + parent->_colour = BLACK; + if (w->_left) + { + w->_left->_colour = BLACK; + } + RotateR(parent); + } + x = _root; + break; + } + } + } + + if (x) + { + x->_colour = BLACK; + } + } + + Node *Minimum(Node *node) + { + while (node->_left != nullptr) + { + node = node->_left; + } + return node; + } + + void Transplant(Node *u, Node *v) + { + if (u->_parent == nullptr) + { + _root = v; + } + else if (u == u->_parent->_left) + { + u->_parent->_left = v; + } + else + { + u->_parent->_right = v; + } + + if (v != nullptr) + { + v->_parent = u->_parent; + } + } + + // 查找节点 + Node *Find(const K &key) + { + Node *cur = _root; + while (cur) + { + if (cur->_kv.first > key) + { + cur = cur->_left; + } + else if (cur->_kv.first < key) + { + cur = cur->_right; + } + else + { + return cur; + } + } + return nullptr; + } + + // 前序遍历的递归实现 + // 辅助函数 + // void _PreOrder(Node *root) + // { + // if (root == nullptr) + // { + // return; + // } + + // // 访问根节点 + // std::cout << root->_kv.first << " (" << (root->_colour == RED ? "RED" : "BLACK") << ") "; + // _PreOrder(root->_left); // 访问左子树 + // _PreOrder(root->_right); // 访问右子树 + // } + + // void PreOrder() + // { + // std::cout << "前序遍历: "; + // _PreOrder(_root); + // std::cout << std::endl; + // } + + // 前序遍历的非递归实现 + void PreOrder() + { + if (_root == nullptr) + { + return; + } + + std::stack stack; + stack.push(_root); + + std::cout << "前序遍历: "; + while (!stack.empty()) + { + Node *cur = stack.top(); + stack.pop(); + // 访问根节点 + std::cout << cur->_kv.first << " (" << (cur->_colour == RED ? "RED" : "BLACK") << ") "; + + // 先压入右子树再压入左子树(确保左子树先处理) + if (cur->_right != nullptr) + { + stack.push(cur->_right); + } + if (cur->_left != nullptr) + { + stack.push(cur->_left); + } + } + std::cout << std::endl; + } + + // 中序遍历 + // void _InOrder(Node *root) + // { + // if (root == nullptr) + // { + // return; + // } + + // _InOrder(root->_left); + // // 访问根节点 + // std::cout << root->_kv.first << " (" << (root->_colour == RED ? "RED" : "BLACK") << ") "; + // _InOrder(root->_right); + // } + + // void InOrder() + // { + // std::cout << "中序遍历: "; + // _InOrder(_root); + // std::cout << std::endl; + // } + + // 中序遍历 非递归 + void InOrder() + { + std::stack stack; + Node *cur = _root; + + std::cout << "中序遍历: "; + while (cur != nullptr || !stack.empty()) + { + // 找到最左边的节点 + while (cur != nullptr) + { + stack.push(cur); + cur = cur->_left; + } + + // 处理当前节点 + cur = stack.top(); + stack.pop(); + // 访问根节点 + std::cout << cur->_kv.first << " (" << (cur->_colour == RED ? "RED" : "BLACK") << ") "; + + // 转向右子树 + cur = cur->_right; + } + std::cout << std::endl; + } + + // 后序遍历的递归实现 + // 辅助函数 + // void _PostOrder(Node *root) + // { + // if (root == nullptr) + // { + // return; + // } + + // _PostOrder(root->_left); // 访问左子树 + // _PostOrder(root->_right); // 访问右子树 + // // 访问根节点 + // std::cout << root->_kv.first << " (" << (root->_colour == RED ? "RED" : "BLACK") << ") "; + // } + + // void PostOrder() + // { + // std::cout << "后序遍历: "; + // _PostOrder(_root); + // std::cout << std::endl; + // } + + // 后序遍历的非递归实现 + void PostOrder() + { + if (_root == nullptr) + { + return; + } + + std::stack st; + Node *cur = _root; + Node *lastNode = nullptr; // 最近访问的节点 + std::cout << "后序遍历: "; + while (cur || !st.empty()) + { + while (cur) + { + st.push(cur); + cur = cur->_left; + } + + Node *top = st.top(); + if ((top->_right == nullptr) || (lastNode == top->_right)) + { + // 访问当前节点 + std::cout << top->_kv.first << " (" << (top->_colour == RED ? "RED" : "BLACK") << ") "; + lastNode = top; + st.pop(); + } + else + { + cur = top->_right; + } + } + std::cout << std::endl; + } + + // 层序遍历 + void LevelOrder() + { + if (_root == nullptr) + { + return; + } + + std::queue queue; + queue.push(_root); + + std::cout << "层序遍历: " << std::endl; + while (!queue.empty()) + { + int size = queue.size(); + while (size--) + { + Node *cur = queue.front(); + queue.pop(); + // 访问当前节点 + std::cout << cur->_kv.first << " (" << (cur->_colour == RED ? "RED" : "BLACK") << ") "; + + if (cur->_left != nullptr) + { + queue.push(cur->_left); // 将左子树压入队列 + } + if (cur->_right != nullptr) + { + queue.push(cur->_right); // 将右子树压入队列 + } + } + std::cout << std::endl; + } + std::cout << std::endl; + } + + // 查找后继节点 + Node *findMin(Node *node) + { + while (node->_left != nullptr) + { + node = node->_left; + } + return node; + } + + Node *FindSuccessor(Node *node) + { + if (node->_right != nullptr) + { + return findMin(node->_right); + } + + Node *cur = _root; + Node *successor = nullptr; + while (cur != nullptr) + { + if (node->_kv.first < cur->_kv.first) + { + successor = cur; + cur = cur->_left; + } + else if (node->_kv.first > cur->_kv.first) + { + cur = cur->_right; + } + else + { + break; + } + } + return successor; + } + + // 查找前驱节点 + Node *findMax(Node *node) + { + while (node->_right != nullptr) + { + node = node->_right; + } + return node; + } + + Node *FindPredecessor(Node *node) + { + if (node->_left != nullptr) + { + return findMax(node->_left); + } + + Node *cur = _root; + Node *predecessor = nullptr; + while (cur != nullptr) + { + if (node->_kv.first < cur->_kv.first) + { + cur = cur->_left; + } + else if (node->_kv.first > cur->_kv.first) + { + predecessor = cur; + cur = cur->_right; + } + else + { + break; + } + } + return predecessor; + } + + // 判断是否是红黑树 + bool IsRBTree() + { + // 空树也是红黑树 + if (_root == nullptr) + { + return true; + } + + // 1. 根是黑色 + if (_root->_colour != BLACK) + { + std::cout << "根节点不是黑色" << std::endl; + return false; + } + + // 获取任意一条路径上黑色节点的数量 + size_t blackCount = 0; + Node *cur = _root; + while (cur) + { + if (cur->_colour == BLACK) + { + blackCount++; + } + cur = cur->_left; + } + + // 判断是否满足红黑树的性质, k 用来记录路径中黑色节点的个数 + size_t k = 0; + return _IsRBTree(_root, k, blackCount); + } + + bool _IsRBTree(Node *root, size_t k, size_t blackCount) + { + // 走到 nullptr 之后, 判断 k 和 blackCount 是否相等 + if (root == nullptr) + { + // 最终黑色节点个数 + if (blackCount != k) + { + std::cout << "违反性质四: 每条路径中黑色节点的个数必须相等" << std::endl; + return false; + } + return true; + } + + // 统计黑色节点个数 + if (root->_colour == BLACK) + { + k++; + } + + // 检测当前节点与其父亲节点是否都为红色 + Node *parent = root->_parent; + if (parent && parent->_colour == RED && root->_colour == RED) + { + std::cout << "违反了性质三: 红色节点的孩子必须是黑色" << std::endl; + return false; + } + + return _IsRBTree(root->_left, k, blackCount) && _IsRBTree(root->_right, k, blackCount); + } + + private: + Node *_root; + }; +} \ No newline at end of file diff --git a/Linux/main b/Linux/main new file mode 100644 index 0000000..b6304e5 Binary files /dev/null and b/Linux/main differ diff --git a/Windows_RBTree/.vs/Windows_RBTree/FileContentIndex/1b38c67f-c22c-4867-9077-9a4f8c40279c.vsidx b/Windows_RBTree/.vs/Windows_RBTree/FileContentIndex/1b38c67f-c22c-4867-9077-9a4f8c40279c.vsidx new file mode 100644 index 0000000..4b587fc Binary files /dev/null and b/Windows_RBTree/.vs/Windows_RBTree/FileContentIndex/1b38c67f-c22c-4867-9077-9a4f8c40279c.vsidx differ diff --git a/Windows_RBTree/.vs/Windows_RBTree/FileContentIndex/5b59df87-c407-4a5f-bf1d-88aaff741cd0.vsidx b/Windows_RBTree/.vs/Windows_RBTree/FileContentIndex/5b59df87-c407-4a5f-bf1d-88aaff741cd0.vsidx new file mode 100644 index 0000000..faf8ee7 Binary files /dev/null and b/Windows_RBTree/.vs/Windows_RBTree/FileContentIndex/5b59df87-c407-4a5f-bf1d-88aaff741cd0.vsidx differ diff --git a/Windows_RBTree/.vs/Windows_RBTree/FileContentIndex/aabd876c-f266-4362-bd2b-af81b54715f4.vsidx b/Windows_RBTree/.vs/Windows_RBTree/FileContentIndex/aabd876c-f266-4362-bd2b-af81b54715f4.vsidx new file mode 100644 index 0000000..b501cff Binary files /dev/null and b/Windows_RBTree/.vs/Windows_RBTree/FileContentIndex/aabd876c-f266-4362-bd2b-af81b54715f4.vsidx differ diff --git a/Windows_RBTree/.vs/Windows_RBTree/FileContentIndex/e9508898-ea9c-42fc-a2f7-193c370f1a41.vsidx b/Windows_RBTree/.vs/Windows_RBTree/FileContentIndex/e9508898-ea9c-42fc-a2f7-193c370f1a41.vsidx new file mode 100644 index 0000000..00f74d2 Binary files /dev/null and b/Windows_RBTree/.vs/Windows_RBTree/FileContentIndex/e9508898-ea9c-42fc-a2f7-193c370f1a41.vsidx differ diff --git a/Windows_RBTree/.vs/Windows_RBTree/v17/.suo b/Windows_RBTree/.vs/Windows_RBTree/v17/.suo new file mode 100644 index 0000000..31c43e0 Binary files /dev/null and b/Windows_RBTree/.vs/Windows_RBTree/v17/.suo differ diff --git a/Windows_RBTree/.vs/Windows_RBTree/v17/Browse.VC.db b/Windows_RBTree/.vs/Windows_RBTree/v17/Browse.VC.db new file mode 100644 index 0000000..d34fe8a Binary files /dev/null and b/Windows_RBTree/.vs/Windows_RBTree/v17/Browse.VC.db differ diff --git a/Windows_RBTree/.vs/Windows_RBTree/v17/ipch/AutoPCH/b04414422c149ba9/RBTREE.ipch b/Windows_RBTree/.vs/Windows_RBTree/v17/ipch/AutoPCH/b04414422c149ba9/RBTREE.ipch new file mode 100644 index 0000000..6637ab1 Binary files /dev/null and b/Windows_RBTree/.vs/Windows_RBTree/v17/ipch/AutoPCH/b04414422c149ba9/RBTREE.ipch differ diff --git a/Windows_RBTree/AVLTree.hpp b/Windows_RBTree/AVLTree.hpp new file mode 100644 index 0000000..54f3b00 --- /dev/null +++ b/Windows_RBTree/AVLTree.hpp @@ -0,0 +1,612 @@ +#pragma once + +#include +#include +#include + +namespace Lenyiin +{ + template + struct AVLTreeNode + { + AVLTreeNode* _left; + AVLTreeNode* _right; + AVLTreeNode* _parent; + + int _bf; // balance factor ƽ + std::pair _kv; // key-value + + // ͨ + AVLTreeNode(const std::pair& kv) + : _left(nullptr), _right(nullptr), _parent(nullptr), _bf(0), _kv(kv) + { + } + }; + + template + class AVLTree + { + private: + typedef AVLTreeNode Node; + + public: + bool Insert(const std::pair& kv) + { + // 1. ȰĹв + if (_root == nullptr) + { + _root = new Node(kv); + return true; + } + + Node* parent = nullptr; + Node* cur = _root; + while (cur) + { + if (cur->_kv.first > kv.first) + { + parent = cur; + cur = cur->_left; + } + else if (cur->_kv.first < kv.first) + { + parent = cur; + cur = cur->_right; + } + else + { + return false; // , ʾѾ, Ҫ + } + } + + // ҵλ + cur = new Node(kv); + if (parent->_kv.first > kv.first) + { + parent->_left = cur; + cur->_parent = parent; + } + else + { + parent->_right = cur; + cur->_parent = parent; + } + + // 2. ƽ + while (parent) + { + if (cur == parent->_right) + { + parent->_bf++; // ұ, ƽ++ + } + else + { + parent->_bf--; // , ƽ-- + } + + if (parent->_bf == 0) + { + // ˵ parent ڵ߶Ȳ, ½ + break; + } + else if (parent->_bf == 1 || parent->_bf == -1) + { + // ˵ parent ĸ߶ȱ, ϸ + cur = parent; + parent = parent->_parent; + } + else if (parent->_bf == 2 || parent->_bf == -2) + { + // parent ڵ, Ҫתһ + // 1. תǰDZ + // 2. תƽ + if (parent->_bf == 2) + { + if (cur->_bf == 1) + { + // + RotateL(parent); + } + else if (cur->_bf == -1) + { + // ˫ + RotateRL(parent); + } + } + else if (parent->_bf == -2) + { + if (cur->_bf == -1) + { + // + RotateR(parent); + } + else if (cur->_bf == 1) + { + // ˫ + RotateLR(parent); + } + } + + // תɺ, parent ڵĸ߶Ȼָ˲ڵǰĸ߶ + // , һûӰ, ½ + break; + } + } + + return true; + } + + // + void RotateL(Node* parent) + { + Node* ppNode = parent->_parent; + Node* subR = parent->_right; + Node* subRL = subR->_left; + + parent->_right = subRL; + if (subRL) + { + subRL->_parent = parent; + } + subR->_left = parent; + parent->_parent = subR; + + // 1. ԭ parent ĸ, subR Ǹ + if (parent == _root) + { + _root = subR; + subR->_parent = nullptr; + } + // 2. parent Ϊֻе, ıӹϵ, ô subR Ҫλ + else + { + if (ppNode->_left == parent) + { + ppNode->_left = subR; + } + else + { + ppNode->_right = subR; + } + subR->_parent = ppNode; + } + + parent->_bf = subR->_bf = 0; + } + + // ҵ + void RotateR(Node* parent) + { + Node* ppNode = parent->_parent; + Node* subL = parent->_left; + Node* subLR = subL->_right; + + parent->_left = subLR; + if (subLR) + { + subLR->_parent = parent; + } + subL->_right = parent; + parent->_parent = subL; + + if (parent == _root) + { + _root = subL; + subL->_parent = nullptr; + } + else + { + if (ppNode->_left == parent) + { + ppNode->_left = subL; + } + else + { + ppNode->_right = subL; + } + subL->_parent = ppNode; + } + + parent->_bf = subL->_bf = 0; + } + + // ˫ + void RotateRL(Node* parent) + { + Node* subR = parent->_right; + Node* subRL = subR->_left; + int bf = subRL->_bf; + + RotateR(parent->_right); + RotateL(parent); + + if (bf == -1) + { + parent->_bf = 0; + subR->_bf = 1; + subRL->_bf = 0; + } + else if (bf == 1) + { + parent->_bf = -1; + subR->_bf = 0; + subRL->_bf = 0; + } + else if (bf == 0) + { + parent->_bf = 0; + subR->_bf = 0; + subRL->_bf = 0; + } + } + + // ˫ + void RotateLR(Node* parent) + { + Node* subL = parent->_left; + Node* subLR = subL->_right; + int bf = subLR->_bf; + + RotateL(subL); + RotateR(parent); + + if (bf == 1) + { + parent->_bf = 0; + subL->_bf = -1; + subLR->_bf = 0; + } + else if (bf == -1) + { + parent->_bf = 1; + subL->_bf = 0; + subLR->_bf = 0; + } + else if (bf == 0) + { + parent->_bf = 0; + subL->_bf = 0; + subLR->_bf = 0; + } + } + + // + // void _InOrder(Node* root) + //{ + // if (root == nullptr) + // { + // return; + // } + + // _InOrder(root->_left); + // std::cout << root->_kv.first << ":" << root->_kv.second << std::endl; + // _InOrder(root->_right); + //} + + // void InOrder() + //{ + // _InOrder(_root); + // std::cout << std::endl; + // } + + // ǵݹ + void InOrder() + { + std::stack stack; + Node* cur = _root; + + while (cur != nullptr || !stack.empty()) + { + // ҵߵĽڵ + while (cur != nullptr) + { + stack.push(cur); + cur = cur->_left; + } + + // ǰڵ + cur = stack.top(); + stack.pop(); + std::cout << cur->_kv.first << ":" << cur->_kv.second << std::endl; + + // ת + cur = cur->_right; + } + std::cout << std::endl; + } + + // ǰĵݹʵ + // + // void _PreOrder(Node* root) + //{ + // if (root == nullptr) + // { + // return; + // } + + // std::cout << root->_kv.first << ":" << root->_kv.second << std::endl; // ʸڵ + // _PreOrder(root->_left); // + // _PreOrder(root->_right); // + //} + + // void PreOrder() + //{ + // _PreOrder(_root); + // std::cout << std::endl; + // } + + // ǰķǵݹʵ + void PreOrder() + { + if (_root == nullptr) + { + return; + } + + std::stack stack; + stack.push(_root); + + while (!stack.empty()) + { + Node* cur = stack.top(); + stack.pop(); + std::cout << cur->_kv.first << ":" << cur->_kv.second << std::endl; // ʵǰڵ + + // ѹѹȷȴ + if (cur->_right != nullptr) + { + stack.push(cur->_right); + } + if (cur->_left != nullptr) + { + stack.push(cur->_left); + } + } + std::cout << std::endl; + } + + // ĵݹʵ + // + // void _PostOrder(Node* root) { + // if (root == nullptr) + // { + // return; + // } + + // _PostOrder(root->_left); // + // _PostOrder(root->_right); // + // std::cout << root->_kv.first << ":" << root->_kv.second << std::endl; // ʸڵ + //} + + // void PostOrder() + //{ + // _PostOrder(_root); + // std::cout << std::endl; + // } + + // ķǵݹʵ + void PostOrder() + { + if (_root == nullptr) + { + return; + } + + std::stack st; + Node* cur = _root; + Node* lastNode = nullptr; // ʵĽڵ + while (cur || !st.empty()) + { + while (cur) + { + st.push(cur); + cur = cur->_left; + } + + Node* top = st.top(); + if ((top->_right == nullptr) || (lastNode == top->_right)) + { + std::cout << top->_kv.first << ":" << top->_kv.second << std::endl; + lastNode = top; + st.pop(); + } + else + { + cur = top->_right; + } + } + std::cout << std::endl; + } + + // + void LevelOrder() + { + if (_root == nullptr) + { + return; + } + + std::queue queue; + queue.push(_root); + + while (!queue.empty()) + { + Node* cur = queue.front(); + queue.pop(); + std::cout << cur->_kv.first << ":" << cur->_kv.second << std::endl; // ʵǰڵ + + if (cur->_left != nullptr) + { + queue.push(cur->_left); // ѹ + } + if (cur->_right != nullptr) + { + queue.push(cur->_right); // ѹ + } + } + std::cout << std::endl; + } + + // Һ̽ڵ + Node* findMin(Node* node) + { + while (node->_left != nullptr) + { + node = node->_left; + } + return node; + } + + Node* FindSuccessor(Node* node) + { + if (node->_right != nullptr) + { + return findMin(node->_right); + } + + Node* cur = _root; + Node* successor = nullptr; + while (cur != nullptr) + { + if (node->_kv.first < cur->_kv.first) + { + successor = cur; + cur = cur->_left; + } + else if (node->_kv.first > cur->_kv.first) + { + cur = cur->_right; + } + else + { + break; + } + } + return successor; + } + + // ǰڵ + Node* findMax(Node* node) + { + while (node->_right != nullptr) + { + node = node->_right; + } + return node; + } + + Node* FindPredecessor(Node* node) + { + if (node->_left != nullptr) + { + return findMax(node->_left); + } + + Node* cur = _root; + Node* predecessor = nullptr; + while (cur != nullptr) + { + if (node->_kv.first < cur->_kv.first) + { + cur = cur->_left; + } + else if (node->_kv.first > cur->_kv.first) + { + predecessor = cur; + cur = cur->_right; + } + else + { + break; + } + } + return predecessor; + } + + // ȡĸ߶ + int Height(Node* root) + { + if (root == nullptr) + { + return 0; + } + + int leftHeight = Height(root->_left); + int rightHeight = Height(root->_right); + + return leftHeight > rightHeight ? leftHeight + 1 : rightHeight + 1; + } + + // жǷƽ + bool _IsBalance(Node* root) + { + if (root == nullptr) + { + return true; + } + + int leftHeight = Height(root->_left); + int rightHeight = Height(root->_right); + if (abs(leftHeight - rightHeight) > 1) + { + return false; + } + + return _IsBalance(root->_left) && _IsBalance(root->_right); + } + + bool IsBalance() + { + return _IsBalance(_root); + } + + // ǵݹ + // Node* Find(const K& key) + //{ + // Node* cur = _root; + // while (cur) + // { + // if (cur->_kv.first > key) + // { + // cur = cur->_left; + // } + // else if (cur->_kv.first < key) + // { + // cur = cur->_right; + // } + // else + // { + // return cur; + // } + // } + // return nullptr; + //} + + // ҵĵݹʵ + // + Node* _find(Node* root, const K& key) + { + if (root == nullptr || root->_kv.first == key) + { + return root; + } + if (key < root->_kv.first) + { + return _find(root->_left, key); + } + else + { + return _find(root->_right, key); + } + } + + // ҽڵ + Node* Find(const K& key) + { + return _find(_root, key); + } + + private: + Node* _root = nullptr; + }; +} \ No newline at end of file diff --git a/Windows_RBTree/RBTree.cpp b/Windows_RBTree/RBTree.cpp new file mode 100644 index 0000000..53ba662 --- /dev/null +++ b/Windows_RBTree/RBTree.cpp @@ -0,0 +1,100 @@ +#include "RBTree.hpp" +#include "AVLTree.hpp" + +using namespace Lenyiin; + +void test_RBTree() +{ + // int a[] = {16, 3, 7, 11, 9, 26, 18, 14, 15}; + int a[] = { 4, 2, 6, 1, 3, 5, 15, 7, 16, 14 }; + RBTree t; + for (const auto& e : a) + { + t.Insert(std::make_pair(e, e)); + } + + t.PreOrder(); + t.InOrder(); + t.PostOrder(); + t.LevelOrder(); + + std::cout << "IsRBTree ? " << t.IsRBTree() << std::endl; + + auto node = t.Find(5); + if (node != nullptr) + { + std::cout << node->_kv.first << std::endl; + } + else + { + std::cout << "ûҵ" << std::endl; + } + + auto pre = t.FindPredecessor(node); + if (pre != nullptr) + { + std::cout << node->_kv.first << " ǰڵ: " << pre->_kv.first << std::endl; + } + else + { + std::cout << "ǰڵΪ" << std::endl; + } + + auto suc = t.FindSuccessor(node); + if (suc != nullptr) + { + std::cout << node->_kv.first << " ĺ̽ڵ: " << suc->_kv.first << std::endl; + } + else + { + std::cout << "̽ڵΪ" << std::endl; + } + + t.Erase(7); + t.LevelOrder(); + std::cout << "IsRBTree ? " << t.IsRBTree() << std::endl; + + t.Erase(15); + t.LevelOrder(); + std::cout << "IsRBTree ? " << t.IsRBTree() << std::endl; +} + +void testRB_AVLTree() +{ + const int n = 100000; + std::vector v; + v.reserve(n); + srand(time(0)); + for (size_t i = 0; i < n; i++) + { + v.push_back(rand()); + } + + RBTree rbtree; + AVLTree avltree; + + size_t begin1 = clock(); + for (const auto& e : v) + { + rbtree.Insert(std::make_pair(e, e)); + } + size_t end1 = clock(); + + size_t begin2 = clock(); + for (const auto& e : v) + { + avltree.Insert(std::make_pair(e, e)); + } + size_t end2 = clock(); + + std::cout << "ʱ䣺" << end1 - begin1 << std::endl; + std::cout << "AVL ʱ䣺\t" << end2 - begin2 << std::endl; +} + +int main() +{ + test_RBTree(); + testRB_AVLTree(); + + return 0; +} \ No newline at end of file diff --git a/Windows_RBTree/RBTree.hpp b/Windows_RBTree/RBTree.hpp new file mode 100644 index 0000000..b1131a2 --- /dev/null +++ b/Windows_RBTree/RBTree.hpp @@ -0,0 +1,846 @@ +#pragma once + +#include +#include +#include +#include + +namespace Lenyiin +{ + enum Colour + { + RED, + BLACK + }; + + template + struct RBTreeNode + { + RBTreeNode* _left; + RBTreeNode* _right; + RBTreeNode* _parent; + + std::pair _kv; + Colour _colour; + + RBTreeNode(const std::pair& kv) + : _left(nullptr), _right(nullptr), _parent(nullptr), _kv(kv), _colour(RED) + { + } + }; + + template + class RBTree + { + private: + typedef RBTreeNode Node; + + // + void RotateL(Node* parent) + { + Node* ppNode = parent->_parent; + Node* subR = parent->_right; + Node* subRL = subR->_left; + + parent->_right = subRL; + if (subRL) + { + subRL->_parent = parent; + } + subR->_left = parent; + parent->_parent = subR; + + // 1. ԭ parent ĸ, subR Ǹ + if (parent == _root) + { + _root = subR; + subR->_parent = nullptr; + } + // 2. parent Ϊֻе, ıӹϵ, ô subR Ҫλ + else + { + if (ppNode->_left == parent) + { + ppNode->_left = subR; + } + else + { + ppNode->_right = subR; + } + subR->_parent = ppNode; + } + } + + // ҵ + void RotateR(Node* parent) + { + Node* ppNode = parent->_parent; + Node* subL = parent->_left; + Node* subLR = subL->_right; + + parent->_left = subLR; + if (subLR) + { + subLR->_parent = parent; + } + subL->_right = parent; + parent->_parent = subL; + + if (parent == _root) + { + _root = subL; + subL->_parent = nullptr; + } + else + { + if (ppNode->_left == parent) + { + ppNode->_left = subL; + } + else + { + ppNode->_right = subL; + } + subL->_parent = ppNode; + } + } + + // ɾ + void DeleteTree(Node* root) + { + if (root == nullptr) + { + return; + } + + // ݹɾ + DeleteTree(root->_left); + // ݹɾ + DeleteTree(root->_right); + + // ɾǰڵ + delete root; + } + + public: + RBTree(Node* root = nullptr) + : _root(root) + { + } + + ~RBTree() + { + DeleteTree(_root); + } + + // 1. ڡ + // 2. ɫڵ㣬ĸǺɫģ + // 3. ɫڵ㣬ĸǺɫģƶ游һΪɫؼ + // a. Ϊ죬Ѹ׺ڣ游죬ϴ + // b. Ϊڣ߲ڡת or ˫+ ɫ + bool Insert(const std::pair& kv) + { + // 1. Ĺв + // Ϊգֱӽ½ڵΪڵ㣬Ⱦɺɫ + if (_root == nullptr) + { + _root = new Node(kv); + _root->_colour = BLACK; // ڵǺɫ + return true; + } + + // ҵλ + Node* parent = nullptr; + Node* cur = _root; + while (cur) + { + if (cur->_kv.first > kv.first) + { + parent = cur; + cur = cur->_left; + } + else if (cur->_kv.first < kv.first) + { + parent = cur; + cur = cur->_right; + } + else + { + return false; // ĽڵѾ + } + } + + // ҵλ ½ڵ + cur = new Node(kv); + if (parent->_kv.first > kv.first) + { + parent->_left = cur; + cur->_parent = parent; + } + else + { + parent->_right = cur; + cur->_parent = parent; + } + + // + InsertFixUp(parent, cur); + + return true; + } + + void InsertFixUp(Node* parent, Node* cur) + { + // ɫ + // ½ĻǺڵ? ɫ + // 1. , ڡ + // 2. ɫڵ, ĸǺɫ, + // 3. ɫڵ, ĸǺɫ, ƶ游һΪɫؼ + // a. Ϊ, Ѹ׺, 游, ϴ + // b. Ϊ, ߲ڡת or ˫+ ɫ + while (parent && parent->_colour == RED) + { + // ؼ + Node* grandfather = parent->_parent; + if (grandfather->_left == parent) + { + Node* uncle = grandfather->_right; + + // 1: uncle , Ϊ + if (uncle && uncle->_colour == RED) + { + parent->_colour = uncle->_colour = BLACK; + grandfather->_colour = RED; + + // ϵ + cur = grandfather; + parent = cur->_parent; + } + // 2 or 3 : uncle or uncle Ϊ + else + { + // 3: ˫ -> ɵ + if (cur == parent->_right) + { + RotateL(parent); + std::swap(parent, cur); + } + + // ڶ (ps: пǵ) + RotateR(grandfather); + grandfather->_colour = RED; + parent->_colour = BLACK; + + break; + } + } + else + { + Node* uncle = grandfather->_left; + + // 1: uncle , Ϊ + if (uncle && uncle->_colour == RED) + { + parent->_colour = BLACK; + uncle->_colour = BLACK; + grandfather->_colour = RED; + + // ϵ + cur = grandfather; + parent = cur->_parent; + } + // 2 or 3: uncle or uncle Ϊ + else + { + // 3: ˫ -> Ϊ + if (cur == parent->_left) + { + RotateR(parent); + std::swap(parent, cur); + } + + // ڶ (ps: пǵ) + RotateL(grandfather); + grandfather->_colour = RED; + parent->_colour = BLACK; + + break; + } + } + } + + // ֤ڵΪɫ + _root->_colour = BLACK; + } + + // ɾ + bool Erase(const K& key) + { + // ҽڵ + Node* nodeToDelete = _root; + while (nodeToDelete) + { + if (nodeToDelete->_kv.first > key) + { + nodeToDelete = nodeToDelete->_left; + } + else if (nodeToDelete->_kv.first < key) + { + nodeToDelete = nodeToDelete->_right; + } + else + { + break; // ҵɾĽڵ + } + } + + // δҵڵ + if (nodeToDelete == nullptr) + { + return false; + } + + // ִɾ + Node* parent, * child; + Colour originalColour = nodeToDelete->_colour; + + if (nodeToDelete->_left == nullptr) + { + child = nodeToDelete->_right; + parent = nodeToDelete->_parent; + Transplant(nodeToDelete, nodeToDelete->_right); + } + else if (nodeToDelete->_right == nullptr) + { + child = nodeToDelete->_left; + parent = nodeToDelete->_parent; + Transplant(nodeToDelete, nodeToDelete->_left); + } + else + { + Node* successor = Minimum(nodeToDelete->_right); + originalColour = successor->_colour; + child = successor->_right; + if (successor->_parent == nodeToDelete) + { + parent = successor; + } + else + { + Transplant(successor, successor->_right); + successor->_right = nodeToDelete->_right; + successor->_right->_parent = successor; + parent = successor->_parent; + } + Transplant(nodeToDelete, successor); + successor->_left = nodeToDelete->_left; + successor->_left->_parent = successor; + successor->_colour = nodeToDelete->_colour; + } + + delete nodeToDelete; + + // ɾĽڵǺɫҪе + if (originalColour == BLACK) + { + EraseFixUp(child, parent); + } + + return true; + } + + void EraseFixUp(Node* x, Node* parent) + { + while (x != _root && (x == nullptr || x->_colour == BLACK)) + { + if (x == parent->_left) + { + Node* w = parent->_right; + // 1: xֵܽڵwǺɫ + if (w->_colour == RED) + { + w->_colour = BLACK; + parent->_colour = RED; + RotateL(parent); + w = parent->_right; + } + // 2: xֵܽڵwǺɫģwӽڵ㶼Ǻɫ + if ((w->_left == nullptr || w->_left->_colour == BLACK) && + (w->_right == nullptr || w->_right->_colour == BLACK)) + { + w->_colour = RED; + x = parent; + parent = x->_parent; + } + else + { + // 3: wǺɫģwӽڵǺɫӽڵǺɫ + if (w->_right == nullptr || w->_right->_colour == BLACK) + { + if (w->_left) + w->_left->_colour = BLACK; + w->_colour = RED; + RotateR(w); + w = parent->_right; + } + // 4: wǺɫģwӽڵǺɫ + if (w) + { + w->_colour = parent->_colour; + parent->_colour = BLACK; + if (w->_right) + w->_right->_colour = BLACK; + RotateL(parent); + } + x = _root; + break; + } + } + else + { + Node* w = parent->_left; + // 1: xֵܽڵwǺɫ + if (w->_colour == RED) + { + w->_colour = BLACK; + parent->_colour = RED; + RotateR(parent); + w = parent->_left; + } + // 2: xֵܽڵwǺɫģwӽڵ㶼Ǻɫ + if ((w->_left == nullptr || w->_left->_colour == BLACK) && + (w->_right == nullptr || w->_right->_colour == BLACK)) + { + w->_colour = RED; + x = parent; + parent = x->_parent; + } + else + { + // 3: wǺɫģwӽڵǺɫӽڵǺɫ + if (w->_left == nullptr || w->_left->_colour == BLACK) + { + if (w->_right) + { + w->_right->_colour = BLACK; + } + w->_colour = RED; + RotateL(w); + w = parent->_left; + } + // 4: wǺɫģwӽڵǺɫ + if (w) + { + w->_colour = parent->_colour; + parent->_colour = BLACK; + if (w->_left) + { + w->_left->_colour = BLACK; + } + RotateR(parent); + } + x = _root; + break; + } + } + } + + if (x) + { + x->_colour = BLACK; + } + } + + Node* Minimum(Node* node) + { + while (node->_left != nullptr) + { + node = node->_left; + } + return node; + } + + void Transplant(Node* u, Node* v) + { + if (u->_parent == nullptr) + { + _root = v; + } + else if (u == u->_parent->_left) + { + u->_parent->_left = v; + } + else + { + u->_parent->_right = v; + } + + if (v != nullptr) + { + v->_parent = u->_parent; + } + } + + // ҽڵ + Node* Find(const K& key) + { + Node* cur = _root; + while (cur) + { + if (cur->_kv.first > key) + { + cur = cur->_left; + } + else if (cur->_kv.first < key) + { + cur = cur->_right; + } + else + { + return cur; + } + } + return nullptr; + } + + // ǰĵݹʵ + // + // void _PreOrder(Node *root) + // { + // if (root == nullptr) + // { + // return; + // } + + // // ʸڵ + // std::cout << root->_kv.first << " (" << (root->_colour == RED ? "RED" : "BLACK") << ") "; + // _PreOrder(root->_left); // + // _PreOrder(root->_right); // + // } + + // void PreOrder() + // { + // std::cout << "ǰ: "; + // _PreOrder(_root); + // std::cout << std::endl; + // } + + // ǰķǵݹʵ + void PreOrder() + { + if (_root == nullptr) + { + return; + } + + std::stack stack; + stack.push(_root); + + std::cout << "ǰ: "; + while (!stack.empty()) + { + Node* cur = stack.top(); + stack.pop(); + // ʸڵ + std::cout << cur->_kv.first << " (" << (cur->_colour == RED ? "RED" : "BLACK") << ") "; + + // ѹѹȷȴ + if (cur->_right != nullptr) + { + stack.push(cur->_right); + } + if (cur->_left != nullptr) + { + stack.push(cur->_left); + } + } + std::cout << std::endl; + } + + // + // void _InOrder(Node *root) + // { + // if (root == nullptr) + // { + // return; + // } + + // _InOrder(root->_left); + // // ʸڵ + // std::cout << root->_kv.first << " (" << (root->_colour == RED ? "RED" : "BLACK") << ") "; + // _InOrder(root->_right); + // } + + // void InOrder() + // { + // std::cout << ": "; + // _InOrder(_root); + // std::cout << std::endl; + // } + + // ǵݹ + void InOrder() + { + std::stack stack; + Node* cur = _root; + + std::cout << ": "; + while (cur != nullptr || !stack.empty()) + { + // ҵߵĽڵ + while (cur != nullptr) + { + stack.push(cur); + cur = cur->_left; + } + + // ǰڵ + cur = stack.top(); + stack.pop(); + // ʸڵ + std::cout << cur->_kv.first << " (" << (cur->_colour == RED ? "RED" : "BLACK") << ") "; + + // ת + cur = cur->_right; + } + std::cout << std::endl; + } + + // ĵݹʵ + // + // void _PostOrder(Node *root) + // { + // if (root == nullptr) + // { + // return; + // } + + // _PostOrder(root->_left); // + // _PostOrder(root->_right); // + // // ʸڵ + // std::cout << root->_kv.first << " (" << (root->_colour == RED ? "RED" : "BLACK") << ") "; + // } + + // void PostOrder() + // { + // std::cout << ": "; + // _PostOrder(_root); + // std::cout << std::endl; + // } + + // ķǵݹʵ + void PostOrder() + { + if (_root == nullptr) + { + return; + } + + std::stack st; + Node* cur = _root; + Node* lastNode = nullptr; // ʵĽڵ + std::cout << ": "; + while (cur || !st.empty()) + { + while (cur) + { + st.push(cur); + cur = cur->_left; + } + + Node* top = st.top(); + if ((top->_right == nullptr) || (lastNode == top->_right)) + { + // ʵǰڵ + std::cout << top->_kv.first << " (" << (top->_colour == RED ? "RED" : "BLACK") << ") "; + lastNode = top; + st.pop(); + } + else + { + cur = top->_right; + } + } + std::cout << std::endl; + } + + // + void LevelOrder() + { + if (_root == nullptr) + { + return; + } + + std::queue queue; + queue.push(_root); + + std::cout << ": " << std::endl; + while (!queue.empty()) + { + int size = queue.size(); + while (size--) + { + Node* cur = queue.front(); + queue.pop(); + // ʵǰڵ + std::cout << cur->_kv.first << " (" << (cur->_colour == RED ? "RED" : "BLACK") << ") "; + + if (cur->_left != nullptr) + { + queue.push(cur->_left); // ѹ + } + if (cur->_right != nullptr) + { + queue.push(cur->_right); // ѹ + } + } + std::cout << std::endl; + } + std::cout << std::endl; + } + + // Һ̽ڵ + Node* findMin(Node* node) + { + while (node->_left != nullptr) + { + node = node->_left; + } + return node; + } + + Node* FindSuccessor(Node* node) + { + if (node->_right != nullptr) + { + return findMin(node->_right); + } + + Node* cur = _root; + Node* successor = nullptr; + while (cur != nullptr) + { + if (node->_kv.first < cur->_kv.first) + { + successor = cur; + cur = cur->_left; + } + else if (node->_kv.first > cur->_kv.first) + { + cur = cur->_right; + } + else + { + break; + } + } + return successor; + } + + // ǰڵ + Node* findMax(Node* node) + { + while (node->_right != nullptr) + { + node = node->_right; + } + return node; + } + + Node* FindPredecessor(Node* node) + { + if (node->_left != nullptr) + { + return findMax(node->_left); + } + + Node* cur = _root; + Node* predecessor = nullptr; + while (cur != nullptr) + { + if (node->_kv.first < cur->_kv.first) + { + cur = cur->_left; + } + else if (node->_kv.first > cur->_kv.first) + { + predecessor = cur; + cur = cur->_right; + } + else + { + break; + } + } + return predecessor; + } + + // жǷǺ + bool IsRBTree() + { + // ҲǺ + if (_root == nullptr) + { + return true; + } + + // 1. Ǻɫ + if (_root->_colour != BLACK) + { + std::cout << "ڵ㲻Ǻɫ" << std::endl; + return false; + } + + // ȡһ·Ϻɫڵ + size_t blackCount = 0; + Node* cur = _root; + while (cur) + { + if (cur->_colour == BLACK) + { + blackCount++; + } + cur = cur->_left; + } + + // жǷ, k ¼·кɫڵĸ + size_t k = 0; + return _IsRBTree(_root, k, blackCount); + } + + bool _IsRBTree(Node* root, size_t k, size_t blackCount) + { + // ߵ nullptr ֮, ж k blackCount Ƿ + if (root == nullptr) + { + // պɫڵ + if (blackCount != k) + { + std::cout << "Υ: ÿ·кɫڵĸ" << std::endl; + return false; + } + return true; + } + + // ͳƺɫڵ + if (root->_colour == BLACK) + { + k++; + } + + // ⵱ǰڵ丸׽ڵǷΪɫ + Node* parent = root->_parent; + if (parent && parent->_colour == RED && root->_colour == RED) + { + std::cout << "Υ: ɫڵĺӱǺɫ" << std::endl; + return false; + } + + return _IsRBTree(root->_left, k, blackCount) && _IsRBTree(root->_right, k, blackCount); + } + + private: + Node* _root; + }; +} \ No newline at end of file diff --git a/Windows_RBTree/Windows_RBTree.sln b/Windows_RBTree/Windows_RBTree.sln new file mode 100644 index 0000000..67753d0 --- /dev/null +++ b/Windows_RBTree/Windows_RBTree.sln @@ -0,0 +1,31 @@ + +Microsoft Visual Studio Solution File, Format Version 12.00 +# Visual Studio Version 17 +VisualStudioVersion = 17.7.34221.43 +MinimumVisualStudioVersion = 10.0.40219.1 +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "Windows_RBTree", "Windows_RBTree.vcxproj", "{42DB53E7-EF25-40D3-BFC1-32390B8ED7F0}" +EndProject +Global + GlobalSection(SolutionConfigurationPlatforms) = preSolution + Debug|x64 = Debug|x64 + Debug|x86 = Debug|x86 + Release|x64 = Release|x64 + Release|x86 = Release|x86 + EndGlobalSection + GlobalSection(ProjectConfigurationPlatforms) = postSolution + {42DB53E7-EF25-40D3-BFC1-32390B8ED7F0}.Debug|x64.ActiveCfg = Debug|x64 + {42DB53E7-EF25-40D3-BFC1-32390B8ED7F0}.Debug|x64.Build.0 = Debug|x64 + {42DB53E7-EF25-40D3-BFC1-32390B8ED7F0}.Debug|x86.ActiveCfg = Debug|Win32 + {42DB53E7-EF25-40D3-BFC1-32390B8ED7F0}.Debug|x86.Build.0 = Debug|Win32 + {42DB53E7-EF25-40D3-BFC1-32390B8ED7F0}.Release|x64.ActiveCfg = Release|x64 + {42DB53E7-EF25-40D3-BFC1-32390B8ED7F0}.Release|x64.Build.0 = Release|x64 + {42DB53E7-EF25-40D3-BFC1-32390B8ED7F0}.Release|x86.ActiveCfg = Release|Win32 + {42DB53E7-EF25-40D3-BFC1-32390B8ED7F0}.Release|x86.Build.0 = Release|Win32 + EndGlobalSection + GlobalSection(SolutionProperties) = preSolution + HideSolutionNode = FALSE + EndGlobalSection + GlobalSection(ExtensibilityGlobals) = postSolution + SolutionGuid = {373424CD-AADC-4D9C-B61E-7D43BD7C3183} + EndGlobalSection +EndGlobal diff --git a/Windows_RBTree/Windows_RBTree.vcxproj b/Windows_RBTree/Windows_RBTree.vcxproj new file mode 100644 index 0000000..49dc1e2 --- /dev/null +++ b/Windows_RBTree/Windows_RBTree.vcxproj @@ -0,0 +1,139 @@ + + + + + Debug + Win32 + + + Release + Win32 + + + Debug + x64 + + + Release + x64 + + + + 17.0 + Win32Proj + {42db53e7-ef25-40d3-bfc1-32390b8ed7f0} + WindowsRBTree + 10.0 + + + + Application + true + v143 + Unicode + + + Application + false + v143 + true + Unicode + + + Application + true + v143 + Unicode + + + Application + false + v143 + true + Unicode + + + + + + + + + + + + + + + + + + + + + + Level3 + true + WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions) + true + + + Console + true + + + + + Level3 + true + true + true + WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions) + true + + + Console + true + true + true + + + + + Level3 + true + _DEBUG;_CONSOLE;%(PreprocessorDefinitions) + true + + + Console + true + + + + + Level3 + true + true + true + NDEBUG;_CONSOLE;%(PreprocessorDefinitions) + true + + + Console + true + true + true + + + + + + + + + + + + + \ No newline at end of file diff --git a/Windows_RBTree/Windows_RBTree.vcxproj.filters b/Windows_RBTree/Windows_RBTree.vcxproj.filters new file mode 100644 index 0000000..a6260d3 --- /dev/null +++ b/Windows_RBTree/Windows_RBTree.vcxproj.filters @@ -0,0 +1,30 @@ + + + + + {4FC737F1-C7A5-4376-A066-2A32D752A2FF} + cpp;c;cc;cxx;c++;cppm;ixx;def;odl;idl;hpj;bat;asm;asmx + + + {93995380-89BD-4b04-88EB-625FBE52EBFB} + h;hh;hpp;hxx;h++;hm;inl;inc;ipp;xsd + + + {67DA6AB6-F800-4c08-8B7A-83BB121AAD01} + rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms + + + + + 源文件 + + + + + 头文件 + + + 头文件 + + + \ No newline at end of file diff --git a/Windows_RBTree/Windows_RBTree.vcxproj.user b/Windows_RBTree/Windows_RBTree.vcxproj.user new file mode 100644 index 0000000..88a5509 --- /dev/null +++ b/Windows_RBTree/Windows_RBTree.vcxproj.user @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/Windows_RBTree/x64/Debug/RBTree.obj b/Windows_RBTree/x64/Debug/RBTree.obj new file mode 100644 index 0000000..b47586e Binary files /dev/null and b/Windows_RBTree/x64/Debug/RBTree.obj differ diff --git a/Windows_RBTree/x64/Debug/Windows_RBTree.exe b/Windows_RBTree/x64/Debug/Windows_RBTree.exe new file mode 100644 index 0000000..55498dd Binary files /dev/null and b/Windows_RBTree/x64/Debug/Windows_RBTree.exe differ diff --git a/Windows_RBTree/x64/Debug/Windows_RBTree.exe.recipe b/Windows_RBTree/x64/Debug/Windows_RBTree.exe.recipe new file mode 100644 index 0000000..614709e --- /dev/null +++ b/Windows_RBTree/x64/Debug/Windows_RBTree.exe.recipe @@ -0,0 +1,11 @@ + + + + + E:\Git 仓库\公开仓库\8_RBTree\Windows_RBTree\x64\Debug\Windows_RBTree.exe + + + + + + \ No newline at end of file diff --git a/Windows_RBTree/x64/Debug/Windows_RBTree.ilk b/Windows_RBTree/x64/Debug/Windows_RBTree.ilk new file mode 100644 index 0000000..bc8e463 Binary files /dev/null and b/Windows_RBTree/x64/Debug/Windows_RBTree.ilk differ diff --git a/Windows_RBTree/x64/Debug/Windows_RBTree.log b/Windows_RBTree/x64/Debug/Windows_RBTree.log new file mode 100644 index 0000000..f721e55 --- /dev/null +++ b/Windows_RBTree/x64/Debug/Windows_RBTree.log @@ -0,0 +1,7 @@ + RBTree.cpp +E:\Git 仓库\公开仓库\8_RBTree\Windows_RBTree\RBTree.cpp(67,15): warning C4244: “参数”: 从“time_t”转换到“unsigned int”,可能丢失数据 +E:\Git 仓库\公开仓库\8_RBTree\Windows_RBTree\RBTree.hpp(681,26): warning C4267: “初始化”: 从“size_t”转换到“int”,可能丢失数据 +E:\Git 仓库\公开仓库\8_RBTree\Windows_RBTree\RBTree.hpp(668,14): message : 在编译 类 模板 成员函数“void Lenyiin::RBTree::LevelOrder(void)”时 +E:\Git 仓库\公开仓库\8_RBTree\Windows_RBTree\RBTree.cpp(19,17): message : 请参阅 "test_RBTree" 中对 "Lenyiin::RBTree::LevelOrder" 的第一个引用 +E:\Git 仓库\公开仓库\8_RBTree\Windows_RBTree\RBTree.cpp(10,22): message : 查看对正在编译的 类 模板 实例化“Lenyiin::RBTree”的引用 + Windows_RBTree.vcxproj -> E:\Git 仓库\公开仓库\8_RBTree\Windows_RBTree\x64\Debug\Windows_RBTree.exe diff --git a/Windows_RBTree/x64/Debug/Windows_RBTree.pdb b/Windows_RBTree/x64/Debug/Windows_RBTree.pdb new file mode 100644 index 0000000..08725a2 Binary files /dev/null and b/Windows_RBTree/x64/Debug/Windows_RBTree.pdb differ diff --git a/Windows_RBTree/x64/Debug/Windows_RBTree.tlog/CL.command.1.tlog b/Windows_RBTree/x64/Debug/Windows_RBTree.tlog/CL.command.1.tlog new file mode 100644 index 0000000..e20861e Binary files /dev/null and b/Windows_RBTree/x64/Debug/Windows_RBTree.tlog/CL.command.1.tlog differ diff --git a/Windows_RBTree/x64/Debug/Windows_RBTree.tlog/CL.read.1.tlog b/Windows_RBTree/x64/Debug/Windows_RBTree.tlog/CL.read.1.tlog new file mode 100644 index 0000000..c5663a8 Binary files /dev/null and b/Windows_RBTree/x64/Debug/Windows_RBTree.tlog/CL.read.1.tlog differ diff --git a/Windows_RBTree/x64/Debug/Windows_RBTree.tlog/CL.write.1.tlog b/Windows_RBTree/x64/Debug/Windows_RBTree.tlog/CL.write.1.tlog new file mode 100644 index 0000000..c7c6cb5 Binary files /dev/null and b/Windows_RBTree/x64/Debug/Windows_RBTree.tlog/CL.write.1.tlog differ diff --git a/Windows_RBTree/x64/Debug/Windows_RBTree.tlog/Cl.items.tlog b/Windows_RBTree/x64/Debug/Windows_RBTree.tlog/Cl.items.tlog new file mode 100644 index 0000000..3f0050d --- /dev/null +++ b/Windows_RBTree/x64/Debug/Windows_RBTree.tlog/Cl.items.tlog @@ -0,0 +1 @@ +E:\Git 仓库\公开仓库\8_RBTree\Windows_RBTree\RBTree.cpp;E:\Git 仓库\公开仓库\8_RBTree\Windows_RBTree\x64\Debug\RBTree.obj diff --git a/Windows_RBTree/x64/Debug/Windows_RBTree.tlog/Windows_RBTree.lastbuildstate b/Windows_RBTree/x64/Debug/Windows_RBTree.tlog/Windows_RBTree.lastbuildstate new file mode 100644 index 0000000..d1600fc --- /dev/null +++ b/Windows_RBTree/x64/Debug/Windows_RBTree.tlog/Windows_RBTree.lastbuildstate @@ -0,0 +1,2 @@ +PlatformToolSet=v143:VCToolArchitecture=Native64Bit:VCToolsVersion=14.37.32822:TargetPlatformVersion=10.0.22000.0: +Debug|x64|E:\Git 仓库\公开仓库\8_RBTree\Windows_RBTree\| diff --git a/Windows_RBTree/x64/Debug/Windows_RBTree.tlog/link.command.1.tlog b/Windows_RBTree/x64/Debug/Windows_RBTree.tlog/link.command.1.tlog new file mode 100644 index 0000000..719635f Binary files /dev/null and b/Windows_RBTree/x64/Debug/Windows_RBTree.tlog/link.command.1.tlog differ diff --git a/Windows_RBTree/x64/Debug/Windows_RBTree.tlog/link.read.1.tlog b/Windows_RBTree/x64/Debug/Windows_RBTree.tlog/link.read.1.tlog new file mode 100644 index 0000000..ffd25ee Binary files /dev/null and b/Windows_RBTree/x64/Debug/Windows_RBTree.tlog/link.read.1.tlog differ diff --git a/Windows_RBTree/x64/Debug/Windows_RBTree.tlog/link.write.1.tlog b/Windows_RBTree/x64/Debug/Windows_RBTree.tlog/link.write.1.tlog new file mode 100644 index 0000000..339b7e8 Binary files /dev/null and b/Windows_RBTree/x64/Debug/Windows_RBTree.tlog/link.write.1.tlog differ diff --git a/Windows_RBTree/x64/Debug/Windows_RBTree.vcxproj.FileListAbsolute.txt b/Windows_RBTree/x64/Debug/Windows_RBTree.vcxproj.FileListAbsolute.txt new file mode 100644 index 0000000..64e6580 --- /dev/null +++ b/Windows_RBTree/x64/Debug/Windows_RBTree.vcxproj.FileListAbsolute.txt @@ -0,0 +1 @@ +E:\Git 仓库\公开仓库\8_RBTree\Windows_RBTree\x64\Debug\Windows_RBTree.exe diff --git a/Windows_RBTree/x64/Debug/vc143.idb b/Windows_RBTree/x64/Debug/vc143.idb new file mode 100644 index 0000000..cbe1e18 Binary files /dev/null and b/Windows_RBTree/x64/Debug/vc143.idb differ diff --git a/Windows_RBTree/x64/Debug/vc143.pdb b/Windows_RBTree/x64/Debug/vc143.pdb new file mode 100644 index 0000000..221ce7f Binary files /dev/null and b/Windows_RBTree/x64/Debug/vc143.pdb differ