注:下面这个版本基于《算法(第四版)》实现。这个红黑树是简化版本的。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
enum Color { RED, BLACK };

template <class K, class V>
class RBTree {
struct RBNode {
K key;
V value;
size_t N;
Color color;
RBNode *left, *right;

RBNode(K key, V value, size_t N, Color color)
: key(key), value(value), N(N), color(color), left(nullptr), right(nullptr) {}
};

using Node = RBNode;

Node* root = nullptr;

const size_t size(const Node* h) {
if (!h) return 0;
return h->N;
}

const bool isRed(const Node* h) {
if (h == nullptr) return false;
return h->color == RED;
}

Node* put(Node* h, K const& key, V const& value) {
if (h == nullptr) return new Node(key, value, 1, RED);

if (key < h->key)
h->left = put(h->left, key, value);
else if (h->key < key)
h->right = put(h->right, key, value);
else
h->value = value;

// A red link appears on the right
if (isRed(h->right) && !isRed(h->left)) h = rotateLeft(h);
// Two continuous red links
if (isRed(h->left) && isRed(h->left->left)) h = rotateRight(h);
// Red links on both sides
if (isRed(h->left) && isRed(h->right)) flipColors(h);

h->N = 1 + size(h->left) + size(h->right);

return h;
}

void flipColors(Node* h) {
h->left->color = h->right->color = BLACK;
h->color = RED;
}

Node* rotateLeft(Node* h) {
Node* x = h->right;
h->right = x->left;
x->left = h;
x->color = h->color;
x->N = h->N;
h->N = 1 + size(h->left) + size(h->right);
return x;
}

Node* rotateRight(Node* h) {
Node* x = h->left;
h->left = x->right;
x->right = h;
x->color = h->color;
x->N = h->N;
h->N = 1 + size(h->left) + size(h->right);
return x;
}

Node* get(Node* h, K const& key) {
if (!h) return nullptr;

if (h->key < key)
return get(h->left, key);
else if (key < h->key)
return get(h->left, key);
return h;
}

public:
size_t size() { return size(root); }

void put(K const& key, V const& value) {
root = put(root, key, value);
root->color = BLACK;
}

V& get(K const& key) {
Node* x = get(root, key);
if (x == nullptr) {
put(key, V{});
x = get(root, key);
}
return x->value;
}

V& operator[](K const& key) { return get(key); }
};