红黑树

This commit is contained in:
2024-06-30 14:50:16 +08:00
commit 20ecee3980
6 changed files with 592 additions and 0 deletions

2
.gitignore vendored Normal file
View File

@@ -0,0 +1,2 @@
.idea
cmake-build-*

13
CMakeLists.txt Normal file
View File

@@ -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
)

1
README.md Normal file
View File

@@ -0,0 +1 @@
# 基础数据结构

541
include/RedBlackTree.h Normal file
View File

@@ -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<typename T>
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 T>
typename RedBlackTree<T>::Node *RedBlackTree<T>::maximum() {
Node *tree = rootNode;
if (tree == nullptr)
return nullptr;
while (tree->right != nullptr)
tree = tree->right;
return tree;
}
template<typename T>
typename RedBlackTree<T>::Node *RedBlackTree<T>::minimum() {
Node *tree = rootNode;
if (tree == nullptr)
return nullptr;
while (tree->left != nullptr)
tree = tree->left;
return tree;
}
template<typename T>
void RedBlackTree<T>::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<typename T>
void RedBlackTree<T>::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 T>
typename RedBlackTree<T>::Node *RedBlackTree<T>::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 T>
typename RedBlackTree<T>::Node *RedBlackTree<T>::iterativeSearch(T key) {
return iterativeSearch(rootNode, key);
}
template<typename T>
void RedBlackTree<T>::remove(T key) {
Node *node;
// 查找key对应的节点(node),找到的话就删除该节点
if ((node = iterativeSearch(rootNode, key)) != nullptr)
remove(rootNode, node);
}
template<typename T>
void RedBlackTree<T>::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<typename T>
void RedBlackTree<T>::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<typename T>
void RedBlackTree<T>::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<typename T>
void RedBlackTree<T>::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<typename T>
void RedBlackTree<T>::insert(T key) {
Node *node = new Node(key, BLACK, nullptr, nullptr, nullptr);
insert(rootNode, node);
}
template<typename T>
void RedBlackTree<T>::destroy() {
destroy(rootNode);
}
template<typename T>
void RedBlackTree<T>::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

25
main.cpp Normal file
View File

@@ -0,0 +1,25 @@
#include <iostream>
#include <RedBlackTree.h>
class RedBlackTree : public ling::RedBlackTree<int> {
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;
}

10
src/RedBlackTree.cpp Normal file
View File

@@ -0,0 +1,10 @@
// 版权所有 (c) ling 保留所有权利。
// 除非另行说明否则仅允许在DataStruct中使用此文件中的代码。
//
// 由 ling 创建于 24-6-30.
//
#include "RedBlackTree.h"
namespace ling {
} // ling