From 20ecee3980239aabe7f9be60feccb6796ae6790c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E9=A9=BB=E9=AD=82=E5=9C=A3=E4=BD=BF?= Date: Sun, 30 Jun 2024 14:50:16 +0800 Subject: [PATCH] =?UTF-8?q?=E7=BA=A2=E9=BB=91=E6=A0=91?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .gitignore | 2 + CMakeLists.txt | 13 + README.md | 1 + include/RedBlackTree.h | 541 +++++++++++++++++++++++++++++++++++++++++ main.cpp | 25 ++ src/RedBlackTree.cpp | 10 + 6 files changed, 592 insertions(+) create mode 100644 .gitignore create mode 100644 CMakeLists.txt create mode 100644 README.md create mode 100644 include/RedBlackTree.h create mode 100644 main.cpp create mode 100644 src/RedBlackTree.cpp diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..1c85d0e --- /dev/null +++ b/.gitignore @@ -0,0 +1,2 @@ +.idea +cmake-build-* diff --git a/CMakeLists.txt b/CMakeLists.txt new file mode 100644 index 0000000..a1226c2 --- /dev/null +++ b/CMakeLists.txt @@ -0,0 +1,13 @@ +cmake_minimum_required(VERSION 3.29) +project(DataStruct) + +set(CMAKE_CXX_STANDARD 17) + +include_directories(include) + +add_executable(DataStruct + main.cpp + src/RedBlackTree.cpp + src/HeapSort.cpp + include/HeapSort.h +) diff --git a/README.md b/README.md new file mode 100644 index 0000000..79530f4 --- /dev/null +++ b/README.md @@ -0,0 +1 @@ +# 基础数据结构 \ No newline at end of file diff --git a/include/RedBlackTree.h b/include/RedBlackTree.h new file mode 100644 index 0000000..4296d89 --- /dev/null +++ b/include/RedBlackTree.h @@ -0,0 +1,541 @@ +// 版权所有 (c) ling 保留所有权利。 +// 除非另行说明,否则仅允许在DataStruct中使用此文件中的代码。 +// +// 由 ling 创建于 24-6-30. +// + +#ifndef REDBLACKTREE_REDBLACKTREE_H_03 +#define REDBLACKTREE_REDBLACKTREE_H_03 + +namespace ling { + + enum Relation { + EQUAL, + BIG, + SMALL, + }; + enum Color { + RED, + BLACK, + }; + + /** + * 红黑树 + * @tparam T + */ + template + class RedBlackTree { + public: + struct Node { + T value; + Color color; + Node *left; + Node *right; + //父节点 + Node *parent; + + Node(T value, Color c, Node *p, Node *l, Node *r) : value(value), color(c), parent(p), left(l), right(r) { + } + }; + + private: + /// 根节点 + Node *rootNode = nullptr; + + void destroy(Node *&node); + + /// 插入函数 + void insert(Node *&root, Node *node); + + /** + * 红黑树插入修正函数 + * + * 在向红黑树中插入节点之后(失去平衡),再调用该函数; + * 目的是将它重新塑造成一颗红黑树。 + * + * @param root 红黑树的根 + * @param node 插入的结点 + */ + void insertFixUp(Node *&root, Node *node); + + /** + * 红黑树删除修正函数 + * + * 在从红黑树中删除插入节点之后(红黑树失去平衡),再调用该函数; + * 目的是将它重新塑造成一颗红黑树。 + * + * @param root 红黑树的根 + * @param node 待修正的节点 + */ + void removeFixUp(Node *&root, Node *node, Node *parent); + + /** + * 对红黑树的节点(x)进行左旋转 + * + * 左旋示意图(对节点x进行左旋): + * px px + * / / + * x y + * / \ --(左旋)--> / \ # + * lx y x ry + * / \ / \ + * ly ry lx ly + * + * + */ + void leftRotate(Node *&root, Node *x); + + /** + * 对红黑树的节点(y)进行右旋转 + * + * 右旋示意图(对节点y进行左旋): + * py py + * / / + * y x + * / \ --(右旋)--> / \ # + * x ry lx y + * / \ / \ # + * lx rx rx ry + * + */ + void rightRotate(Node *root, Node *y); + + /// 查找元素 + Node *iterativeSearch(Node *x, T key) const; + + /// 删除元素 + void remove(Node *&root, Node *node); + + protected: + + virtual Relation equal(const T &val1, const T &val2) const = 0; + + public: + explicit RedBlackTree() = default; + + virtual ~RedBlackTree() { + destroy(); + } + + /// 销毁红黑树 + void destroy(); + + /// 插入元素 + void insert(T key); + + /// 删除节点 + void remove(T key); + + /// 查找节点 + Node *iterativeSearch(T key); + + /// 根节点 + Node *getRoot() { + return rootNode; + } + + // 查找最小结点:返回tree为根结点的红黑树的最小结点。 + Node *minimum(); + + // 查找最大结点:返回tree为根结点的红黑树的最大结点。 + Node *maximum(); + +#define rb_parent(r) ((r)->parent) +#define rb_color(r) ((r)->color) +#define rb_is_red(r) ((r)->color==RED) +#define rb_is_black(r) ((r)->color==BLACK) +#define rb_set_black(r) do { (r)->color = BLACK; } while (0) +#define rb_set_red(r) do { (r)->color = RED; } while (0) +#define rb_set_parent(r, p) do { (r)->parent = (p); } while (0) +#define rb_set_color(r, c) do { (r)->color = (c); } while (0) + + }; + + template + typename RedBlackTree::Node *RedBlackTree::maximum() { + Node *tree = rootNode; + if (tree == nullptr) + return nullptr; + + while (tree->right != nullptr) + tree = tree->right; + return tree; + } + + template + typename RedBlackTree::Node *RedBlackTree::minimum() { + Node *tree = rootNode; + if (tree == nullptr) + return nullptr; + + while (tree->left != nullptr) + tree = tree->left; + return tree; + } + + template + void RedBlackTree::removeFixUp(RedBlackTree::Node *&root, RedBlackTree::Node *node, RedBlackTree::Node *parent) { + Node *other; + + while ((!node || rb_is_black(node)) && node != root) { + if (parent->left == node) { + other = parent->right; + if (rb_is_red(other)) { + // Case 1: x的兄弟w是红色的 + rb_set_black(other); + rb_set_red(parent); + leftRotate(root, parent); + other = parent->right; + } + if ((!other->left || rb_is_black(other->left)) && + (!other->right || rb_is_black(other->right))) { + // Case 2: x的兄弟w是黑色,且w的俩个孩子也都是黑色的 + rb_set_red(other); + node = parent; + parent = rb_parent(node); + } else { + if (!other->right || rb_is_black(other->right)) { + // Case 3: x的兄弟w是黑色的,并且w的左孩子是红色,右孩子为黑色。 + rb_set_black(other->left); + rb_set_red(other); + rightRotate(root, other); + other = parent->right; + } + // Case 4: x的兄弟w是黑色的;并且w的右孩子是红色的,左孩子任意颜色。 + rb_set_color(other, rb_color(parent)); + rb_set_black(parent); + rb_set_black(other->right); + leftRotate(root, parent); + node = root; + break; + } + } else { + other = parent->left; + if (rb_is_red(other)) { + // Case 1: x的兄弟w是红色的 + rb_set_black(other); + rb_set_red(parent); + rightRotate(root, parent); + other = parent->left; + } + if ((!other->left || rb_is_black(other->left)) && + (!other->right || rb_is_black(other->right))) { + // Case 2: x的兄弟w是黑色,且w的俩个孩子也都是黑色的 + rb_set_red(other); + node = parent; + parent = rb_parent(node); + } else { + if (!other->left || rb_is_black(other->left)) { + // Case 3: x的兄弟w是黑色的,并且w的左孩子是红色,右孩子为黑色。 + rb_set_black(other->right); + rb_set_red(other); + leftRotate(root, other); + other = parent->left; + } + // Case 4: x的兄弟w是黑色的;并且w的右孩子是红色的,左孩子任意颜色。 + rb_set_color(other, rb_color(parent)); + rb_set_black(parent); + rb_set_black(other->left); + rightRotate(root, parent); + node = root; + break; + } + } + } + if (node) + rb_set_black(node); + } + + template + void RedBlackTree::remove(RedBlackTree::Node *&root, RedBlackTree::Node *node) { + Node *child, *parent; + Color color; + + // 被删除节点的"左右孩子都不为空"的情况。 + if ((node->left != nullptr) && (node->right != nullptr)) { + // 被删节点的后继节点。(称为"取代节点") + // 用它来取代"被删节点"的位置,然后再将"被删节点"去掉。 + Node *replace = node; + + // 获取后继节点 + replace = replace->right; + while (replace->left != nullptr) + replace = replace->left; + + // "node节点"不是根节点(只有根节点不存在父节点) + if (rb_parent(node)) { + if (rb_parent(node)->left == node) + rb_parent(node)->left = replace; + else + rb_parent(node)->right = replace; + } else + // "node节点"是根节点,更新根节点。 + root = replace; + + // child是"取代节点"的右孩子,也是需要"调整的节点"。 + // "取代节点"肯定不存在左孩子!因为它是一个后继节点。 + child = replace->right; + parent = rb_parent(replace); + // 保存"取代节点"的颜色 + color = rb_color(replace); + + // "被删除节点"是"它的后继节点的父节点" + if (parent == node) { + parent = replace; + } else { + // child不为空 + if (child) + rb_set_parent(child, parent); + parent->left = child; + + replace->right = node->right; + rb_set_parent(node->right, replace); + } + + replace->parent = node->parent; + replace->color = node->color; + replace->left = node->left; + node->left->parent = replace; + + if (color == BLACK) + removeFixUp(root, child, parent); + + delete node; + return; + } + + if (node->left != nullptr) + child = node->left; + else + child = node->right; + + parent = node->parent; + // 保存"取代节点"的颜色 + color = node->color; + + if (child) + child->parent = parent; + + // "node节点"不是根节点 + if (parent) { + if (parent->left == node) + parent->left = child; + else + parent->right = child; + } else + root = child; + + if (color == BLACK) + removeFixUp(root, child, parent); + delete node; + } + + template + typename RedBlackTree::Node *RedBlackTree::iterativeSearch(RedBlackTree::Node *x, T key) const { + while ((x != nullptr) && equal(x->value, key) != EQUAL) { + if (equal(key, x->value) == SMALL) { + x = x->left; + } else { + x = x->right; + } + } + return x; + } + + template + typename RedBlackTree::Node *RedBlackTree::iterativeSearch(T key) { + return iterativeSearch(rootNode, key); + } + + template + void RedBlackTree::remove(T key) { + Node *node; + // 查找key对应的节点(node),找到的话就删除该节点 + if ((node = iterativeSearch(rootNode, key)) != nullptr) + remove(rootNode, node); + } + + template + void RedBlackTree::rightRotate(RedBlackTree::Node *root, RedBlackTree::Node *y) { + // 设置x是当前节点的左孩子。 + Node *x = y->left; + + // 将 “x的右孩子” 设为 “y的左孩子”; + // 如果"x的右孩子"不为空的话,将 “y” 设为 “x的右孩子的父亲” + y->left = x->right; + if (x->right != nullptr) + x->right->parent = y; + + // 将 “y的父亲” 设为 “x的父亲” + x->parent = y->parent; + + if (y->parent == nullptr) { + root = x; // 如果 “y的父亲” 是空节点,则将x设为根节点 + } else { + if (y == y->parent->right) + y->parent->right = x; // 如果 y是它父节点的右孩子,则将x设为“y的父节点的右孩子” + else + y->parent->left = x; // (y是它父节点的左孩子) 将x设为“x的父节点的左孩子” + } + + // 将 “y” 设为 “x的右孩子” + x->right = y; + + // 将 “y的父节点” 设为 “x” + y->parent = x; + } + + template + void RedBlackTree::leftRotate(RedBlackTree::Node *&root, RedBlackTree::Node *x) { + // 设置x的右孩子为y + Node *y = x->right; + + // 将 “y的左孩子” 设为 “x的右孩子”; + // 如果y的左孩子非空,将 “x” 设为 “y的左孩子的父亲” + x->right = y->left; + if (y->left != nullptr) + y->left->parent = x; + + // 将 “x的父亲” 设为 “y的父亲” + y->parent = x->parent; + + if (x->parent == nullptr) { + root = y; // 如果 “x的父亲” 是空节点,则将y设为根节点 + } else { + if (x->parent->left == x) + x->parent->left = y; // 如果 x是它父节点的左孩子,则将y设为“x的父节点的左孩子” + else + x->parent->right = y; // 如果 x是它父节点的左孩子,则将y设为“x的父节点的左孩子” + } + + // 将 “x” 设为 “y的左孩子” + y->left = x; + // 将 “x的父节点” 设为 “y” + x->parent = y; + } + + template + void RedBlackTree::insertFixUp(RedBlackTree::Node *&root, RedBlackTree::Node *node) { + Node *parent; + Node *gparent; + // 若父节点存在,并且父节点的颜色是红色 + while ((parent = rb_parent(node)) && rb_is_red(parent)) { + gparent = rb_parent(parent); + //若父节点是祖父节点的左孩子 + //若“父节点”是“祖父节点的左孩子” + if (parent == gparent->left) { + // Case 1条件:叔叔节点是红色 + { + Node *uncle = gparent->right; + if (uncle && rb_is_red(uncle)) { + rb_set_black(uncle); + rb_set_black(parent); + rb_set_red(gparent); + node = gparent; + continue; + } + } + + // Case 2条件:叔叔是黑色,且当前节点是右孩子 + if (parent->right == node) { + Node *tmp; + leftRotate(root, parent); + tmp = parent; + parent = node; + node = tmp; + } + + // Case 3条件:叔叔是黑色,且当前节点是左孩子。 + rb_set_black(parent); + rb_set_red(gparent); + rightRotate(root, gparent); + } else//若“z的父节点”是“z的祖父节点的右孩子” + { + // Case 1条件:叔叔节点是红色 + { + Node *uncle = gparent->left; + if (uncle && rb_is_red(uncle)) { + rb_set_black(uncle); + rb_set_black(parent); + rb_set_red(gparent); + node = gparent; + continue; + } + } + + // Case 2条件:叔叔是黑色,且当前节点是左孩子 + if (parent->left == node) { + Node *tmp; + rightRotate(root, parent); + tmp = parent; + parent = node; + node = tmp; + } + + // Case 3条件:叔叔是黑色,且当前节点是右孩子。 + rb_set_black(parent); + rb_set_red(gparent); + leftRotate(root, gparent); + } + } + + // 将根节点设为黑色 + rb_set_black(root); + } + + template + void RedBlackTree::insert(RedBlackTree::Node *&root, RedBlackTree::Node *node) { + Node *y = nullptr; + Node *x = root; + + // 1. 将红黑树当作一颗二叉搜索树,将节点插入二叉搜索树中 + while (x != nullptr) { + y = x; + if (equal(node->value, x->value) == SMALL) { + x = x->left; + } else { + x = x->right; + } + } + node->parent = y; + if (y != nullptr) { + if (equal(node->value, y->value) == SMALL) { + y->left = node; + } else { + y->right = node; + } + } else { + root = node; + } + // 2. 设置节点的颜色为红色 + node->color = RED; + // 3. 将他重新修正为一颗红黑树 + insertFixUp(root, node); + } + + template + void RedBlackTree::insert(T key) { + Node *node = new Node(key, BLACK, nullptr, nullptr, nullptr); + insert(rootNode, node); + } + + template + void RedBlackTree::destroy() { + destroy(rootNode); + } + + template + void RedBlackTree::destroy(RedBlackTree::Node *&node) { + if (node == nullptr) + return; + if (node->left != nullptr) + destroy(node->left); + if (node->right != nullptr) + destroy(node->right); + delete node; + node = nullptr; + } + +} // ling + +#endif //REDBLACKTREE_REDBLACKTREE_H_03 diff --git a/main.cpp b/main.cpp new file mode 100644 index 0000000..c54a33d --- /dev/null +++ b/main.cpp @@ -0,0 +1,25 @@ +#include +#include + + +class RedBlackTree : public ling::RedBlackTree { +protected: + [[nodiscard]] ling::Relation equal(const int &val1, const int &val2) const override { + if (val1 == val2) + return ling::Relation::EQUAL; + if (val1 < val2) + return ling::Relation::SMALL; + return ling::Relation::BIG; + } +}; + +int main() { + RedBlackTree tree; + + for (int i = 0; i < 400000; i++) + tree.insert(i); + + std::cout << "Max : " << tree.maximum()->value << std::endl; + + return 0; +} diff --git a/src/RedBlackTree.cpp b/src/RedBlackTree.cpp new file mode 100644 index 0000000..e9f6806 --- /dev/null +++ b/src/RedBlackTree.cpp @@ -0,0 +1,10 @@ +// 版权所有 (c) ling 保留所有权利。 +// 除非另行说明,否则仅允许在DataStruct中使用此文件中的代码。 +// +// 由 ling 创建于 24-6-30. +// + +#include "RedBlackTree.h" + +namespace ling { +} // ling \ No newline at end of file