红黑树
This commit is contained in:
2
.gitignore
vendored
Normal file
2
.gitignore
vendored
Normal file
@@ -0,0 +1,2 @@
|
||||
.idea
|
||||
cmake-build-*
|
||||
13
CMakeLists.txt
Normal file
13
CMakeLists.txt
Normal 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
|
||||
)
|
||||
541
include/RedBlackTree.h
Normal file
541
include/RedBlackTree.h
Normal 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
25
main.cpp
Normal 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
10
src/RedBlackTree.cpp
Normal file
@@ -0,0 +1,10 @@
|
||||
// 版权所有 (c) ling 保留所有权利。
|
||||
// 除非另行说明,否则仅允许在DataStruct中使用此文件中的代码。
|
||||
//
|
||||
// 由 ling 创建于 24-6-30.
|
||||
//
|
||||
|
||||
#include "RedBlackTree.h"
|
||||
|
||||
namespace ling {
|
||||
} // ling
|
||||
Reference in New Issue
Block a user