map和set的实现

RBTree

红黑树修改版本

RBTreeNode树里面的每一个节点

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
#pragma once
#include <iostream>
using namespace std;

enum Color
{
RED,
BLACK
};
template <class T>//这里只有一个T变量,可以是一个key也可以是一个pair

struct RBTreeNode
{
RBTreeNode<T> *_left;
RBTreeNode<T> *_right;
RBTreeNode<T> *_parent;
T _data;//只使用T的data变量
Color _col; //控制颜色
RBTreeNode(const T &data)
: _data(data), _left(nullptr), _right(nullptr), _parent(nullptr), _col(RED) //一开始的颜色给红色
{
}
};

树的迭代器Iterator

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
template <class T, class Ref, class Ptr> // T是变量类型,Ref返回的是里面的值,Ptr返回的是里面的地址
struct RBTreeIterator
{
typedef RBTreeNode<T> Node;//里面的存储的元素类型是T
typedef RBTreeIterator<T,Ref, Ptr> Self;//迭代器进行重定义
Node *_node;
RBTreeIterator(Node *node)
: _node(node)
{
}

Ref operator*() //这个返回的是T&返回的是值
{
return _node->_data;
}
Ptr operator->()
{
return &_node->_data;
}
Self& operator++()//返回的是自己这个指针
//中序遍历,从小到大
{
// 1. 左边都访问过了,假如右树存在,下一个就要访问右树的最左节点
// 2. 如果右为空,我所在的子树完了,我是父亲的左边,下一个访问父亲
// 2.1我是父亲的右边,访问的父亲的父亲

if (_node->_right) //右不为空
{
Node *min = _node->_right; //找右的最左节点
while (min->_left)
{
min = min->_left;
}
_node = min;
}
else
{
//右为空,找孩子是父亲左的祖先
Node *cur = _node;
Node* parent=cur->_parent;
//如果cur是父亲的右
while(parent&&cur==parent->_right)
{
cur=parent;
parent=parent->_parent;
}
//cur是父亲的左
_node=parent;
}
return *this;
}
Self& operator--()
{
//右根左,和++反过来的
//左不为空,到左节点的最右边
//左为空,是父亲的右节点,到父亲
//是父亲的左节点,到孩子是父亲的右节点
if(_node->_left)
{
//左不为空,
Node* max=_node->_left;
while(max->_right)
{
max=max->_right;
}
_node=max;
}
else
{
Node* parent=_node->_parent;
while(parent&&parent->_left==_node)
{

_node=parent;
parent=parent->_parent;
}
_node=_node->_parent;

}

return *this;
}

bool operator!=(const Self& s)
{
return _node!=s._node;
}

};

RBTree

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
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
// set传的T是key RBTree<K,K,SetKeyOfT>
// map传的T是pair RBTree<K,pair<K,pair<K,V>,MapKeyOfT>

template <class K, class T, class KeyOfT> // KeyOfT是一个仿函数,我们要取出T的first
//K是为了获得T里面的第一个参数的类型
//T里面就是树里面存储的元素
//KeyOfT是获得出T里面第一个参数的值
class RBTree
{
typedef RBTreeNode<T> Node;

private:
Node *_root;

private:
void _InOrder(Node *root)//中序遍历
{
if (root == nullptr)
return;
_InOrder(root->_left);
cout << root->_kv.first << " ";
_InOrder(root->_right);
}
void RotateR(Node *parent)
{
//右单旋转
Node *subL = parent->_left; //子节点
Node *subLR = subL->_right; //子节点的右节点
Node *parentparent = parent->_parent; //出问题节点的父节点
parent->_left = subLR;
subL->_right = parent;
parent->_parent = subL;
if (subLR)
subLR->_parent = parent;

//和父节点的父节点连接
if (parent == _root)
{
//要旋转的节点已经是根
//更新根
_root = subL;
_root->_parent = nullptr; //更新顶部
}
else
{
//父节点上面还有节点
if (parentparent->_left == parent)
{
//是左节点
subL->_parent = parentparent;
parentparent->_left = subL;
}
else
{
subL->_parent = parentparent;
parentparent->_right = subL;
}
}
}
void RotateL(Node *parent) //左单旋
{
Node *subR = parent->_right;
Node *subRL = subR->_left;
Node *parentparent = parent->_parent;
parent->_parent = subR;
subR->_left = parent;
parent->_right = subRL;
if (subRL)
subRL->_parent = parent;
if (parent == _root)
{
_root = subR;
_root->_parent = nullptr;
}
else
{
if (parentparent->_right == parent)
{
parentparent->_right = subR;
subR->_parent = parentparent;
}
else
{
parentparent->_left = subR;
subR->_parent = parentparent;
}
}
}

public:
typedef RBTreeIterator<T, T &, T *> Iterator;
typedef RBTreeIterator<T,const T&,const T*> const_Iterator;

//中序遍历就是从小到大的
Iterator begin() //因为它是走中序,所以第一个是最左节点,最小值
{
Node *min = _root; //最小值,就是左节点
while (min && min->_left)
{
min = min->_left;
}

return Iterator(min);
}
Iterator end()
{
//最大值的下一个节点
//最右边的下一个是null

return Iterator(nullptr);
}

Iterator Find(const K& key)//K是为了取出V里面的第一个参数
{
Node* cur=_root;
KeyOfT kot;//使用仿函数,调用
while(cur)
{
if(kot(cur->_data)<key)
{
cur=cur->_right;
}
else if(kot(cur->_data)>key)
{
cur=cur->_left;
}
else
{
return Iterator(cur);
}
}
return end();//没有找到,就返回end
}

RBTree()
: _root(nullptr)
{
}
~RBTree()
{
Destroy(_root);
_root=nullptr;
}
RBTree(const RBTree<K,T,KeyOfT>&t)
{
_root=Copy(t._root);
}
Node* Copy(Node* root)
{
if(root==nullptr)
{
return nullptr;
}
//前序遍历
Node* newRoot=new Node(root->_data);
newRoot->_col=root->_col;

newRoot->_left=Copy(root->_left);
newRoot->_right=Copy(root->_right);
if(newRoot->_left)
{
newRoot->_left->_parent=newRoot;
}
else if(newRoot->_right)
{
newRoot->_right->_parent=newRoot;
}


return newRoot;
}

RBTree<K,T,KeyOfT>& operator=(RBTree<K,T,KeyOfT> t)
{
swap(_root,t._root);//这里的t是拷贝构造,所以这里的交换不会影响t
return *this;

}
void Destroy(Node* root)
{
if(root==nullptr)
{
return;
}
Destroy(root->_left);
Destroy(root->_right);
delete root;//后序遍历

}
pair<Iterator,bool> Insert(const T &data)
{
if (_root == nullptr)
{
_root = new Node(data);
_root->_col = BLACK;
return make_pair(Iterator(_root),true);
}
//

//因为我们需要知道它的T的参数是什么
//这里我们添加一个
KeyOfT kot; //使用这个来进行比较,仿函数

Node *cur = _root;
Node *parent = nullptr; //还要找到父亲
while (cur)
{
if (kot(cur->_data) > kot(data)) //这里如果是pair,我们就得按照k去比较大小,所以这里我们需要知道它是key还是pair
{
//取出它的有效比较对象来进行比较
parent = cur;
cur = cur->_left;
}
else if (kot(cur->_data) < kot(data)) //比他大,在右边
{
//只要把key取出来就都可以使用这个东西
parent = cur;
cur = cur->_right;
}
else
{
return make_pair(Iterator(cur),false);//这个值存在,就返回这个已近有的节点
}
}
//走到这里,就可以链接上
cur = new Node(data);

Node* newnode=cur;//把这个新节点给保持起来
cur->_col = RED; //新增节点颜色给红色

cur->_parent = parent; //链接上父亲
if (kot(parent->_data) > kot(data)) //父亲的值也能取出来
{
//比他小,在左边
parent->_left = cur;
}
else
{
parent->_right = cur;
}
//插入之前一定是红黑树
//这里就要控制平衡,通过颜色
//插入黑节点(影响路径),还是红节点(只影响自己的,不影响其他区域)

//往上调整
//我为红,父亲如果为红,爷爷一定是黑色
// 1.叔叔存在且为红
while (parent && parent->_col == RED) //往上处理,父亲颜色为红色,就要处理,黑色就不要处理,为红,就不是根
{
Node *grandparent = parent->_parent;
if (parent == grandparent->_left)
{
Node *uncle = grandparent->_right; //叔叔就是在右边
//叔叔存在且为红
if (uncle && uncle->_col == RED)
{
//叔叔存在,且为红
//变色,继续向上处理
parent->_col = BLACK;
uncle->_col = BLACK;
grandparent->_col = RED;

cur = grandparent; //继续迭代往上操作
parent = cur->_parent;
}

//叔叔不存在
else //不存在,或存在且为黑
{
//不存在,进行旋转
//旋转+变色
if (cur == parent->_left)
{
RotateR(grandparent); //进行右单旋转
//变色
parent->_col = BLACK;
grandparent->_col = RED;
}
else
{
//双旋
//左右双旋
// p进行右单旋,g左单旋,g变红藕,cur变黑,
RotateL(parent);
RotateR(grandparent);
cur->_col = BLACK;
grandparent->_col = RED;
}
break;
}
}
else //父亲是祖父的右边
{
Node *uncle = grandparent->_left; //叔叔就是在右边
//叔叔存在且为红
if (uncle && uncle->_col == RED)
{
//叔叔存在,且为红
//变色,继续向上处理
parent->_col = BLACK;
uncle->_col = BLACK;
grandparent->_col = RED;

cur = grandparent; //继续迭代往上操作
parent = cur->_parent;
}

//叔叔不存在
else //不存在,或存在且为黑
{
//不存在,进行旋转
//旋转+变色
if (cur == parent->_right)
{
RotateL(grandparent); //进行右单旋转
//变色
parent->_col = BLACK;
grandparent->_col = RED;
}
else
{
RotateR(parent);
RotateL(grandparent);
cur->_col = BLACK;
grandparent->_col = RED;
}
break;
}
}
}
_root->_col = BLACK; //根的一定是黑色

return make_pair(Iterator(newnode),true);
}
};

map

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
#pragma once
#include "RBtree.hpp"

namespace xzw
{
template <class K, class V>
class map
{

public:
struct MapKeyOfT //仿函数,泛型编程,复用同一棵树
{
const K &operator()(const pair<K, V> &kv)
{
return kv.first; //返回的是第一个参数
}
};

typedef typename RBTree<K, pair<K, V>, MapKeyOfT>::Iterator Iterator;//对于一个类型的使用,我们就要声明,不然编译器以为是一个变量

Iterator begin()
{
return _t.begin();
}
Iterator end()
{
return _t.end();
}

pair<Iterator,bool> insert(const pair<K, V> &kv)
{
return _t.Insert(kv);
}


V& operator[](const K&key)
{
auto ret=_t.Insert(make_pair(key,V()));
return ret.first->second;
}
private:
RBTree<K, pair<K, V>, MapKeyOfT> _t; //用第二个模板参数来控制
};

};

set

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
#pragma once
#include "RBtree.hpp"

namespace xzw
{
template <class K>
class set
{

public:
struct SetKeyOfT //仿函数
{
const K &operator()(const K &k)
{
return k; //返回的是第一个参数
}
};
typedef typename RBTree<K, K, SetKeyOfT>::Iterator Iterator; //取出它的内嵌类型,再进行重命名

Iterator begin()
{
return _t.begin();
}
Iterator end()
{
return _t.end();
}
Iterator Find(const K& key)
{
return _t.Find(key);
}
pair<Iterator,bool> insert(const K &key)
{
return _t.Insert(key);
}


private:
RBTree<K, K, SetKeyOfT> _t; //用第二个模板参数来控制
};

};

map和set的实现
http://example.com/2022/09/18/map和set的实现/
作者
Zevin
发布于
2022年9月18日
许可协议