《算法导论》中的红⿊树
1.
每个节点或者是红⾊的,或者是⿊⾊的
2.
根节点是⿊⾊的
3.
每⼀个叶⼦节点(最后的空节点)是⿊⾊的
4.
如果⼀个节点是红⾊的,那么他的孩⼦节点都是⿊⾊的
5.
从任意⼀个节点到叶⼦节点,经过的⿊⾊节点是⼀样的
红黑树的最长路径中节点数不会超过最短路径节点个数的两倍。
最长路径:一黑一红间隔
最短路径:全黑
路径:root->NULL
非递归插入:(关键看叔叔节点判断)
#pragma once
#include<iostream>
#include<cassert>
#include<vector>
using namespace std;
enum Colour
{
RED,
BLACK,
};
template<class K,class V>
struct RBTreeNode {
pair<K, V>kv;
RBTreeNode<K,V>* parent;
RBTreeNode<K, V>* right;
RBTreeNode<K, V>* left;
Colour col;
RBTreeNode(const pair<K,V>& kv):kv(kv),parent(nullptr),right(nullptr),left(nullptr),col(RED){}
};
template<class K,class V>
class RBTree {
typedef RBTreeNode<K, V> Node;
private:
Node* root = nullptr;
void RotateL(Node* parent) {
Node* subR = parent->right;
Node* subRL = subR->left;
parent->right = subRL;
if (subRL)
{
subRL->parent = parent;
}
subR->left = parent;
Node* pparent = parent->parent;
parent->parent = subR;
if (parent == root)
{
root = subR;
root->parent = nullptr;
}
else
{
if (parent == pparent->left)
{
pparent->left = subR;
}
else {
pparent->right = subR;
}
subR->parent = pparent;
}
}
void RotateR(Node* parent) {
Node* subL = parent->left;
Node* subLR = subL->right;
parent->left = subLR;
if (subLR)
{
subLR->parent = parent;
}
Node* pparent = parent->parent;
subL->right = parent;
parent->parent = subL;
if (parent == root)
{
root = subL;
root->parent = nullptr;
}
else
{
if (parent == pparent->left)
{
pparent->left = subL;
}
else {
pparent->right = subL;
}
subL->parent = pparent;
}
}
void _InOrder(Node* root)
{
if (root == nullptr)
return;
_InOrder(root->left);
cout << root->kv.first << " ";
_InOrder(root->right);
}
int _maxHeight(Node* node) {
if (node == nullptr)
{
return 0;
}
int LH = _maxHeight(node->left);
int RH = _maxHeight(node->right);
return (LH > RH) ? LH + 1 : RH + 1;
}
int _minHeight(Node* node) {
if (node == nullptr)
{
return 0;
}
int LH = _minHeight(node->left);
int RH = _minHeight(node->right);
return (LH < RH) ? LH + 1 : RH + 1;
}
bool _IsRBTree(Node* node, size_t k, const size_t blackCount) {
if (node == nullptr)
{
if (k != blackCount)
{
cout << "违反性质四:每条路径的黑色节点个数相同" << endl;
return false;
}
return true;
}
if (node->col == BLACK)
{
k++;
}
if (node->col == RED && node->parent && node->parent->col == RED)
{
cout << "违反性质三:不能存在连续的红色节点" << endl;
return false;
}
return _IsRBTree(node->left, k, blackCount) && _IsRBTree(node->right, k, blackCount);
}
public:
int maxHeight() {
return _maxHeight(root);
}
int minHeight() {
return _minHeight(root);
}
void InOrder() {
_InOrder(root);
}
bool IsRBTree() {
Node* node = root;
if (node == nullptr)
{
return true;
}
if (node->col != BLACK)
{
cout << "根的节点不为黑色" << endl;
return false;
}
size_t blackCount = 0;
Node* cur = node;
while (cur)
{
if (cur->col == BLACK)
blackCount++;
cur = cur->left;
}
size_t k = 0;
return _IsRBTree(root, k, blackCount);
}
bool Insert(const pair<K, V>& kv) {
if (root == nullptr)
{
root = new Node(kv);
root->col = BLACK;
return true;
}
Node* cur = root;
Node* parent = nullptr;
while (cur)
{
if (cur->kv.first < kv.first) {
parent = cur;
cur = cur->right;
}
else if (cur->kv.first > kv.first)
{
parent = cur;
cur = cur->left;
}
else
{
return false;
}
}
cur = new Node(kv);
cur->col = RED;
if (kv.first < parent->kv.first)
{
parent->left = cur;
}
else {
parent->right = cur;
}
cur->parent = parent;
while (parent && parent->col == RED)
{
Node* grandfather = parent->parent;
if (parent == grandfather->left)
{
Node* uncle = grandfather->right;
if (uncle && uncle->col == RED)
{
parent->col = uncle->col = BLACK;
grandfather->col = RED;
cur = grandfather;
parent = cur->parent;
}
else //uncle不存在或存在且为黑色
{
if (cur == parent->left)
{
RotateR(grandfather);
parent->col = BLACK;
grandfather->col = RED;
}
else
{
RotateL(parent);
RotateR(grandfather);
cur->col = BLACK;
grandfather->col = RED;
}
break;
}
}
else {
Node* uncle = grandfather->left;
if (uncle && uncle->col == RED)
{
parent->col = uncle->col = BLACK;
grandfather->col = RED;
cur = grandfather;
parent = cur->parent;
}
else
{
if (cur == parent->right)
{
RotateL(grandfather);
parent->col = BLACK;
grandfather->col = RED;
}
else
{
RotateR(parent);
RotateL(grandfather);
cur->col = BLACK;
grandfather->col = RED;
}
break;
}
}
}
root->col = BLACK;
return true;
}
};
void testRBTree1() {
int a[] = { 30, 29, 28, 27, 26, 25, 24, 11, 8, 7, 6, 5, 4, 3, 2, 1 };
RBTree<int, int> t;
for (auto e : a)
{
t.Insert(make_pair(e, e));
}
t.InOrder();
}
void testRBTree2() {
const int N = 1000;
vector<int>v;
srand(time(0));
for (size_t i = 0; i < N; i++)
{
//v.push_back(i);
v.push_back(rand());
}
RBTree<int, int>rbTree;
for (auto e : v) {
rbTree.Insert(make_pair(e, e));
}
cout << "是否平衡?" << rbTree.IsRBTree() << endl;
cout << "最小高度 = " << rbTree.minHeight() << endl;
cout << "最大高度 = " << rbTree.maxHeight() << endl;
rbTree.InOrder();
}
递归插入:(主要和2-3树的插入操作相似,如更好的理解红黑树和B树,请先了解2-3树)
//
// Created by hpf on 18-7-16.
//
#ifndef RED_BLACK_TREE_RBTREE_H
#define RED_BLACK_TREE_RBTREE_H
#include <iostream>
#include <vector>
template<typename Key, typename Value>
class RBTree {
private:
static const bool RED = true;
static const bool BLACK = false;
struct Node {
Key key;
Value value;
Node *left;
Node *right;
bool color;
Node(Key key, Value value) {
this->key = key;
this->value = value;
this->left = this->right = nullptr;
color = RED;
}
Node(Node *node) {
this->key = node->key;
this->value = node->value;
this->left = node->left;
this->right = node->right;
this->color = node->color;
}
};
Node *root;
int size;
public:
RBTree() {
root = nullptr;
size = 0;
}
~RBTree() {
destroy(root);
}
int getSize() {
return size;
}
int isEmpty() {
return size == 0;
}
bool isRed(Node *node) {
if (node == nullptr) {
return BLACK;
}
return node->color;
}
void add(Key key, Value value) {
root = add(root, key, value);
root->color = BLACK;
}
bool contains(Key key) {
return getNode(root, key) != nullptr;
}
Value *get(Key key) {
Node *node = getNode(root, key);
return node == nullptr ? nullptr : &(node->value);
}
void set(Key key, Value newValue) {
Node *node = getNode(root, key);
if (node != nullptr) {
node->value = newValue;
}
}
private:
// 向以node为根的二叉搜索树中,插入节点(key, value)
// 返回插入新节点后的二叉搜索树的根
Node *add(Node *node, Key key, Value value) {
if (node == nullptr) {
size++;
return new Node(key, value);
}
if (key == node->key) {
node->value = value;
} else if (key < node->key) {
node->left = add(node->left, key, value);
} else {
node->right = add(node->right, key, value);
}
if (isRed(node->right) && !isRed(node->left)) {
node = leftRotate(node);
}
if (isRed(node->left) && isRed(node->left->left)) {
node = rightRotate(node);
}
if (isRed(node->left) && isRed(node->right)) {
flipColors(node);
}
return node;
}
// 在以node为根的二叉搜索树中查找key所对应的Node
Node *getNode(Node *node, Key key) {
if (node == nullptr) {
return nullptr;
}
if (key == node->key) {
return node;
} else if (key < node->key) {
return getNode(node->left, key);
} else {
return getNode(node->right, key);
}
}
void destroy(Node *node) {
if (node != nullptr) {
destroy(node->left);
destroy(node->right);
delete node;
size--;
}
}
Node *leftRotate(Node *node) {
Node *x = node->right;
node->right = x->left;
x->left = node;
x->color = node->color;
node->color = RED;
return x;
}
Node *rightRotate(Node *node) {
Node *x = node->left;
node->left = x->right;
x->right = node;
x->color = node->color;
node->color = RED;
return x;
}
void flipColors(Node *node) {
node->color = RED;
node->left->color = BLACK;
node->right->color = BLACK;
}
};
#endif //RED_BLACK_TREE_RBTREE_H
红黑树的性能总结
对于完全随机的数据,普通的⼆分搜索树很好⽤!
缺点:极端情况退化成链表(或者⾼度不平衡)
对于查询较多的使⽤情况,
AVL
树很好⽤!
红⿊树牺牲了平衡性(
2logn
的⾼度)
统计性能更优
(综合增删改查所有的操作)