root / lab4 / .minix-src / include / c++ / __tree
History | View | Annotate | Download (82 KB)
1 | 13 | up20180614 | // -*- C++ -*- |
---|---|---|---|
2 | //===----------------------------------------------------------------------===// |
||
3 | // |
||
4 | // The LLVM Compiler Infrastructure |
||
5 | // |
||
6 | // This file is dual licensed under the MIT and the University of Illinois Open |
||
7 | // Source Licenses. See LICENSE.TXT for details. |
||
8 | // |
||
9 | //===----------------------------------------------------------------------===// |
||
10 | |||
11 | #ifndef _LIBCPP___TREE |
||
12 | #define _LIBCPP___TREE |
||
13 | |||
14 | #include <__config> |
||
15 | #include <iterator> |
||
16 | #include <memory> |
||
17 | #include <stdexcept> |
||
18 | #include <algorithm> |
||
19 | |||
20 | #if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) |
||
21 | #pragma GCC system_header |
||
22 | #endif |
||
23 | |||
24 | _LIBCPP_BEGIN_NAMESPACE_STD |
||
25 | |||
26 | template <class _Tp, class _Compare, class _Allocator> class __tree; |
||
27 | template <class _Tp, class _NodePtr, class _DiffType> |
||
28 | class _LIBCPP_TYPE_VIS_ONLY __tree_iterator; |
||
29 | template <class _Tp, class _ConstNodePtr, class _DiffType> |
||
30 | class _LIBCPP_TYPE_VIS_ONLY __tree_const_iterator; |
||
31 | |||
32 | /* |
||
33 | |||
34 | _NodePtr algorithms |
||
35 | |||
36 | The algorithms taking _NodePtr are red black tree algorithms. Those |
||
37 | algorithms taking a parameter named __root should assume that __root |
||
38 | points to a proper red black tree (unless otherwise specified). |
||
39 | |||
40 | Each algorithm herein assumes that __root->__parent_ points to a non-null |
||
41 | structure which has a member __left_ which points back to __root. No other |
||
42 | member is read or written to at __root->__parent_. |
||
43 | |||
44 | __root->__parent_ will be referred to below (in comments only) as end_node. |
||
45 | end_node->__left_ is an externably accessible lvalue for __root, and can be |
||
46 | changed by node insertion and removal (without explicit reference to end_node). |
||
47 | |||
48 | All nodes (with the exception of end_node), even the node referred to as |
||
49 | __root, have a non-null __parent_ field. |
||
50 | |||
51 | */ |
||
52 | |||
53 | // Returns: true if __x is a left child of its parent, else false |
||
54 | // Precondition: __x != nullptr. |
||
55 | template <class _NodePtr> |
||
56 | inline _LIBCPP_INLINE_VISIBILITY |
||
57 | bool |
||
58 | __tree_is_left_child(_NodePtr __x) _NOEXCEPT |
||
59 | { |
||
60 | return __x == __x->__parent_->__left_; |
||
61 | } |
||
62 | |||
63 | // Determintes if the subtree rooted at __x is a proper red black subtree. If |
||
64 | // __x is a proper subtree, returns the black height (null counts as 1). If |
||
65 | // __x is an improper subtree, returns 0. |
||
66 | template <class _NodePtr> |
||
67 | unsigned |
||
68 | __tree_sub_invariant(_NodePtr __x) |
||
69 | { |
||
70 | if (__x == nullptr) |
||
71 | return 1; |
||
72 | // parent consistency checked by caller |
||
73 | // check __x->__left_ consistency |
||
74 | if (__x->__left_ != nullptr && __x->__left_->__parent_ != __x) |
||
75 | return 0; |
||
76 | // check __x->__right_ consistency |
||
77 | if (__x->__right_ != nullptr && __x->__right_->__parent_ != __x) |
||
78 | return 0; |
||
79 | // check __x->__left_ != __x->__right_ unless both are nullptr |
||
80 | if (__x->__left_ == __x->__right_ && __x->__left_ != nullptr) |
||
81 | return 0; |
||
82 | // If this is red, neither child can be red |
||
83 | if (!__x->__is_black_) |
||
84 | { |
||
85 | if (__x->__left_ && !__x->__left_->__is_black_) |
||
86 | return 0; |
||
87 | if (__x->__right_ && !__x->__right_->__is_black_) |
||
88 | return 0; |
||
89 | } |
||
90 | unsigned __h = __tree_sub_invariant(__x->__left_); |
||
91 | if (__h == 0) |
||
92 | return 0; // invalid left subtree |
||
93 | if (__h != __tree_sub_invariant(__x->__right_)) |
||
94 | return 0; // invalid or different height right subtree |
||
95 | return __h + __x->__is_black_; // return black height of this node |
||
96 | } |
||
97 | |||
98 | // Determintes if the red black tree rooted at __root is a proper red black tree. |
||
99 | // __root == nullptr is a proper tree. Returns true is __root is a proper |
||
100 | // red black tree, else returns false. |
||
101 | template <class _NodePtr> |
||
102 | bool |
||
103 | __tree_invariant(_NodePtr __root) |
||
104 | { |
||
105 | if (__root == nullptr) |
||
106 | return true; |
||
107 | // check __x->__parent_ consistency |
||
108 | if (__root->__parent_ == nullptr) |
||
109 | return false; |
||
110 | if (!__tree_is_left_child(__root)) |
||
111 | return false; |
||
112 | // root must be black |
||
113 | if (!__root->__is_black_) |
||
114 | return false; |
||
115 | // do normal node checks |
||
116 | return __tree_sub_invariant(__root) != 0; |
||
117 | } |
||
118 | |||
119 | // Returns: pointer to the left-most node under __x. |
||
120 | // Precondition: __x != nullptr. |
||
121 | template <class _NodePtr> |
||
122 | inline _LIBCPP_INLINE_VISIBILITY |
||
123 | _NodePtr |
||
124 | __tree_min(_NodePtr __x) _NOEXCEPT |
||
125 | { |
||
126 | while (__x->__left_ != nullptr) |
||
127 | __x = __x->__left_; |
||
128 | return __x; |
||
129 | } |
||
130 | |||
131 | // Returns: pointer to the right-most node under __x. |
||
132 | // Precondition: __x != nullptr. |
||
133 | template <class _NodePtr> |
||
134 | inline _LIBCPP_INLINE_VISIBILITY |
||
135 | _NodePtr |
||
136 | __tree_max(_NodePtr __x) _NOEXCEPT |
||
137 | { |
||
138 | while (__x->__right_ != nullptr) |
||
139 | __x = __x->__right_; |
||
140 | return __x; |
||
141 | } |
||
142 | |||
143 | // Returns: pointer to the next in-order node after __x. |
||
144 | // Precondition: __x != nullptr. |
||
145 | template <class _NodePtr> |
||
146 | _NodePtr |
||
147 | __tree_next(_NodePtr __x) _NOEXCEPT |
||
148 | { |
||
149 | if (__x->__right_ != nullptr) |
||
150 | return __tree_min(__x->__right_); |
||
151 | while (!__tree_is_left_child(__x)) |
||
152 | __x = __x->__parent_; |
||
153 | return __x->__parent_; |
||
154 | } |
||
155 | |||
156 | // Returns: pointer to the previous in-order node before __x. |
||
157 | // Precondition: __x != nullptr. |
||
158 | template <class _NodePtr> |
||
159 | _NodePtr |
||
160 | __tree_prev(_NodePtr __x) _NOEXCEPT |
||
161 | { |
||
162 | if (__x->__left_ != nullptr) |
||
163 | return __tree_max(__x->__left_); |
||
164 | while (__tree_is_left_child(__x)) |
||
165 | __x = __x->__parent_; |
||
166 | return __x->__parent_; |
||
167 | } |
||
168 | |||
169 | // Returns: pointer to a node which has no children |
||
170 | // Precondition: __x != nullptr. |
||
171 | template <class _NodePtr> |
||
172 | _NodePtr |
||
173 | __tree_leaf(_NodePtr __x) _NOEXCEPT |
||
174 | { |
||
175 | while (true) |
||
176 | { |
||
177 | if (__x->__left_ != nullptr) |
||
178 | { |
||
179 | __x = __x->__left_; |
||
180 | continue; |
||
181 | } |
||
182 | if (__x->__right_ != nullptr) |
||
183 | { |
||
184 | __x = __x->__right_; |
||
185 | continue; |
||
186 | } |
||
187 | break; |
||
188 | } |
||
189 | return __x; |
||
190 | } |
||
191 | |||
192 | // Effects: Makes __x->__right_ the subtree root with __x as its left child |
||
193 | // while preserving in-order order. |
||
194 | // Precondition: __x->__right_ != nullptr |
||
195 | template <class _NodePtr> |
||
196 | void |
||
197 | __tree_left_rotate(_NodePtr __x) _NOEXCEPT |
||
198 | { |
||
199 | _NodePtr __y = __x->__right_; |
||
200 | __x->__right_ = __y->__left_; |
||
201 | if (__x->__right_ != nullptr) |
||
202 | __x->__right_->__parent_ = __x; |
||
203 | __y->__parent_ = __x->__parent_; |
||
204 | if (__tree_is_left_child(__x)) |
||
205 | __x->__parent_->__left_ = __y; |
||
206 | else |
||
207 | __x->__parent_->__right_ = __y; |
||
208 | __y->__left_ = __x; |
||
209 | __x->__parent_ = __y; |
||
210 | } |
||
211 | |||
212 | // Effects: Makes __x->__left_ the subtree root with __x as its right child |
||
213 | // while preserving in-order order. |
||
214 | // Precondition: __x->__left_ != nullptr |
||
215 | template <class _NodePtr> |
||
216 | void |
||
217 | __tree_right_rotate(_NodePtr __x) _NOEXCEPT |
||
218 | { |
||
219 | _NodePtr __y = __x->__left_; |
||
220 | __x->__left_ = __y->__right_; |
||
221 | if (__x->__left_ != nullptr) |
||
222 | __x->__left_->__parent_ = __x; |
||
223 | __y->__parent_ = __x->__parent_; |
||
224 | if (__tree_is_left_child(__x)) |
||
225 | __x->__parent_->__left_ = __y; |
||
226 | else |
||
227 | __x->__parent_->__right_ = __y; |
||
228 | __y->__right_ = __x; |
||
229 | __x->__parent_ = __y; |
||
230 | } |
||
231 | |||
232 | // Effects: Rebalances __root after attaching __x to a leaf. |
||
233 | // Precondition: __root != nulptr && __x != nullptr. |
||
234 | // __x has no children. |
||
235 | // __x == __root or == a direct or indirect child of __root. |
||
236 | // If __x were to be unlinked from __root (setting __root to |
||
237 | // nullptr if __root == __x), __tree_invariant(__root) == true. |
||
238 | // Postcondition: __tree_invariant(end_node->__left_) == true. end_node->__left_ |
||
239 | // may be different than the value passed in as __root. |
||
240 | template <class _NodePtr> |
||
241 | void |
||
242 | __tree_balance_after_insert(_NodePtr __root, _NodePtr __x) _NOEXCEPT |
||
243 | { |
||
244 | __x->__is_black_ = __x == __root; |
||
245 | while (__x != __root && !__x->__parent_->__is_black_) |
||
246 | { |
||
247 | // __x->__parent_ != __root because __x->__parent_->__is_black == false |
||
248 | if (__tree_is_left_child(__x->__parent_)) |
||
249 | { |
||
250 | _NodePtr __y = __x->__parent_->__parent_->__right_; |
||
251 | if (__y != nullptr && !__y->__is_black_) |
||
252 | { |
||
253 | __x = __x->__parent_; |
||
254 | __x->__is_black_ = true; |
||
255 | __x = __x->__parent_; |
||
256 | __x->__is_black_ = __x == __root; |
||
257 | __y->__is_black_ = true; |
||
258 | } |
||
259 | else |
||
260 | { |
||
261 | if (!__tree_is_left_child(__x)) |
||
262 | { |
||
263 | __x = __x->__parent_; |
||
264 | __tree_left_rotate(__x); |
||
265 | } |
||
266 | __x = __x->__parent_; |
||
267 | __x->__is_black_ = true; |
||
268 | __x = __x->__parent_; |
||
269 | __x->__is_black_ = false; |
||
270 | __tree_right_rotate(__x); |
||
271 | break; |
||
272 | } |
||
273 | } |
||
274 | else |
||
275 | { |
||
276 | _NodePtr __y = __x->__parent_->__parent_->__left_; |
||
277 | if (__y != nullptr && !__y->__is_black_) |
||
278 | { |
||
279 | __x = __x->__parent_; |
||
280 | __x->__is_black_ = true; |
||
281 | __x = __x->__parent_; |
||
282 | __x->__is_black_ = __x == __root; |
||
283 | __y->__is_black_ = true; |
||
284 | } |
||
285 | else |
||
286 | { |
||
287 | if (__tree_is_left_child(__x)) |
||
288 | { |
||
289 | __x = __x->__parent_; |
||
290 | __tree_right_rotate(__x); |
||
291 | } |
||
292 | __x = __x->__parent_; |
||
293 | __x->__is_black_ = true; |
||
294 | __x = __x->__parent_; |
||
295 | __x->__is_black_ = false; |
||
296 | __tree_left_rotate(__x); |
||
297 | break; |
||
298 | } |
||
299 | } |
||
300 | } |
||
301 | } |
||
302 | |||
303 | // Precondition: __root != nullptr && __z != nullptr. |
||
304 | // __tree_invariant(__root) == true. |
||
305 | // __z == __root or == a direct or indirect child of __root. |
||
306 | // Effects: unlinks __z from the tree rooted at __root, rebalancing as needed. |
||
307 | // Postcondition: __tree_invariant(end_node->__left_) == true && end_node->__left_ |
||
308 | // nor any of its children refer to __z. end_node->__left_ |
||
309 | // may be different than the value passed in as __root. |
||
310 | template <class _NodePtr> |
||
311 | void |
||
312 | __tree_remove(_NodePtr __root, _NodePtr __z) _NOEXCEPT |
||
313 | { |
||
314 | // __z will be removed from the tree. Client still needs to destruct/deallocate it |
||
315 | // __y is either __z, or if __z has two children, __tree_next(__z). |
||
316 | // __y will have at most one child. |
||
317 | // __y will be the initial hole in the tree (make the hole at a leaf) |
||
318 | _NodePtr __y = (__z->__left_ == nullptr || __z->__right_ == nullptr) ? |
||
319 | __z : __tree_next(__z); |
||
320 | // __x is __y's possibly null single child |
||
321 | _NodePtr __x = __y->__left_ != nullptr ? __y->__left_ : __y->__right_; |
||
322 | // __w is __x's possibly null uncle (will become __x's sibling) |
||
323 | _NodePtr __w = nullptr; |
||
324 | // link __x to __y's parent, and find __w |
||
325 | if (__x != nullptr) |
||
326 | __x->__parent_ = __y->__parent_; |
||
327 | if (__tree_is_left_child(__y)) |
||
328 | { |
||
329 | __y->__parent_->__left_ = __x; |
||
330 | if (__y != __root) |
||
331 | __w = __y->__parent_->__right_; |
||
332 | else |
||
333 | __root = __x; // __w == nullptr |
||
334 | } |
||
335 | else |
||
336 | { |
||
337 | __y->__parent_->__right_ = __x; |
||
338 | // __y can't be root if it is a right child |
||
339 | __w = __y->__parent_->__left_; |
||
340 | } |
||
341 | bool __removed_black = __y->__is_black_; |
||
342 | // If we didn't remove __z, do so now by splicing in __y for __z, |
||
343 | // but copy __z's color. This does not impact __x or __w. |
||
344 | if (__y != __z) |
||
345 | { |
||
346 | // __z->__left_ != nulptr but __z->__right_ might == __x == nullptr |
||
347 | __y->__parent_ = __z->__parent_; |
||
348 | if (__tree_is_left_child(__z)) |
||
349 | __y->__parent_->__left_ = __y; |
||
350 | else |
||
351 | __y->__parent_->__right_ = __y; |
||
352 | __y->__left_ = __z->__left_; |
||
353 | __y->__left_->__parent_ = __y; |
||
354 | __y->__right_ = __z->__right_; |
||
355 | if (__y->__right_ != nullptr) |
||
356 | __y->__right_->__parent_ = __y; |
||
357 | __y->__is_black_ = __z->__is_black_; |
||
358 | if (__root == __z) |
||
359 | __root = __y; |
||
360 | } |
||
361 | // There is no need to rebalance if we removed a red, or if we removed |
||
362 | // the last node. |
||
363 | if (__removed_black && __root != nullptr) |
||
364 | { |
||
365 | // Rebalance: |
||
366 | // __x has an implicit black color (transferred from the removed __y) |
||
367 | // associated with it, no matter what its color is. |
||
368 | // If __x is __root (in which case it can't be null), it is supposed |
||
369 | // to be black anyway, and if it is doubly black, then the double |
||
370 | // can just be ignored. |
||
371 | // If __x is red (in which case it can't be null), then it can absorb |
||
372 | // the implicit black just by setting its color to black. |
||
373 | // Since __y was black and only had one child (which __x points to), __x |
||
374 | // is either red with no children, else null, otherwise __y would have |
||
375 | // different black heights under left and right pointers. |
||
376 | // if (__x == __root || __x != nullptr && !__x->__is_black_) |
||
377 | if (__x != nullptr) |
||
378 | __x->__is_black_ = true; |
||
379 | else |
||
380 | { |
||
381 | // Else __x isn't root, and is "doubly black", even though it may |
||
382 | // be null. __w can not be null here, else the parent would |
||
383 | // see a black height >= 2 on the __x side and a black height |
||
384 | // of 1 on the __w side (__w must be a non-null black or a red |
||
385 | // with a non-null black child). |
||
386 | while (true) |
||
387 | { |
||
388 | if (!__tree_is_left_child(__w)) // if x is left child |
||
389 | { |
||
390 | if (!__w->__is_black_) |
||
391 | { |
||
392 | __w->__is_black_ = true; |
||
393 | __w->__parent_->__is_black_ = false; |
||
394 | __tree_left_rotate(__w->__parent_); |
||
395 | // __x is still valid |
||
396 | // reset __root only if necessary |
||
397 | if (__root == __w->__left_) |
||
398 | __root = __w; |
||
399 | // reset sibling, and it still can't be null |
||
400 | __w = __w->__left_->__right_; |
||
401 | } |
||
402 | // __w->__is_black_ is now true, __w may have null children |
||
403 | if ((__w->__left_ == nullptr || __w->__left_->__is_black_) && |
||
404 | (__w->__right_ == nullptr || __w->__right_->__is_black_)) |
||
405 | { |
||
406 | __w->__is_black_ = false; |
||
407 | __x = __w->__parent_; |
||
408 | // __x can no longer be null |
||
409 | if (__x == __root || !__x->__is_black_) |
||
410 | { |
||
411 | __x->__is_black_ = true; |
||
412 | break; |
||
413 | } |
||
414 | // reset sibling, and it still can't be null |
||
415 | __w = __tree_is_left_child(__x) ? |
||
416 | __x->__parent_->__right_ : |
||
417 | __x->__parent_->__left_; |
||
418 | // continue; |
||
419 | } |
||
420 | else // __w has a red child |
||
421 | { |
||
422 | if (__w->__right_ == nullptr || __w->__right_->__is_black_) |
||
423 | { |
||
424 | // __w left child is non-null and red |
||
425 | __w->__left_->__is_black_ = true; |
||
426 | __w->__is_black_ = false; |
||
427 | __tree_right_rotate(__w); |
||
428 | // __w is known not to be root, so root hasn't changed |
||
429 | // reset sibling, and it still can't be null |
||
430 | __w = __w->__parent_; |
||
431 | } |
||
432 | // __w has a right red child, left child may be null |
||
433 | __w->__is_black_ = __w->__parent_->__is_black_; |
||
434 | __w->__parent_->__is_black_ = true; |
||
435 | __w->__right_->__is_black_ = true; |
||
436 | __tree_left_rotate(__w->__parent_); |
||
437 | break; |
||
438 | } |
||
439 | } |
||
440 | else |
||
441 | { |
||
442 | if (!__w->__is_black_) |
||
443 | { |
||
444 | __w->__is_black_ = true; |
||
445 | __w->__parent_->__is_black_ = false; |
||
446 | __tree_right_rotate(__w->__parent_); |
||
447 | // __x is still valid |
||
448 | // reset __root only if necessary |
||
449 | if (__root == __w->__right_) |
||
450 | __root = __w; |
||
451 | // reset sibling, and it still can't be null |
||
452 | __w = __w->__right_->__left_; |
||
453 | } |
||
454 | // __w->__is_black_ is now true, __w may have null children |
||
455 | if ((__w->__left_ == nullptr || __w->__left_->__is_black_) && |
||
456 | (__w->__right_ == nullptr || __w->__right_->__is_black_)) |
||
457 | { |
||
458 | __w->__is_black_ = false; |
||
459 | __x = __w->__parent_; |
||
460 | // __x can no longer be null |
||
461 | if (!__x->__is_black_ || __x == __root) |
||
462 | { |
||
463 | __x->__is_black_ = true; |
||
464 | break; |
||
465 | } |
||
466 | // reset sibling, and it still can't be null |
||
467 | __w = __tree_is_left_child(__x) ? |
||
468 | __x->__parent_->__right_ : |
||
469 | __x->__parent_->__left_; |
||
470 | // continue; |
||
471 | } |
||
472 | else // __w has a red child |
||
473 | { |
||
474 | if (__w->__left_ == nullptr || __w->__left_->__is_black_) |
||
475 | { |
||
476 | // __w right child is non-null and red |
||
477 | __w->__right_->__is_black_ = true; |
||
478 | __w->__is_black_ = false; |
||
479 | __tree_left_rotate(__w); |
||
480 | // __w is known not to be root, so root hasn't changed |
||
481 | // reset sibling, and it still can't be null |
||
482 | __w = __w->__parent_; |
||
483 | } |
||
484 | // __w has a left red child, right child may be null |
||
485 | __w->__is_black_ = __w->__parent_->__is_black_; |
||
486 | __w->__parent_->__is_black_ = true; |
||
487 | __w->__left_->__is_black_ = true; |
||
488 | __tree_right_rotate(__w->__parent_); |
||
489 | break; |
||
490 | } |
||
491 | } |
||
492 | } |
||
493 | } |
||
494 | } |
||
495 | } |
||
496 | |||
497 | template <class _Allocator> class __map_node_destructor; |
||
498 | |||
499 | template <class _Allocator> |
||
500 | class __tree_node_destructor |
||
501 | { |
||
502 | typedef _Allocator allocator_type; |
||
503 | typedef allocator_traits<allocator_type> __alloc_traits; |
||
504 | typedef typename __alloc_traits::value_type::value_type value_type; |
||
505 | public: |
||
506 | typedef typename __alloc_traits::pointer pointer; |
||
507 | private: |
||
508 | |||
509 | allocator_type& __na_; |
||
510 | |||
511 | __tree_node_destructor& operator=(const __tree_node_destructor&); |
||
512 | |||
513 | public: |
||
514 | bool __value_constructed; |
||
515 | |||
516 | _LIBCPP_INLINE_VISIBILITY |
||
517 | explicit __tree_node_destructor(allocator_type& __na, bool __val = false) _NOEXCEPT |
||
518 | : __na_(__na), |
||
519 | __value_constructed(__val) |
||
520 | {} |
||
521 | |||
522 | _LIBCPP_INLINE_VISIBILITY |
||
523 | void operator()(pointer __p) _NOEXCEPT |
||
524 | { |
||
525 | if (__value_constructed) |
||
526 | __alloc_traits::destroy(__na_, _VSTD::addressof(__p->__value_)); |
||
527 | if (__p) |
||
528 | __alloc_traits::deallocate(__na_, __p, 1); |
||
529 | } |
||
530 | |||
531 | template <class> friend class __map_node_destructor; |
||
532 | }; |
||
533 | |||
534 | // node |
||
535 | |||
536 | template <class _Pointer> |
||
537 | class __tree_end_node |
||
538 | { |
||
539 | public: |
||
540 | typedef _Pointer pointer; |
||
541 | pointer __left_; |
||
542 | |||
543 | _LIBCPP_INLINE_VISIBILITY |
||
544 | __tree_end_node() _NOEXCEPT : __left_() {} |
||
545 | }; |
||
546 | |||
547 | template <class _VoidPtr> |
||
548 | class __tree_node_base |
||
549 | : public __tree_end_node |
||
550 | < |
||
551 | typename pointer_traits<_VoidPtr>::template |
||
552 | #ifndef _LIBCPP_HAS_NO_TEMPLATE_ALIASES |
||
553 | rebind<__tree_node_base<_VoidPtr> > |
||
554 | #else |
||
555 | rebind<__tree_node_base<_VoidPtr> >::other |
||
556 | #endif |
||
557 | > |
||
558 | { |
||
559 | __tree_node_base(const __tree_node_base&); |
||
560 | __tree_node_base& operator=(const __tree_node_base&); |
||
561 | public: |
||
562 | typedef typename pointer_traits<_VoidPtr>::template |
||
563 | #ifndef _LIBCPP_HAS_NO_TEMPLATE_ALIASES |
||
564 | rebind<__tree_node_base> |
||
565 | #else |
||
566 | rebind<__tree_node_base>::other |
||
567 | #endif |
||
568 | pointer; |
||
569 | typedef typename pointer_traits<_VoidPtr>::template |
||
570 | #ifndef _LIBCPP_HAS_NO_TEMPLATE_ALIASES |
||
571 | rebind<const __tree_node_base> |
||
572 | #else |
||
573 | rebind<const __tree_node_base>::other |
||
574 | #endif |
||
575 | const_pointer; |
||
576 | typedef __tree_end_node<pointer> base; |
||
577 | |||
578 | pointer __right_; |
||
579 | pointer __parent_; |
||
580 | bool __is_black_; |
||
581 | |||
582 | _LIBCPP_INLINE_VISIBILITY |
||
583 | __tree_node_base() _NOEXCEPT |
||
584 | : __right_(), __parent_(), __is_black_(false) {} |
||
585 | }; |
||
586 | |||
587 | template <class _Tp, class _VoidPtr> |
||
588 | class __tree_node |
||
589 | : public __tree_node_base<_VoidPtr> |
||
590 | { |
||
591 | public: |
||
592 | typedef __tree_node_base<_VoidPtr> base; |
||
593 | typedef _Tp value_type; |
||
594 | |||
595 | value_type __value_; |
||
596 | |||
597 | #if !defined(_LIBCPP_HAS_NO_RVALUE_REFERENCES) && !defined(_LIBCPP_HAS_NO_VARIADICS) |
||
598 | template <class ..._Args> |
||
599 | _LIBCPP_INLINE_VISIBILITY |
||
600 | explicit __tree_node(_Args&& ...__args) |
||
601 | : __value_(_VSTD::forward<_Args>(__args)...) {} |
||
602 | #else // !defined(_LIBCPP_HAS_NO_RVALUE_REFERENCES) && !defined(_LIBCPP_HAS_NO_VARIADICS) |
||
603 | _LIBCPP_INLINE_VISIBILITY |
||
604 | explicit __tree_node(const value_type& __v) |
||
605 | : __value_(__v) {} |
||
606 | #endif // !defined(_LIBCPP_HAS_NO_RVALUE_REFERENCES) && !defined(_LIBCPP_HAS_NO_VARIADICS) |
||
607 | }; |
||
608 | |||
609 | template <class _TreeIterator> class _LIBCPP_TYPE_VIS_ONLY __map_iterator; |
||
610 | template <class _TreeIterator> class _LIBCPP_TYPE_VIS_ONLY __map_const_iterator; |
||
611 | |||
612 | template <class _Tp, class _NodePtr, class _DiffType> |
||
613 | class _LIBCPP_TYPE_VIS_ONLY __tree_iterator |
||
614 | { |
||
615 | typedef _NodePtr __node_pointer; |
||
616 | typedef typename pointer_traits<__node_pointer>::element_type __node; |
||
617 | |||
618 | __node_pointer __ptr_; |
||
619 | |||
620 | typedef pointer_traits<__node_pointer> __pointer_traits; |
||
621 | public: |
||
622 | typedef bidirectional_iterator_tag iterator_category; |
||
623 | typedef _Tp value_type; |
||
624 | typedef _DiffType difference_type; |
||
625 | typedef value_type& reference; |
||
626 | typedef typename pointer_traits<__node_pointer>::template |
||
627 | #ifndef _LIBCPP_HAS_NO_TEMPLATE_ALIASES |
||
628 | rebind<value_type> |
||
629 | #else |
||
630 | rebind<value_type>::other |
||
631 | #endif |
||
632 | pointer; |
||
633 | |||
634 | _LIBCPP_INLINE_VISIBILITY __tree_iterator() _NOEXCEPT |
||
635 | #if _LIBCPP_STD_VER > 11 |
||
636 | : __ptr_(nullptr) |
||
637 | #endif |
||
638 | {} |
||
639 | |||
640 | _LIBCPP_INLINE_VISIBILITY reference operator*() const {return __ptr_->__value_;} |
||
641 | _LIBCPP_INLINE_VISIBILITY pointer operator->() const |
||
642 | {return pointer_traits<pointer>::pointer_to(__ptr_->__value_);} |
||
643 | |||
644 | _LIBCPP_INLINE_VISIBILITY |
||
645 | __tree_iterator& operator++() { |
||
646 | __ptr_ = static_cast<__node_pointer>( |
||
647 | __tree_next(static_cast<typename __node::base::pointer>(__ptr_))); |
||
648 | return *this; |
||
649 | } |
||
650 | _LIBCPP_INLINE_VISIBILITY |
||
651 | __tree_iterator operator++(int) |
||
652 | {__tree_iterator __t(*this); ++(*this); return __t;} |
||
653 | |||
654 | _LIBCPP_INLINE_VISIBILITY |
||
655 | __tree_iterator& operator--() { |
||
656 | __ptr_ = static_cast<__node_pointer>( |
||
657 | __tree_prev(static_cast<typename __node::base::pointer>(__ptr_))); |
||
658 | return *this; |
||
659 | } |
||
660 | _LIBCPP_INLINE_VISIBILITY |
||
661 | __tree_iterator operator--(int) |
||
662 | {__tree_iterator __t(*this); --(*this); return __t;} |
||
663 | |||
664 | friend _LIBCPP_INLINE_VISIBILITY |
||
665 | bool operator==(const __tree_iterator& __x, const __tree_iterator& __y) |
||
666 | {return __x.__ptr_ == __y.__ptr_;} |
||
667 | friend _LIBCPP_INLINE_VISIBILITY |
||
668 | bool operator!=(const __tree_iterator& __x, const __tree_iterator& __y) |
||
669 | {return !(__x == __y);} |
||
670 | |||
671 | private: |
||
672 | _LIBCPP_INLINE_VISIBILITY |
||
673 | explicit __tree_iterator(__node_pointer __p) _NOEXCEPT : __ptr_(__p) {} |
||
674 | template <class, class, class> friend class __tree; |
||
675 | template <class, class, class> friend class _LIBCPP_TYPE_VIS_ONLY __tree_const_iterator; |
||
676 | template <class> friend class _LIBCPP_TYPE_VIS_ONLY __map_iterator; |
||
677 | template <class, class, class, class> friend class _LIBCPP_TYPE_VIS_ONLY map; |
||
678 | template <class, class, class, class> friend class _LIBCPP_TYPE_VIS_ONLY multimap; |
||
679 | template <class, class, class> friend class _LIBCPP_TYPE_VIS_ONLY set; |
||
680 | template <class, class, class> friend class _LIBCPP_TYPE_VIS_ONLY multiset; |
||
681 | }; |
||
682 | |||
683 | template <class _Tp, class _ConstNodePtr, class _DiffType> |
||
684 | class _LIBCPP_TYPE_VIS_ONLY __tree_const_iterator |
||
685 | { |
||
686 | typedef _ConstNodePtr __node_pointer; |
||
687 | typedef typename pointer_traits<__node_pointer>::element_type __node; |
||
688 | |||
689 | __node_pointer __ptr_; |
||
690 | |||
691 | typedef pointer_traits<__node_pointer> __pointer_traits; |
||
692 | public: |
||
693 | typedef bidirectional_iterator_tag iterator_category; |
||
694 | typedef _Tp value_type; |
||
695 | typedef _DiffType difference_type; |
||
696 | typedef const value_type& reference; |
||
697 | typedef typename pointer_traits<__node_pointer>::template |
||
698 | #ifndef _LIBCPP_HAS_NO_TEMPLATE_ALIASES |
||
699 | rebind<const value_type> |
||
700 | #else |
||
701 | rebind<const value_type>::other |
||
702 | #endif |
||
703 | pointer; |
||
704 | |||
705 | _LIBCPP_INLINE_VISIBILITY __tree_const_iterator() _NOEXCEPT |
||
706 | #if _LIBCPP_STD_VER > 11 |
||
707 | : __ptr_(nullptr) |
||
708 | #endif |
||
709 | {} |
||
710 | |||
711 | private: |
||
712 | typedef typename remove_const<__node>::type __non_const_node; |
||
713 | typedef typename pointer_traits<__node_pointer>::template |
||
714 | #ifndef _LIBCPP_HAS_NO_TEMPLATE_ALIASES |
||
715 | rebind<__non_const_node> |
||
716 | #else |
||
717 | rebind<__non_const_node>::other |
||
718 | #endif |
||
719 | __non_const_node_pointer; |
||
720 | typedef __tree_iterator<value_type, __non_const_node_pointer, difference_type> |
||
721 | __non_const_iterator; |
||
722 | public: |
||
723 | _LIBCPP_INLINE_VISIBILITY |
||
724 | __tree_const_iterator(__non_const_iterator __p) _NOEXCEPT |
||
725 | : __ptr_(__p.__ptr_) {} |
||
726 | |||
727 | _LIBCPP_INLINE_VISIBILITY reference operator*() const {return __ptr_->__value_;} |
||
728 | _LIBCPP_INLINE_VISIBILITY pointer operator->() const |
||
729 | {return pointer_traits<pointer>::pointer_to(__ptr_->__value_);} |
||
730 | |||
731 | _LIBCPP_INLINE_VISIBILITY |
||
732 | __tree_const_iterator& operator++() { |
||
733 | typedef typename pointer_traits<__node_pointer>::template |
||
734 | #ifndef _LIBCPP_HAS_NO_TEMPLATE_ALIASES |
||
735 | rebind<typename __node::base> |
||
736 | #else |
||
737 | rebind<typename __node::base>::other |
||
738 | #endif |
||
739 | __node_base_pointer; |
||
740 | |||
741 | __ptr_ = static_cast<__node_pointer>( |
||
742 | __tree_next(static_cast<__node_base_pointer>(__ptr_))); |
||
743 | return *this; |
||
744 | } |
||
745 | |||
746 | _LIBCPP_INLINE_VISIBILITY |
||
747 | __tree_const_iterator operator++(int) |
||
748 | {__tree_const_iterator __t(*this); ++(*this); return __t;} |
||
749 | |||
750 | _LIBCPP_INLINE_VISIBILITY |
||
751 | __tree_const_iterator& operator--() { |
||
752 | typedef typename pointer_traits<__node_pointer>::template |
||
753 | #ifndef _LIBCPP_HAS_NO_TEMPLATE_ALIASES |
||
754 | rebind<typename __node::base> |
||
755 | #else |
||
756 | rebind<typename __node::base>::other |
||
757 | #endif |
||
758 | __node_base_pointer; |
||
759 | |||
760 | __ptr_ = static_cast<__node_pointer>( |
||
761 | __tree_prev(static_cast<__node_base_pointer>(__ptr_))); |
||
762 | return *this; |
||
763 | } |
||
764 | |||
765 | _LIBCPP_INLINE_VISIBILITY |
||
766 | __tree_const_iterator operator--(int) |
||
767 | {__tree_const_iterator __t(*this); --(*this); return __t;} |
||
768 | |||
769 | friend _LIBCPP_INLINE_VISIBILITY |
||
770 | bool operator==(const __tree_const_iterator& __x, const __tree_const_iterator& __y) |
||
771 | {return __x.__ptr_ == __y.__ptr_;} |
||
772 | friend _LIBCPP_INLINE_VISIBILITY |
||
773 | bool operator!=(const __tree_const_iterator& __x, const __tree_const_iterator& __y) |
||
774 | {return !(__x == __y);} |
||
775 | |||
776 | private: |
||
777 | _LIBCPP_INLINE_VISIBILITY |
||
778 | explicit __tree_const_iterator(__node_pointer __p) _NOEXCEPT |
||
779 | : __ptr_(__p) {} |
||
780 | template <class, class, class> friend class __tree; |
||
781 | template <class, class, class, class> friend class _LIBCPP_TYPE_VIS_ONLY map; |
||
782 | template <class, class, class, class> friend class _LIBCPP_TYPE_VIS_ONLY multimap; |
||
783 | template <class, class, class> friend class _LIBCPP_TYPE_VIS_ONLY set; |
||
784 | template <class, class, class> friend class _LIBCPP_TYPE_VIS_ONLY multiset; |
||
785 | template <class> friend class _LIBCPP_TYPE_VIS_ONLY __map_const_iterator; |
||
786 | }; |
||
787 | |||
788 | template <class _Tp, class _Compare, class _Allocator> |
||
789 | class __tree |
||
790 | { |
||
791 | public: |
||
792 | typedef _Tp value_type; |
||
793 | typedef _Compare value_compare; |
||
794 | typedef _Allocator allocator_type; |
||
795 | typedef allocator_traits<allocator_type> __alloc_traits; |
||
796 | typedef typename __alloc_traits::pointer pointer; |
||
797 | typedef typename __alloc_traits::const_pointer const_pointer; |
||
798 | typedef typename __alloc_traits::size_type size_type; |
||
799 | typedef typename __alloc_traits::difference_type difference_type; |
||
800 | |||
801 | typedef typename __alloc_traits::void_pointer __void_pointer; |
||
802 | |||
803 | typedef __tree_node<value_type, __void_pointer> __node; |
||
804 | typedef __tree_node_base<__void_pointer> __node_base; |
||
805 | typedef typename __rebind_alloc_helper<__alloc_traits, __node>::type __node_allocator; |
||
806 | typedef allocator_traits<__node_allocator> __node_traits; |
||
807 | typedef typename __node_traits::pointer __node_pointer; |
||
808 | typedef typename __node_traits::pointer __node_const_pointer; |
||
809 | typedef typename __node_base::pointer __node_base_pointer; |
||
810 | typedef typename __node_base::pointer __node_base_const_pointer; |
||
811 | private: |
||
812 | typedef typename __node_base::base __end_node_t; |
||
813 | typedef typename pointer_traits<__node_pointer>::template |
||
814 | #ifndef _LIBCPP_HAS_NO_TEMPLATE_ALIASES |
||
815 | rebind<__end_node_t> |
||
816 | #else |
||
817 | rebind<__end_node_t>::other |
||
818 | #endif |
||
819 | __end_node_ptr; |
||
820 | typedef typename pointer_traits<__node_pointer>::template |
||
821 | #ifndef _LIBCPP_HAS_NO_TEMPLATE_ALIASES |
||
822 | rebind<__end_node_t> |
||
823 | #else |
||
824 | rebind<__end_node_t>::other |
||
825 | #endif |
||
826 | __end_node_const_ptr; |
||
827 | |||
828 | __node_pointer __begin_node_; |
||
829 | __compressed_pair<__end_node_t, __node_allocator> __pair1_; |
||
830 | __compressed_pair<size_type, value_compare> __pair3_; |
||
831 | |||
832 | public: |
||
833 | _LIBCPP_INLINE_VISIBILITY |
||
834 | __node_pointer __end_node() _NOEXCEPT |
||
835 | { |
||
836 | return static_cast<__node_pointer> |
||
837 | ( |
||
838 | pointer_traits<__end_node_ptr>::pointer_to(__pair1_.first()) |
||
839 | ); |
||
840 | } |
||
841 | _LIBCPP_INLINE_VISIBILITY |
||
842 | __node_const_pointer __end_node() const _NOEXCEPT |
||
843 | { |
||
844 | return static_cast<__node_const_pointer> |
||
845 | ( |
||
846 | pointer_traits<__end_node_const_ptr>::pointer_to(const_cast<__end_node_t&>(__pair1_.first())) |
||
847 | ); |
||
848 | } |
||
849 | _LIBCPP_INLINE_VISIBILITY |
||
850 | __node_allocator& __node_alloc() _NOEXCEPT {return __pair1_.second();} |
||
851 | private: |
||
852 | _LIBCPP_INLINE_VISIBILITY |
||
853 | const __node_allocator& __node_alloc() const _NOEXCEPT |
||
854 | {return __pair1_.second();} |
||
855 | _LIBCPP_INLINE_VISIBILITY |
||
856 | __node_pointer& __begin_node() _NOEXCEPT {return __begin_node_;} |
||
857 | _LIBCPP_INLINE_VISIBILITY |
||
858 | const __node_pointer& __begin_node() const _NOEXCEPT {return __begin_node_;} |
||
859 | public: |
||
860 | _LIBCPP_INLINE_VISIBILITY |
||
861 | allocator_type __alloc() const _NOEXCEPT |
||
862 | {return allocator_type(__node_alloc());} |
||
863 | private: |
||
864 | _LIBCPP_INLINE_VISIBILITY |
||
865 | size_type& size() _NOEXCEPT {return __pair3_.first();} |
||
866 | public: |
||
867 | _LIBCPP_INLINE_VISIBILITY |
||
868 | const size_type& size() const _NOEXCEPT {return __pair3_.first();} |
||
869 | _LIBCPP_INLINE_VISIBILITY |
||
870 | value_compare& value_comp() _NOEXCEPT {return __pair3_.second();} |
||
871 | _LIBCPP_INLINE_VISIBILITY |
||
872 | const value_compare& value_comp() const _NOEXCEPT |
||
873 | {return __pair3_.second();} |
||
874 | public: |
||
875 | _LIBCPP_INLINE_VISIBILITY |
||
876 | __node_pointer __root() _NOEXCEPT |
||
877 | {return static_cast<__node_pointer> (__end_node()->__left_);} |
||
878 | _LIBCPP_INLINE_VISIBILITY |
||
879 | __node_const_pointer __root() const _NOEXCEPT |
||
880 | {return static_cast<__node_const_pointer>(__end_node()->__left_);} |
||
881 | |||
882 | typedef __tree_iterator<value_type, __node_pointer, difference_type> iterator; |
||
883 | typedef __tree_const_iterator<value_type, __node_pointer, difference_type> const_iterator; |
||
884 | |||
885 | explicit __tree(const value_compare& __comp) |
||
886 | _NOEXCEPT_( |
||
887 | is_nothrow_default_constructible<__node_allocator>::value && |
||
888 | is_nothrow_copy_constructible<value_compare>::value); |
||
889 | explicit __tree(const allocator_type& __a); |
||
890 | __tree(const value_compare& __comp, const allocator_type& __a); |
||
891 | __tree(const __tree& __t); |
||
892 | __tree& operator=(const __tree& __t); |
||
893 | template <class _InputIterator> |
||
894 | void __assign_unique(_InputIterator __first, _InputIterator __last); |
||
895 | template <class _InputIterator> |
||
896 | void __assign_multi(_InputIterator __first, _InputIterator __last); |
||
897 | #ifndef _LIBCPP_HAS_NO_RVALUE_REFERENCES |
||
898 | __tree(__tree&& __t) |
||
899 | _NOEXCEPT_( |
||
900 | is_nothrow_move_constructible<__node_allocator>::value && |
||
901 | is_nothrow_move_constructible<value_compare>::value); |
||
902 | __tree(__tree&& __t, const allocator_type& __a); |
||
903 | __tree& operator=(__tree&& __t) |
||
904 | _NOEXCEPT_( |
||
905 | __node_traits::propagate_on_container_move_assignment::value && |
||
906 | is_nothrow_move_assignable<value_compare>::value && |
||
907 | is_nothrow_move_assignable<__node_allocator>::value); |
||
908 | #endif // _LIBCPP_HAS_NO_RVALUE_REFERENCES |
||
909 | |||
910 | ~__tree(); |
||
911 | |||
912 | _LIBCPP_INLINE_VISIBILITY |
||
913 | iterator begin() _NOEXCEPT {return iterator(__begin_node());} |
||
914 | _LIBCPP_INLINE_VISIBILITY |
||
915 | const_iterator begin() const _NOEXCEPT {return const_iterator(__begin_node());} |
||
916 | _LIBCPP_INLINE_VISIBILITY |
||
917 | iterator end() _NOEXCEPT {return iterator(__end_node());} |
||
918 | _LIBCPP_INLINE_VISIBILITY |
||
919 | const_iterator end() const _NOEXCEPT {return const_iterator(__end_node());} |
||
920 | |||
921 | _LIBCPP_INLINE_VISIBILITY |
||
922 | size_type max_size() const _NOEXCEPT |
||
923 | {return __node_traits::max_size(__node_alloc());} |
||
924 | |||
925 | void clear() _NOEXCEPT; |
||
926 | |||
927 | void swap(__tree& __t) |
||
928 | _NOEXCEPT_( |
||
929 | __is_nothrow_swappable<value_compare>::value |
||
930 | #if _LIBCPP_STD_VER <= 11 |
||
931 | && (!__node_traits::propagate_on_container_swap::value || |
||
932 | __is_nothrow_swappable<__node_allocator>::value) |
||
933 | #endif |
||
934 | ); |
||
935 | |||
936 | #ifndef _LIBCPP_HAS_NO_RVALUE_REFERENCES |
||
937 | #ifndef _LIBCPP_HAS_NO_VARIADICS |
||
938 | template <class... _Args> |
||
939 | pair<iterator, bool> |
||
940 | __emplace_unique(_Args&&... __args); |
||
941 | template <class... _Args> |
||
942 | iterator |
||
943 | __emplace_multi(_Args&&... __args); |
||
944 | |||
945 | template <class... _Args> |
||
946 | iterator |
||
947 | __emplace_hint_unique(const_iterator __p, _Args&&... __args); |
||
948 | template <class... _Args> |
||
949 | iterator |
||
950 | __emplace_hint_multi(const_iterator __p, _Args&&... __args); |
||
951 | #endif // _LIBCPP_HAS_NO_VARIADICS |
||
952 | |||
953 | template <class _Vp> |
||
954 | pair<iterator, bool> __insert_unique(_Vp&& __v); |
||
955 | template <class _Vp> |
||
956 | iterator __insert_unique(const_iterator __p, _Vp&& __v); |
||
957 | template <class _Vp> |
||
958 | iterator __insert_multi(_Vp&& __v); |
||
959 | template <class _Vp> |
||
960 | iterator __insert_multi(const_iterator __p, _Vp&& __v); |
||
961 | #endif // _LIBCPP_HAS_NO_RVALUE_REFERENCES |
||
962 | |||
963 | pair<iterator, bool> __insert_unique(const value_type& __v); |
||
964 | iterator __insert_unique(const_iterator __p, const value_type& __v); |
||
965 | iterator __insert_multi(const value_type& __v); |
||
966 | iterator __insert_multi(const_iterator __p, const value_type& __v); |
||
967 | |||
968 | pair<iterator, bool> __node_insert_unique(__node_pointer __nd); |
||
969 | iterator __node_insert_unique(const_iterator __p, |
||
970 | __node_pointer __nd); |
||
971 | |||
972 | iterator __node_insert_multi(__node_pointer __nd); |
||
973 | iterator __node_insert_multi(const_iterator __p, __node_pointer __nd); |
||
974 | |||
975 | iterator erase(const_iterator __p); |
||
976 | iterator erase(const_iterator __f, const_iterator __l); |
||
977 | template <class _Key> |
||
978 | size_type __erase_unique(const _Key& __k); |
||
979 | template <class _Key> |
||
980 | size_type __erase_multi(const _Key& __k); |
||
981 | |||
982 | void __insert_node_at(__node_base_pointer __parent, |
||
983 | __node_base_pointer& __child, |
||
984 | __node_base_pointer __new_node); |
||
985 | |||
986 | template <class _Key> |
||
987 | iterator find(const _Key& __v); |
||
988 | template <class _Key> |
||
989 | const_iterator find(const _Key& __v) const; |
||
990 | |||
991 | template <class _Key> |
||
992 | size_type __count_unique(const _Key& __k) const; |
||
993 | template <class _Key> |
||
994 | size_type __count_multi(const _Key& __k) const; |
||
995 | |||
996 | template <class _Key> |
||
997 | _LIBCPP_INLINE_VISIBILITY |
||
998 | iterator lower_bound(const _Key& __v) |
||
999 | {return __lower_bound(__v, __root(), __end_node());} |
||
1000 | template <class _Key> |
||
1001 | iterator __lower_bound(const _Key& __v, |
||
1002 | __node_pointer __root, |
||
1003 | __node_pointer __result); |
||
1004 | template <class _Key> |
||
1005 | _LIBCPP_INLINE_VISIBILITY |
||
1006 | const_iterator lower_bound(const _Key& __v) const |
||
1007 | {return __lower_bound(__v, __root(), __end_node());} |
||
1008 | template <class _Key> |
||
1009 | const_iterator __lower_bound(const _Key& __v, |
||
1010 | __node_const_pointer __root, |
||
1011 | __node_const_pointer __result) const; |
||
1012 | template <class _Key> |
||
1013 | _LIBCPP_INLINE_VISIBILITY |
||
1014 | iterator upper_bound(const _Key& __v) |
||
1015 | {return __upper_bound(__v, __root(), __end_node());} |
||
1016 | template <class _Key> |
||
1017 | iterator __upper_bound(const _Key& __v, |
||
1018 | __node_pointer __root, |
||
1019 | __node_pointer __result); |
||
1020 | template <class _Key> |
||
1021 | _LIBCPP_INLINE_VISIBILITY |
||
1022 | const_iterator upper_bound(const _Key& __v) const |
||
1023 | {return __upper_bound(__v, __root(), __end_node());} |
||
1024 | template <class _Key> |
||
1025 | const_iterator __upper_bound(const _Key& __v, |
||
1026 | __node_const_pointer __root, |
||
1027 | __node_const_pointer __result) const; |
||
1028 | template <class _Key> |
||
1029 | pair<iterator, iterator> |
||
1030 | __equal_range_unique(const _Key& __k); |
||
1031 | template <class _Key> |
||
1032 | pair<const_iterator, const_iterator> |
||
1033 | __equal_range_unique(const _Key& __k) const; |
||
1034 | |||
1035 | template <class _Key> |
||
1036 | pair<iterator, iterator> |
||
1037 | __equal_range_multi(const _Key& __k); |
||
1038 | template <class _Key> |
||
1039 | pair<const_iterator, const_iterator> |
||
1040 | __equal_range_multi(const _Key& __k) const; |
||
1041 | |||
1042 | typedef __tree_node_destructor<__node_allocator> _Dp; |
||
1043 | typedef unique_ptr<__node, _Dp> __node_holder; |
||
1044 | |||
1045 | __node_holder remove(const_iterator __p) _NOEXCEPT; |
||
1046 | private: |
||
1047 | typename __node_base::pointer& |
||
1048 | __find_leaf_low(typename __node_base::pointer& __parent, const value_type& __v); |
||
1049 | typename __node_base::pointer& |
||
1050 | __find_leaf_high(typename __node_base::pointer& __parent, const value_type& __v); |
||
1051 | typename __node_base::pointer& |
||
1052 | __find_leaf(const_iterator __hint, |
||
1053 | typename __node_base::pointer& __parent, const value_type& __v); |
||
1054 | template <class _Key> |
||
1055 | typename __node_base::pointer& |
||
1056 | __find_equal(typename __node_base::pointer& __parent, const _Key& __v); |
||
1057 | template <class _Key> |
||
1058 | typename __node_base::pointer& |
||
1059 | __find_equal(const_iterator __hint, typename __node_base::pointer& __parent, |
||
1060 | const _Key& __v); |
||
1061 | |||
1062 | #if !defined(_LIBCPP_HAS_NO_RVALUE_REFERENCES) && !defined(_LIBCPP_HAS_NO_VARIADICS) |
||
1063 | template <class ..._Args> |
||
1064 | __node_holder __construct_node(_Args&& ...__args); |
||
1065 | #else // !defined(_LIBCPP_HAS_NO_RVALUE_REFERENCES) && !defined(_LIBCPP_HAS_NO_VARIADICS) |
||
1066 | __node_holder __construct_node(const value_type& __v); |
||
1067 | #endif |
||
1068 | |||
1069 | void destroy(__node_pointer __nd) _NOEXCEPT; |
||
1070 | |||
1071 | _LIBCPP_INLINE_VISIBILITY |
||
1072 | void __copy_assign_alloc(const __tree& __t) |
||
1073 | {__copy_assign_alloc(__t, integral_constant<bool, |
||
1074 | __node_traits::propagate_on_container_copy_assignment::value>());} |
||
1075 | |||
1076 | _LIBCPP_INLINE_VISIBILITY |
||
1077 | void __copy_assign_alloc(const __tree& __t, true_type) |
||
1078 | {__node_alloc() = __t.__node_alloc();} |
||
1079 | _LIBCPP_INLINE_VISIBILITY |
||
1080 | void __copy_assign_alloc(const __tree& __t, false_type) {} |
||
1081 | |||
1082 | void __move_assign(__tree& __t, false_type); |
||
1083 | void __move_assign(__tree& __t, true_type) |
||
1084 | _NOEXCEPT_(is_nothrow_move_assignable<value_compare>::value && |
||
1085 | is_nothrow_move_assignable<__node_allocator>::value); |
||
1086 | |||
1087 | _LIBCPP_INLINE_VISIBILITY |
||
1088 | void __move_assign_alloc(__tree& __t) |
||
1089 | _NOEXCEPT_( |
||
1090 | !__node_traits::propagate_on_container_move_assignment::value || |
||
1091 | is_nothrow_move_assignable<__node_allocator>::value) |
||
1092 | {__move_assign_alloc(__t, integral_constant<bool, |
||
1093 | __node_traits::propagate_on_container_move_assignment::value>());} |
||
1094 | |||
1095 | _LIBCPP_INLINE_VISIBILITY |
||
1096 | void __move_assign_alloc(__tree& __t, true_type) |
||
1097 | _NOEXCEPT_(is_nothrow_move_assignable<__node_allocator>::value) |
||
1098 | {__node_alloc() = _VSTD::move(__t.__node_alloc());} |
||
1099 | _LIBCPP_INLINE_VISIBILITY |
||
1100 | void __move_assign_alloc(__tree& __t, false_type) _NOEXCEPT {} |
||
1101 | |||
1102 | __node_pointer __detach(); |
||
1103 | static __node_pointer __detach(__node_pointer); |
||
1104 | |||
1105 | template <class, class, class, class> friend class _LIBCPP_TYPE_VIS_ONLY map; |
||
1106 | template <class, class, class, class> friend class _LIBCPP_TYPE_VIS_ONLY multimap; |
||
1107 | }; |
||
1108 | |||
1109 | template <class _Tp, class _Compare, class _Allocator> |
||
1110 | __tree<_Tp, _Compare, _Allocator>::__tree(const value_compare& __comp) |
||
1111 | _NOEXCEPT_( |
||
1112 | is_nothrow_default_constructible<__node_allocator>::value && |
||
1113 | is_nothrow_copy_constructible<value_compare>::value) |
||
1114 | : __pair3_(0, __comp) |
||
1115 | { |
||
1116 | __begin_node() = __end_node(); |
||
1117 | } |
||
1118 | |||
1119 | template <class _Tp, class _Compare, class _Allocator> |
||
1120 | __tree<_Tp, _Compare, _Allocator>::__tree(const allocator_type& __a) |
||
1121 | : __begin_node_(__node_pointer()), |
||
1122 | __pair1_(__node_allocator(__a)), |
||
1123 | __pair3_(0) |
||
1124 | { |
||
1125 | __begin_node() = __end_node(); |
||
1126 | } |
||
1127 | |||
1128 | template <class _Tp, class _Compare, class _Allocator> |
||
1129 | __tree<_Tp, _Compare, _Allocator>::__tree(const value_compare& __comp, |
||
1130 | const allocator_type& __a) |
||
1131 | : __begin_node_(__node_pointer()), |
||
1132 | __pair1_(__node_allocator(__a)), |
||
1133 | __pair3_(0, __comp) |
||
1134 | { |
||
1135 | __begin_node() = __end_node(); |
||
1136 | } |
||
1137 | |||
1138 | // Precondition: size() != 0 |
||
1139 | template <class _Tp, class _Compare, class _Allocator> |
||
1140 | typename __tree<_Tp, _Compare, _Allocator>::__node_pointer |
||
1141 | __tree<_Tp, _Compare, _Allocator>::__detach() |
||
1142 | { |
||
1143 | __node_pointer __cache = __begin_node(); |
||
1144 | __begin_node() = __end_node(); |
||
1145 | __end_node()->__left_->__parent_ = nullptr; |
||
1146 | __end_node()->__left_ = nullptr; |
||
1147 | size() = 0; |
||
1148 | // __cache->__left_ == nullptr |
||
1149 | if (__cache->__right_ != nullptr) |
||
1150 | __cache = static_cast<__node_pointer>(__cache->__right_); |
||
1151 | // __cache->__left_ == nullptr |
||
1152 | // __cache->__right_ == nullptr |
||
1153 | return __cache; |
||
1154 | } |
||
1155 | |||
1156 | // Precondition: __cache != nullptr |
||
1157 | // __cache->left_ == nullptr |
||
1158 | // __cache->right_ == nullptr |
||
1159 | // This is no longer a red-black tree |
||
1160 | template <class _Tp, class _Compare, class _Allocator> |
||
1161 | typename __tree<_Tp, _Compare, _Allocator>::__node_pointer |
||
1162 | __tree<_Tp, _Compare, _Allocator>::__detach(__node_pointer __cache) |
||
1163 | { |
||
1164 | if (__cache->__parent_ == nullptr) |
||
1165 | return nullptr; |
||
1166 | if (__tree_is_left_child(static_cast<__node_base_pointer>(__cache))) |
||
1167 | { |
||
1168 | __cache->__parent_->__left_ = nullptr; |
||
1169 | __cache = static_cast<__node_pointer>(__cache->__parent_); |
||
1170 | if (__cache->__right_ == nullptr) |
||
1171 | return __cache; |
||
1172 | return static_cast<__node_pointer>(__tree_leaf(__cache->__right_)); |
||
1173 | } |
||
1174 | // __cache is right child |
||
1175 | __cache->__parent_->__right_ = nullptr; |
||
1176 | __cache = static_cast<__node_pointer>(__cache->__parent_); |
||
1177 | if (__cache->__left_ == nullptr) |
||
1178 | return __cache; |
||
1179 | return static_cast<__node_pointer>(__tree_leaf(__cache->__left_)); |
||
1180 | } |
||
1181 | |||
1182 | template <class _Tp, class _Compare, class _Allocator> |
||
1183 | __tree<_Tp, _Compare, _Allocator>& |
||
1184 | __tree<_Tp, _Compare, _Allocator>::operator=(const __tree& __t) |
||
1185 | { |
||
1186 | if (this != &__t) |
||
1187 | { |
||
1188 | value_comp() = __t.value_comp(); |
||
1189 | __copy_assign_alloc(__t); |
||
1190 | __assign_multi(__t.begin(), __t.end()); |
||
1191 | } |
||
1192 | return *this; |
||
1193 | } |
||
1194 | |||
1195 | template <class _Tp, class _Compare, class _Allocator> |
||
1196 | template <class _InputIterator> |
||
1197 | void |
||
1198 | __tree<_Tp, _Compare, _Allocator>::__assign_unique(_InputIterator __first, _InputIterator __last) |
||
1199 | { |
||
1200 | if (size() != 0) |
||
1201 | { |
||
1202 | __node_pointer __cache = __detach(); |
||
1203 | #ifndef _LIBCPP_NO_EXCEPTIONS |
||
1204 | try |
||
1205 | { |
||
1206 | #endif // _LIBCPP_NO_EXCEPTIONS |
||
1207 | for (; __cache != nullptr && __first != __last; ++__first) |
||
1208 | { |
||
1209 | __cache->__value_ = *__first; |
||
1210 | __node_pointer __next = __detach(__cache); |
||
1211 | __node_insert_unique(__cache); |
||
1212 | __cache = __next; |
||
1213 | } |
||
1214 | #ifndef _LIBCPP_NO_EXCEPTIONS |
||
1215 | } |
||
1216 | catch (...) |
||
1217 | { |
||
1218 | while (__cache->__parent_ != nullptr) |
||
1219 | __cache = static_cast<__node_pointer>(__cache->__parent_); |
||
1220 | destroy(__cache); |
||
1221 | throw; |
||
1222 | } |
||
1223 | #endif // _LIBCPP_NO_EXCEPTIONS |
||
1224 | if (__cache != nullptr) |
||
1225 | { |
||
1226 | while (__cache->__parent_ != nullptr) |
||
1227 | __cache = static_cast<__node_pointer>(__cache->__parent_); |
||
1228 | destroy(__cache); |
||
1229 | } |
||
1230 | } |
||
1231 | for (; __first != __last; ++__first) |
||
1232 | __insert_unique(*__first); |
||
1233 | } |
||
1234 | |||
1235 | template <class _Tp, class _Compare, class _Allocator> |
||
1236 | template <class _InputIterator> |
||
1237 | void |
||
1238 | __tree<_Tp, _Compare, _Allocator>::__assign_multi(_InputIterator __first, _InputIterator __last) |
||
1239 | { |
||
1240 | if (size() != 0) |
||
1241 | { |
||
1242 | __node_pointer __cache = __detach(); |
||
1243 | #ifndef _LIBCPP_NO_EXCEPTIONS |
||
1244 | try |
||
1245 | { |
||
1246 | #endif // _LIBCPP_NO_EXCEPTIONS |
||
1247 | for (; __cache != nullptr && __first != __last; ++__first) |
||
1248 | { |
||
1249 | __cache->__value_ = *__first; |
||
1250 | __node_pointer __next = __detach(__cache); |
||
1251 | __node_insert_multi(__cache); |
||
1252 | __cache = __next; |
||
1253 | } |
||
1254 | #ifndef _LIBCPP_NO_EXCEPTIONS |
||
1255 | } |
||
1256 | catch (...) |
||
1257 | { |
||
1258 | while (__cache->__parent_ != nullptr) |
||
1259 | __cache = static_cast<__node_pointer>(__cache->__parent_); |
||
1260 | destroy(__cache); |
||
1261 | throw; |
||
1262 | } |
||
1263 | #endif // _LIBCPP_NO_EXCEPTIONS |
||
1264 | if (__cache != nullptr) |
||
1265 | { |
||
1266 | while (__cache->__parent_ != nullptr) |
||
1267 | __cache = static_cast<__node_pointer>(__cache->__parent_); |
||
1268 | destroy(__cache); |
||
1269 | } |
||
1270 | } |
||
1271 | for (; __first != __last; ++__first) |
||
1272 | __insert_multi(*__first); |
||
1273 | } |
||
1274 | |||
1275 | template <class _Tp, class _Compare, class _Allocator> |
||
1276 | __tree<_Tp, _Compare, _Allocator>::__tree(const __tree& __t) |
||
1277 | : __begin_node_(__node_pointer()), |
||
1278 | __pair1_(__node_traits::select_on_container_copy_construction(__t.__node_alloc())), |
||
1279 | __pair3_(0, __t.value_comp()) |
||
1280 | { |
||
1281 | __begin_node() = __end_node(); |
||
1282 | } |
||
1283 | |||
1284 | #ifndef _LIBCPP_HAS_NO_RVALUE_REFERENCES |
||
1285 | |||
1286 | template <class _Tp, class _Compare, class _Allocator> |
||
1287 | __tree<_Tp, _Compare, _Allocator>::__tree(__tree&& __t) |
||
1288 | _NOEXCEPT_( |
||
1289 | is_nothrow_move_constructible<__node_allocator>::value && |
||
1290 | is_nothrow_move_constructible<value_compare>::value) |
||
1291 | : __begin_node_(_VSTD::move(__t.__begin_node_)), |
||
1292 | __pair1_(_VSTD::move(__t.__pair1_)), |
||
1293 | __pair3_(_VSTD::move(__t.__pair3_)) |
||
1294 | { |
||
1295 | if (size() == 0) |
||
1296 | __begin_node() = __end_node(); |
||
1297 | else |
||
1298 | { |
||
1299 | __end_node()->__left_->__parent_ = static_cast<__node_base_pointer>(__end_node()); |
||
1300 | __t.__begin_node() = __t.__end_node(); |
||
1301 | __t.__end_node()->__left_ = nullptr; |
||
1302 | __t.size() = 0; |
||
1303 | } |
||
1304 | } |
||
1305 | |||
1306 | template <class _Tp, class _Compare, class _Allocator> |
||
1307 | __tree<_Tp, _Compare, _Allocator>::__tree(__tree&& __t, const allocator_type& __a) |
||
1308 | : __pair1_(__node_allocator(__a)), |
||
1309 | __pair3_(0, _VSTD::move(__t.value_comp())) |
||
1310 | { |
||
1311 | if (__a == __t.__alloc()) |
||
1312 | { |
||
1313 | if (__t.size() == 0) |
||
1314 | __begin_node() = __end_node(); |
||
1315 | else |
||
1316 | { |
||
1317 | __begin_node() = __t.__begin_node(); |
||
1318 | __end_node()->__left_ = __t.__end_node()->__left_; |
||
1319 | __end_node()->__left_->__parent_ = static_cast<__node_base_pointer>(__end_node()); |
||
1320 | size() = __t.size(); |
||
1321 | __t.__begin_node() = __t.__end_node(); |
||
1322 | __t.__end_node()->__left_ = nullptr; |
||
1323 | __t.size() = 0; |
||
1324 | } |
||
1325 | } |
||
1326 | else |
||
1327 | { |
||
1328 | __begin_node() = __end_node(); |
||
1329 | } |
||
1330 | } |
||
1331 | |||
1332 | template <class _Tp, class _Compare, class _Allocator> |
||
1333 | void |
||
1334 | __tree<_Tp, _Compare, _Allocator>::__move_assign(__tree& __t, true_type) |
||
1335 | _NOEXCEPT_(is_nothrow_move_assignable<value_compare>::value && |
||
1336 | is_nothrow_move_assignable<__node_allocator>::value) |
||
1337 | { |
||
1338 | destroy(static_cast<__node_pointer>(__end_node()->__left_)); |
||
1339 | __begin_node_ = __t.__begin_node_; |
||
1340 | __pair1_.first() = __t.__pair1_.first(); |
||
1341 | __move_assign_alloc(__t); |
||
1342 | __pair3_ = _VSTD::move(__t.__pair3_); |
||
1343 | if (size() == 0) |
||
1344 | __begin_node() = __end_node(); |
||
1345 | else |
||
1346 | { |
||
1347 | __end_node()->__left_->__parent_ = static_cast<__node_base_pointer>(__end_node()); |
||
1348 | __t.__begin_node() = __t.__end_node(); |
||
1349 | __t.__end_node()->__left_ = nullptr; |
||
1350 | __t.size() = 0; |
||
1351 | } |
||
1352 | } |
||
1353 | |||
1354 | template <class _Tp, class _Compare, class _Allocator> |
||
1355 | void |
||
1356 | __tree<_Tp, _Compare, _Allocator>::__move_assign(__tree& __t, false_type) |
||
1357 | { |
||
1358 | if (__node_alloc() == __t.__node_alloc()) |
||
1359 | __move_assign(__t, true_type()); |
||
1360 | else |
||
1361 | { |
||
1362 | value_comp() = _VSTD::move(__t.value_comp()); |
||
1363 | const_iterator __e = end(); |
||
1364 | if (size() != 0) |
||
1365 | { |
||
1366 | __node_pointer __cache = __detach(); |
||
1367 | #ifndef _LIBCPP_NO_EXCEPTIONS |
||
1368 | try |
||
1369 | { |
||
1370 | #endif // _LIBCPP_NO_EXCEPTIONS |
||
1371 | while (__cache != nullptr && __t.size() != 0) |
||
1372 | { |
||
1373 | __cache->__value_ = _VSTD::move(__t.remove(__t.begin())->__value_); |
||
1374 | __node_pointer __next = __detach(__cache); |
||
1375 | __node_insert_multi(__cache); |
||
1376 | __cache = __next; |
||
1377 | } |
||
1378 | #ifndef _LIBCPP_NO_EXCEPTIONS |
||
1379 | } |
||
1380 | catch (...) |
||
1381 | { |
||
1382 | while (__cache->__parent_ != nullptr) |
||
1383 | __cache = static_cast<__node_pointer>(__cache->__parent_); |
||
1384 | destroy(__cache); |
||
1385 | throw; |
||
1386 | } |
||
1387 | #endif // _LIBCPP_NO_EXCEPTIONS |
||
1388 | if (__cache != nullptr) |
||
1389 | { |
||
1390 | while (__cache->__parent_ != nullptr) |
||
1391 | __cache = static_cast<__node_pointer>(__cache->__parent_); |
||
1392 | destroy(__cache); |
||
1393 | } |
||
1394 | } |
||
1395 | while (__t.size() != 0) |
||
1396 | __insert_multi(__e, _VSTD::move(__t.remove(__t.begin())->__value_)); |
||
1397 | } |
||
1398 | } |
||
1399 | |||
1400 | template <class _Tp, class _Compare, class _Allocator> |
||
1401 | __tree<_Tp, _Compare, _Allocator>& |
||
1402 | __tree<_Tp, _Compare, _Allocator>::operator=(__tree&& __t) |
||
1403 | _NOEXCEPT_( |
||
1404 | __node_traits::propagate_on_container_move_assignment::value && |
||
1405 | is_nothrow_move_assignable<value_compare>::value && |
||
1406 | is_nothrow_move_assignable<__node_allocator>::value) |
||
1407 | |||
1408 | { |
||
1409 | __move_assign(__t, integral_constant<bool, |
||
1410 | __node_traits::propagate_on_container_move_assignment::value>()); |
||
1411 | return *this; |
||
1412 | } |
||
1413 | |||
1414 | #endif // _LIBCPP_HAS_NO_RVALUE_REFERENCES |
||
1415 | |||
1416 | template <class _Tp, class _Compare, class _Allocator> |
||
1417 | __tree<_Tp, _Compare, _Allocator>::~__tree() |
||
1418 | { |
||
1419 | destroy(__root()); |
||
1420 | } |
||
1421 | |||
1422 | template <class _Tp, class _Compare, class _Allocator> |
||
1423 | void |
||
1424 | __tree<_Tp, _Compare, _Allocator>::destroy(__node_pointer __nd) _NOEXCEPT |
||
1425 | { |
||
1426 | if (__nd != nullptr) |
||
1427 | { |
||
1428 | destroy(static_cast<__node_pointer>(__nd->__left_)); |
||
1429 | destroy(static_cast<__node_pointer>(__nd->__right_)); |
||
1430 | __node_allocator& __na = __node_alloc(); |
||
1431 | __node_traits::destroy(__na, _VSTD::addressof(__nd->__value_)); |
||
1432 | __node_traits::deallocate(__na, __nd, 1); |
||
1433 | } |
||
1434 | } |
||
1435 | |||
1436 | template <class _Tp, class _Compare, class _Allocator> |
||
1437 | void |
||
1438 | __tree<_Tp, _Compare, _Allocator>::swap(__tree& __t) |
||
1439 | _NOEXCEPT_( |
||
1440 | __is_nothrow_swappable<value_compare>::value |
||
1441 | #if _LIBCPP_STD_VER <= 11 |
||
1442 | && (!__node_traits::propagate_on_container_swap::value || |
||
1443 | __is_nothrow_swappable<__node_allocator>::value) |
||
1444 | #endif |
||
1445 | ) |
||
1446 | { |
||
1447 | using _VSTD::swap; |
||
1448 | swap(__begin_node_, __t.__begin_node_); |
||
1449 | swap(__pair1_.first(), __t.__pair1_.first()); |
||
1450 | __swap_allocator(__node_alloc(), __t.__node_alloc()); |
||
1451 | __pair3_.swap(__t.__pair3_); |
||
1452 | if (size() == 0) |
||
1453 | __begin_node() = __end_node(); |
||
1454 | else |
||
1455 | __end_node()->__left_->__parent_ = static_cast<__node_base_pointer>(__end_node()); |
||
1456 | if (__t.size() == 0) |
||
1457 | __t.__begin_node() = __t.__end_node(); |
||
1458 | else |
||
1459 | __t.__end_node()->__left_->__parent_ = static_cast<__node_base_pointer>(__t.__end_node()); |
||
1460 | } |
||
1461 | |||
1462 | template <class _Tp, class _Compare, class _Allocator> |
||
1463 | void |
||
1464 | __tree<_Tp, _Compare, _Allocator>::clear() _NOEXCEPT |
||
1465 | { |
||
1466 | destroy(__root()); |
||
1467 | size() = 0; |
||
1468 | __begin_node() = __end_node(); |
||
1469 | __end_node()->__left_ = nullptr; |
||
1470 | } |
||
1471 | |||
1472 | // Find lower_bound place to insert |
||
1473 | // Set __parent to parent of null leaf |
||
1474 | // Return reference to null leaf |
||
1475 | template <class _Tp, class _Compare, class _Allocator> |
||
1476 | typename __tree<_Tp, _Compare, _Allocator>::__node_base::pointer& |
||
1477 | __tree<_Tp, _Compare, _Allocator>::__find_leaf_low(typename __node_base::pointer& __parent, |
||
1478 | const value_type& __v) |
||
1479 | { |
||
1480 | __node_pointer __nd = __root(); |
||
1481 | if (__nd != nullptr) |
||
1482 | { |
||
1483 | while (true) |
||
1484 | { |
||
1485 | if (value_comp()(__nd->__value_, __v)) |
||
1486 | { |
||
1487 | if (__nd->__right_ != nullptr) |
||
1488 | __nd = static_cast<__node_pointer>(__nd->__right_); |
||
1489 | else |
||
1490 | { |
||
1491 | __parent = static_cast<__node_base_pointer>(__nd); |
||
1492 | return __parent->__right_; |
||
1493 | } |
||
1494 | } |
||
1495 | else |
||
1496 | { |
||
1497 | if (__nd->__left_ != nullptr) |
||
1498 | __nd = static_cast<__node_pointer>(__nd->__left_); |
||
1499 | else |
||
1500 | { |
||
1501 | __parent = static_cast<__node_base_pointer>(__nd); |
||
1502 | return __parent->__left_; |
||
1503 | } |
||
1504 | } |
||
1505 | } |
||
1506 | } |
||
1507 | __parent = static_cast<__node_base_pointer>(__end_node()); |
||
1508 | return __parent->__left_; |
||
1509 | } |
||
1510 | |||
1511 | // Find upper_bound place to insert |
||
1512 | // Set __parent to parent of null leaf |
||
1513 | // Return reference to null leaf |
||
1514 | template <class _Tp, class _Compare, class _Allocator> |
||
1515 | typename __tree<_Tp, _Compare, _Allocator>::__node_base::pointer& |
||
1516 | __tree<_Tp, _Compare, _Allocator>::__find_leaf_high(typename __node_base::pointer& __parent, |
||
1517 | const value_type& __v) |
||
1518 | { |
||
1519 | __node_pointer __nd = __root(); |
||
1520 | if (__nd != nullptr) |
||
1521 | { |
||
1522 | while (true) |
||
1523 | { |
||
1524 | if (value_comp()(__v, __nd->__value_)) |
||
1525 | { |
||
1526 | if (__nd->__left_ != nullptr) |
||
1527 | __nd = static_cast<__node_pointer>(__nd->__left_); |
||
1528 | else |
||
1529 | { |
||
1530 | __parent = static_cast<__node_base_pointer>(__nd); |
||
1531 | return __parent->__left_; |
||
1532 | } |
||
1533 | } |
||
1534 | else |
||
1535 | { |
||
1536 | if (__nd->__right_ != nullptr) |
||
1537 | __nd = static_cast<__node_pointer>(__nd->__right_); |
||
1538 | else |
||
1539 | { |
||
1540 | __parent = static_cast<__node_base_pointer>(__nd); |
||
1541 | return __parent->__right_; |
||
1542 | } |
||
1543 | } |
||
1544 | } |
||
1545 | } |
||
1546 | __parent = static_cast<__node_base_pointer>(__end_node()); |
||
1547 | return __parent->__left_; |
||
1548 | } |
||
1549 | |||
1550 | // Find leaf place to insert closest to __hint |
||
1551 | // First check prior to __hint. |
||
1552 | // Next check after __hint. |
||
1553 | // Next do O(log N) search. |
||
1554 | // Set __parent to parent of null leaf |
||
1555 | // Return reference to null leaf |
||
1556 | template <class _Tp, class _Compare, class _Allocator> |
||
1557 | typename __tree<_Tp, _Compare, _Allocator>::__node_base::pointer& |
||
1558 | __tree<_Tp, _Compare, _Allocator>::__find_leaf(const_iterator __hint, |
||
1559 | typename __node_base::pointer& __parent, |
||
1560 | const value_type& __v) |
||
1561 | { |
||
1562 | if (__hint == end() || !value_comp()(*__hint, __v)) // check before |
||
1563 | { |
||
1564 | // __v <= *__hint |
||
1565 | const_iterator __prior = __hint; |
||
1566 | if (__prior == begin() || !value_comp()(__v, *--__prior)) |
||
1567 | { |
||
1568 | // *prev(__hint) <= __v <= *__hint |
||
1569 | if (__hint.__ptr_->__left_ == nullptr) |
||
1570 | { |
||
1571 | __parent = static_cast<__node_base_pointer>(__hint.__ptr_); |
||
1572 | return __parent->__left_; |
||
1573 | } |
||
1574 | else |
||
1575 | { |
||
1576 | __parent = static_cast<__node_base_pointer>(__prior.__ptr_); |
||
1577 | return __parent->__right_; |
||
1578 | } |
||
1579 | } |
||
1580 | // __v < *prev(__hint) |
||
1581 | return __find_leaf_high(__parent, __v); |
||
1582 | } |
||
1583 | // else __v > *__hint |
||
1584 | return __find_leaf_low(__parent, __v); |
||
1585 | } |
||
1586 | |||
1587 | // Find place to insert if __v doesn't exist |
||
1588 | // Set __parent to parent of null leaf |
||
1589 | // Return reference to null leaf |
||
1590 | // If __v exists, set parent to node of __v and return reference to node of __v |
||
1591 | template <class _Tp, class _Compare, class _Allocator> |
||
1592 | template <class _Key> |
||
1593 | typename __tree<_Tp, _Compare, _Allocator>::__node_base::pointer& |
||
1594 | __tree<_Tp, _Compare, _Allocator>::__find_equal(typename __node_base::pointer& __parent, |
||
1595 | const _Key& __v) |
||
1596 | { |
||
1597 | __node_pointer __nd = __root(); |
||
1598 | if (__nd != nullptr) |
||
1599 | { |
||
1600 | while (true) |
||
1601 | { |
||
1602 | if (value_comp()(__v, __nd->__value_)) |
||
1603 | { |
||
1604 | if (__nd->__left_ != nullptr) |
||
1605 | __nd = static_cast<__node_pointer>(__nd->__left_); |
||
1606 | else |
||
1607 | { |
||
1608 | __parent = static_cast<__node_base_pointer>(__nd); |
||
1609 | return __parent->__left_; |
||
1610 | } |
||
1611 | } |
||
1612 | else if (value_comp()(__nd->__value_, __v)) |
||
1613 | { |
||
1614 | if (__nd->__right_ != nullptr) |
||
1615 | __nd = static_cast<__node_pointer>(__nd->__right_); |
||
1616 | else |
||
1617 | { |
||
1618 | __parent = static_cast<__node_base_pointer>(__nd); |
||
1619 | return __parent->__right_; |
||
1620 | } |
||
1621 | } |
||
1622 | else |
||
1623 | { |
||
1624 | __parent = static_cast<__node_base_pointer>(__nd); |
||
1625 | return __parent; |
||
1626 | } |
||
1627 | } |
||
1628 | } |
||
1629 | __parent = static_cast<__node_base_pointer>(__end_node()); |
||
1630 | return __parent->__left_; |
||
1631 | } |
||
1632 | |||
1633 | // Find place to insert if __v doesn't exist |
||
1634 | // First check prior to __hint. |
||
1635 | // Next check after __hint. |
||
1636 | // Next do O(log N) search. |
||
1637 | // Set __parent to parent of null leaf |
||
1638 | // Return reference to null leaf |
||
1639 | // If __v exists, set parent to node of __v and return reference to node of __v |
||
1640 | template <class _Tp, class _Compare, class _Allocator> |
||
1641 | template <class _Key> |
||
1642 | typename __tree<_Tp, _Compare, _Allocator>::__node_base::pointer& |
||
1643 | __tree<_Tp, _Compare, _Allocator>::__find_equal(const_iterator __hint, |
||
1644 | typename __node_base::pointer& __parent, |
||
1645 | const _Key& __v) |
||
1646 | { |
||
1647 | if (__hint == end() || value_comp()(__v, *__hint)) // check before |
||
1648 | { |
||
1649 | // __v < *__hint |
||
1650 | const_iterator __prior = __hint; |
||
1651 | if (__prior == begin() || value_comp()(*--__prior, __v)) |
||
1652 | { |
||
1653 | // *prev(__hint) < __v < *__hint |
||
1654 | if (__hint.__ptr_->__left_ == nullptr) |
||
1655 | { |
||
1656 | __parent = static_cast<__node_base_pointer>(__hint.__ptr_); |
||
1657 | return __parent->__left_; |
||
1658 | } |
||
1659 | else |
||
1660 | { |
||
1661 | __parent = static_cast<__node_base_pointer>(__prior.__ptr_); |
||
1662 | return __parent->__right_; |
||
1663 | } |
||
1664 | } |
||
1665 | // __v <= *prev(__hint) |
||
1666 | return __find_equal(__parent, __v); |
||
1667 | } |
||
1668 | else if (value_comp()(*__hint, __v)) // check after |
||
1669 | { |
||
1670 | // *__hint < __v |
||
1671 | const_iterator __next = _VSTD::next(__hint); |
||
1672 | if (__next == end() || value_comp()(__v, *__next)) |
||
1673 | { |
||
1674 | // *__hint < __v < *_VSTD::next(__hint) |
||
1675 | if (__hint.__ptr_->__right_ == nullptr) |
||
1676 | { |
||
1677 | __parent = static_cast<__node_base_pointer>(__hint.__ptr_); |
||
1678 | return __parent->__right_; |
||
1679 | } |
||
1680 | else |
||
1681 | { |
||
1682 | __parent = static_cast<__node_base_pointer>(__next.__ptr_); |
||
1683 | return __parent->__left_; |
||
1684 | } |
||
1685 | } |
||
1686 | // *next(__hint) <= __v |
||
1687 | return __find_equal(__parent, __v); |
||
1688 | } |
||
1689 | // else __v == *__hint |
||
1690 | __parent = static_cast<__node_base_pointer>(__hint.__ptr_); |
||
1691 | return __parent; |
||
1692 | } |
||
1693 | |||
1694 | template <class _Tp, class _Compare, class _Allocator> |
||
1695 | void |
||
1696 | __tree<_Tp, _Compare, _Allocator>::__insert_node_at(__node_base_pointer __parent, |
||
1697 | __node_base_pointer& __child, |
||
1698 | __node_base_pointer __new_node) |
||
1699 | { |
||
1700 | __new_node->__left_ = nullptr; |
||
1701 | __new_node->__right_ = nullptr; |
||
1702 | __new_node->__parent_ = __parent; |
||
1703 | __child = __new_node; |
||
1704 | if (__begin_node()->__left_ != nullptr) |
||
1705 | __begin_node() = static_cast<__node_pointer>(__begin_node()->__left_); |
||
1706 | __tree_balance_after_insert(__end_node()->__left_, __child); |
||
1707 | ++size(); |
||
1708 | } |
||
1709 | |||
1710 | #ifndef _LIBCPP_HAS_NO_RVALUE_REFERENCES |
||
1711 | #ifndef _LIBCPP_HAS_NO_VARIADICS |
||
1712 | |||
1713 | template <class _Tp, class _Compare, class _Allocator> |
||
1714 | template <class ..._Args> |
||
1715 | typename __tree<_Tp, _Compare, _Allocator>::__node_holder |
||
1716 | __tree<_Tp, _Compare, _Allocator>::__construct_node(_Args&& ...__args) |
||
1717 | { |
||
1718 | __node_allocator& __na = __node_alloc(); |
||
1719 | __node_holder __h(__node_traits::allocate(__na, 1), _Dp(__na)); |
||
1720 | __node_traits::construct(__na, _VSTD::addressof(__h->__value_), _VSTD::forward<_Args>(__args)...); |
||
1721 | __h.get_deleter().__value_constructed = true; |
||
1722 | return __h; |
||
1723 | } |
||
1724 | |||
1725 | template <class _Tp, class _Compare, class _Allocator> |
||
1726 | template <class... _Args> |
||
1727 | pair<typename __tree<_Tp, _Compare, _Allocator>::iterator, bool> |
||
1728 | __tree<_Tp, _Compare, _Allocator>::__emplace_unique(_Args&&... __args) |
||
1729 | { |
||
1730 | __node_holder __h = __construct_node(_VSTD::forward<_Args>(__args)...); |
||
1731 | __node_base_pointer __parent; |
||
1732 | __node_base_pointer& __child = __find_equal(__parent, __h->__value_); |
||
1733 | __node_pointer __r = static_cast<__node_pointer>(__child); |
||
1734 | bool __inserted = false; |
||
1735 | if (__child == nullptr) |
||
1736 | { |
||
1737 | __insert_node_at(__parent, __child, static_cast<__node_base_pointer>(__h.get())); |
||
1738 | __r = __h.release(); |
||
1739 | __inserted = true; |
||
1740 | } |
||
1741 | return pair<iterator, bool>(iterator(__r), __inserted); |
||
1742 | } |
||
1743 | |||
1744 | template <class _Tp, class _Compare, class _Allocator> |
||
1745 | template <class... _Args> |
||
1746 | typename __tree<_Tp, _Compare, _Allocator>::iterator |
||
1747 | __tree<_Tp, _Compare, _Allocator>::__emplace_hint_unique(const_iterator __p, _Args&&... __args) |
||
1748 | { |
||
1749 | __node_holder __h = __construct_node(_VSTD::forward<_Args>(__args)...); |
||
1750 | __node_base_pointer __parent; |
||
1751 | __node_base_pointer& __child = __find_equal(__p, __parent, __h->__value_); |
||
1752 | __node_pointer __r = static_cast<__node_pointer>(__child); |
||
1753 | if (__child == nullptr) |
||
1754 | { |
||
1755 | __insert_node_at(__parent, __child, static_cast<__node_base_pointer>(__h.get())); |
||
1756 | __r = __h.release(); |
||
1757 | } |
||
1758 | return iterator(__r); |
||
1759 | } |
||
1760 | |||
1761 | template <class _Tp, class _Compare, class _Allocator> |
||
1762 | template <class... _Args> |
||
1763 | typename __tree<_Tp, _Compare, _Allocator>::iterator |
||
1764 | __tree<_Tp, _Compare, _Allocator>::__emplace_multi(_Args&&... __args) |
||
1765 | { |
||
1766 | __node_holder __h = __construct_node(_VSTD::forward<_Args>(__args)...); |
||
1767 | __node_base_pointer __parent; |
||
1768 | __node_base_pointer& __child = __find_leaf_high(__parent, __h->__value_); |
||
1769 | __insert_node_at(__parent, __child, static_cast<__node_base_pointer>(__h.get())); |
||
1770 | return iterator(static_cast<__node_pointer>(__h.release())); |
||
1771 | } |
||
1772 | |||
1773 | template <class _Tp, class _Compare, class _Allocator> |
||
1774 | template <class... _Args> |
||
1775 | typename __tree<_Tp, _Compare, _Allocator>::iterator |
||
1776 | __tree<_Tp, _Compare, _Allocator>::__emplace_hint_multi(const_iterator __p, |
||
1777 | _Args&&... __args) |
||
1778 | { |
||
1779 | __node_holder __h = __construct_node(_VSTD::forward<_Args>(__args)...); |
||
1780 | __node_base_pointer __parent; |
||
1781 | __node_base_pointer& __child = __find_leaf(__p, __parent, __h->__value_); |
||
1782 | __insert_node_at(__parent, __child, static_cast<__node_base_pointer>(__h.get())); |
||
1783 | return iterator(static_cast<__node_pointer>(__h.release())); |
||
1784 | } |
||
1785 | |||
1786 | #endif // _LIBCPP_HAS_NO_VARIADICS |
||
1787 | |||
1788 | template <class _Tp, class _Compare, class _Allocator> |
||
1789 | template <class _Vp> |
||
1790 | pair<typename __tree<_Tp, _Compare, _Allocator>::iterator, bool> |
||
1791 | __tree<_Tp, _Compare, _Allocator>::__insert_unique(_Vp&& __v) |
||
1792 | { |
||
1793 | __node_holder __h = __construct_node(_VSTD::forward<_Vp>(__v)); |
||
1794 | pair<iterator, bool> __r = __node_insert_unique(__h.get()); |
||
1795 | if (__r.second) |
||
1796 | __h.release(); |
||
1797 | return __r; |
||
1798 | } |
||
1799 | |||
1800 | template <class _Tp, class _Compare, class _Allocator> |
||
1801 | template <class _Vp> |
||
1802 | typename __tree<_Tp, _Compare, _Allocator>::iterator |
||
1803 | __tree<_Tp, _Compare, _Allocator>::__insert_unique(const_iterator __p, _Vp&& __v) |
||
1804 | { |
||
1805 | __node_holder __h = __construct_node(_VSTD::forward<_Vp>(__v)); |
||
1806 | iterator __r = __node_insert_unique(__p, __h.get()); |
||
1807 | if (__r.__ptr_ == __h.get()) |
||
1808 | __h.release(); |
||
1809 | return __r; |
||
1810 | } |
||
1811 | |||
1812 | template <class _Tp, class _Compare, class _Allocator> |
||
1813 | template <class _Vp> |
||
1814 | typename __tree<_Tp, _Compare, _Allocator>::iterator |
||
1815 | __tree<_Tp, _Compare, _Allocator>::__insert_multi(_Vp&& __v) |
||
1816 | { |
||
1817 | __node_holder __h = __construct_node(_VSTD::forward<_Vp>(__v)); |
||
1818 | __node_base_pointer __parent; |
||
1819 | __node_base_pointer& __child = __find_leaf_high(__parent, __h->__value_); |
||
1820 | __insert_node_at(__parent, __child, static_cast<__node_base_pointer>(__h.get())); |
||
1821 | return iterator(__h.release()); |
||
1822 | } |
||
1823 | |||
1824 | template <class _Tp, class _Compare, class _Allocator> |
||
1825 | template <class _Vp> |
||
1826 | typename __tree<_Tp, _Compare, _Allocator>::iterator |
||
1827 | __tree<_Tp, _Compare, _Allocator>::__insert_multi(const_iterator __p, _Vp&& __v) |
||
1828 | { |
||
1829 | __node_holder __h = __construct_node(_VSTD::forward<_Vp>(__v)); |
||
1830 | __node_base_pointer __parent; |
||
1831 | __node_base_pointer& __child = __find_leaf(__p, __parent, __h->__value_); |
||
1832 | __insert_node_at(__parent, __child, static_cast<__node_base_pointer>(__h.get())); |
||
1833 | return iterator(__h.release()); |
||
1834 | } |
||
1835 | |||
1836 | #else // _LIBCPP_HAS_NO_RVALUE_REFERENCES |
||
1837 | |||
1838 | template <class _Tp, class _Compare, class _Allocator> |
||
1839 | typename __tree<_Tp, _Compare, _Allocator>::__node_holder |
||
1840 | __tree<_Tp, _Compare, _Allocator>::__construct_node(const value_type& __v) |
||
1841 | { |
||
1842 | __node_allocator& __na = __node_alloc(); |
||
1843 | __node_holder __h(__node_traits::allocate(__na, 1), _Dp(__na)); |
||
1844 | __node_traits::construct(__na, _VSTD::addressof(__h->__value_), __v); |
||
1845 | __h.get_deleter().__value_constructed = true; |
||
1846 | return _LIBCPP_EXPLICIT_MOVE(__h); // explicitly moved for C++03 |
||
1847 | } |
||
1848 | |||
1849 | #endif // _LIBCPP_HAS_NO_RVALUE_REFERENCES |
||
1850 | |||
1851 | template <class _Tp, class _Compare, class _Allocator> |
||
1852 | pair<typename __tree<_Tp, _Compare, _Allocator>::iterator, bool> |
||
1853 | __tree<_Tp, _Compare, _Allocator>::__insert_unique(const value_type& __v) |
||
1854 | { |
||
1855 | __node_base_pointer __parent; |
||
1856 | __node_base_pointer& __child = __find_equal(__parent, __v); |
||
1857 | __node_pointer __r = static_cast<__node_pointer>(__child); |
||
1858 | bool __inserted = false; |
||
1859 | if (__child == nullptr) |
||
1860 | { |
||
1861 | __node_holder __h = __construct_node(__v); |
||
1862 | __insert_node_at(__parent, __child, static_cast<__node_base_pointer>(__h.get())); |
||
1863 | __r = __h.release(); |
||
1864 | __inserted = true; |
||
1865 | } |
||
1866 | return pair<iterator, bool>(iterator(__r), __inserted); |
||
1867 | } |
||
1868 | |||
1869 | template <class _Tp, class _Compare, class _Allocator> |
||
1870 | typename __tree<_Tp, _Compare, _Allocator>::iterator |
||
1871 | __tree<_Tp, _Compare, _Allocator>::__insert_unique(const_iterator __p, const value_type& __v) |
||
1872 | { |
||
1873 | __node_base_pointer __parent; |
||
1874 | __node_base_pointer& __child = __find_equal(__p, __parent, __v); |
||
1875 | __node_pointer __r = static_cast<__node_pointer>(__child); |
||
1876 | if (__child == nullptr) |
||
1877 | { |
||
1878 | __node_holder __h = __construct_node(__v); |
||
1879 | __insert_node_at(__parent, __child, static_cast<__node_base_pointer>(__h.get())); |
||
1880 | __r = __h.release(); |
||
1881 | } |
||
1882 | return iterator(__r); |
||
1883 | } |
||
1884 | |||
1885 | template <class _Tp, class _Compare, class _Allocator> |
||
1886 | typename __tree<_Tp, _Compare, _Allocator>::iterator |
||
1887 | __tree<_Tp, _Compare, _Allocator>::__insert_multi(const value_type& __v) |
||
1888 | { |
||
1889 | __node_base_pointer __parent; |
||
1890 | __node_base_pointer& __child = __find_leaf_high(__parent, __v); |
||
1891 | __node_holder __h = __construct_node(__v); |
||
1892 | __insert_node_at(__parent, __child, static_cast<__node_base_pointer>(__h.get())); |
||
1893 | return iterator(__h.release()); |
||
1894 | } |
||
1895 | |||
1896 | template <class _Tp, class _Compare, class _Allocator> |
||
1897 | typename __tree<_Tp, _Compare, _Allocator>::iterator |
||
1898 | __tree<_Tp, _Compare, _Allocator>::__insert_multi(const_iterator __p, const value_type& __v) |
||
1899 | { |
||
1900 | __node_base_pointer __parent; |
||
1901 | __node_base_pointer& __child = __find_leaf(__p, __parent, __v); |
||
1902 | __node_holder __h = __construct_node(__v); |
||
1903 | __insert_node_at(__parent, __child, static_cast<__node_base_pointer>(__h.get())); |
||
1904 | return iterator(__h.release()); |
||
1905 | } |
||
1906 | |||
1907 | template <class _Tp, class _Compare, class _Allocator> |
||
1908 | pair<typename __tree<_Tp, _Compare, _Allocator>::iterator, bool> |
||
1909 | __tree<_Tp, _Compare, _Allocator>::__node_insert_unique(__node_pointer __nd) |
||
1910 | { |
||
1911 | __node_base_pointer __parent; |
||
1912 | __node_base_pointer& __child = __find_equal(__parent, __nd->__value_); |
||
1913 | __node_pointer __r = static_cast<__node_pointer>(__child); |
||
1914 | bool __inserted = false; |
||
1915 | if (__child == nullptr) |
||
1916 | { |
||
1917 | __insert_node_at(__parent, __child, static_cast<__node_base_pointer>(__nd)); |
||
1918 | __r = __nd; |
||
1919 | __inserted = true; |
||
1920 | } |
||
1921 | return pair<iterator, bool>(iterator(__r), __inserted); |
||
1922 | } |
||
1923 | |||
1924 | template <class _Tp, class _Compare, class _Allocator> |
||
1925 | typename __tree<_Tp, _Compare, _Allocator>::iterator |
||
1926 | __tree<_Tp, _Compare, _Allocator>::__node_insert_unique(const_iterator __p, |
||
1927 | __node_pointer __nd) |
||
1928 | { |
||
1929 | __node_base_pointer __parent; |
||
1930 | __node_base_pointer& __child = __find_equal(__p, __parent, __nd->__value_); |
||
1931 | __node_pointer __r = static_cast<__node_pointer>(__child); |
||
1932 | if (__child == nullptr) |
||
1933 | { |
||
1934 | __insert_node_at(__parent, __child, static_cast<__node_base_pointer>(__nd)); |
||
1935 | __r = __nd; |
||
1936 | } |
||
1937 | return iterator(__r); |
||
1938 | } |
||
1939 | |||
1940 | template <class _Tp, class _Compare, class _Allocator> |
||
1941 | typename __tree<_Tp, _Compare, _Allocator>::iterator |
||
1942 | __tree<_Tp, _Compare, _Allocator>::__node_insert_multi(__node_pointer __nd) |
||
1943 | { |
||
1944 | __node_base_pointer __parent; |
||
1945 | __node_base_pointer& __child = __find_leaf_high(__parent, __nd->__value_); |
||
1946 | __insert_node_at(__parent, __child, static_cast<__node_base_pointer>(__nd)); |
||
1947 | return iterator(__nd); |
||
1948 | } |
||
1949 | |||
1950 | template <class _Tp, class _Compare, class _Allocator> |
||
1951 | typename __tree<_Tp, _Compare, _Allocator>::iterator |
||
1952 | __tree<_Tp, _Compare, _Allocator>::__node_insert_multi(const_iterator __p, |
||
1953 | __node_pointer __nd) |
||
1954 | { |
||
1955 | __node_base_pointer __parent; |
||
1956 | __node_base_pointer& __child = __find_leaf(__p, __parent, __nd->__value_); |
||
1957 | __insert_node_at(__parent, __child, static_cast<__node_base_pointer>(__nd)); |
||
1958 | return iterator(__nd); |
||
1959 | } |
||
1960 | |||
1961 | template <class _Tp, class _Compare, class _Allocator> |
||
1962 | typename __tree<_Tp, _Compare, _Allocator>::iterator |
||
1963 | __tree<_Tp, _Compare, _Allocator>::erase(const_iterator __p) |
||
1964 | { |
||
1965 | __node_pointer __np = __p.__ptr_; |
||
1966 | iterator __r(__np); |
||
1967 | ++__r; |
||
1968 | if (__begin_node() == __np) |
||
1969 | __begin_node() = __r.__ptr_; |
||
1970 | --size(); |
||
1971 | __node_allocator& __na = __node_alloc(); |
||
1972 | __tree_remove(__end_node()->__left_, |
||
1973 | static_cast<__node_base_pointer>(__np)); |
||
1974 | __node_traits::destroy(__na, const_cast<value_type*>(_VSTD::addressof(*__p))); |
||
1975 | __node_traits::deallocate(__na, __np, 1); |
||
1976 | return __r; |
||
1977 | } |
||
1978 | |||
1979 | template <class _Tp, class _Compare, class _Allocator> |
||
1980 | typename __tree<_Tp, _Compare, _Allocator>::iterator |
||
1981 | __tree<_Tp, _Compare, _Allocator>::erase(const_iterator __f, const_iterator __l) |
||
1982 | { |
||
1983 | while (__f != __l) |
||
1984 | __f = erase(__f); |
||
1985 | return iterator(__l.__ptr_); |
||
1986 | } |
||
1987 | |||
1988 | template <class _Tp, class _Compare, class _Allocator> |
||
1989 | template <class _Key> |
||
1990 | typename __tree<_Tp, _Compare, _Allocator>::size_type |
||
1991 | __tree<_Tp, _Compare, _Allocator>::__erase_unique(const _Key& __k) |
||
1992 | { |
||
1993 | iterator __i = find(__k); |
||
1994 | if (__i == end()) |
||
1995 | return 0; |
||
1996 | erase(__i); |
||
1997 | return 1; |
||
1998 | } |
||
1999 | |||
2000 | template <class _Tp, class _Compare, class _Allocator> |
||
2001 | template <class _Key> |
||
2002 | typename __tree<_Tp, _Compare, _Allocator>::size_type |
||
2003 | __tree<_Tp, _Compare, _Allocator>::__erase_multi(const _Key& __k) |
||
2004 | { |
||
2005 | pair<iterator, iterator> __p = __equal_range_multi(__k); |
||
2006 | size_type __r = 0; |
||
2007 | for (; __p.first != __p.second; ++__r) |
||
2008 | __p.first = erase(__p.first); |
||
2009 | return __r; |
||
2010 | } |
||
2011 | |||
2012 | template <class _Tp, class _Compare, class _Allocator> |
||
2013 | template <class _Key> |
||
2014 | typename __tree<_Tp, _Compare, _Allocator>::iterator |
||
2015 | __tree<_Tp, _Compare, _Allocator>::find(const _Key& __v) |
||
2016 | { |
||
2017 | iterator __p = __lower_bound(__v, __root(), __end_node()); |
||
2018 | if (__p != end() && !value_comp()(__v, *__p)) |
||
2019 | return __p; |
||
2020 | return end(); |
||
2021 | } |
||
2022 | |||
2023 | template <class _Tp, class _Compare, class _Allocator> |
||
2024 | template <class _Key> |
||
2025 | typename __tree<_Tp, _Compare, _Allocator>::const_iterator |
||
2026 | __tree<_Tp, _Compare, _Allocator>::find(const _Key& __v) const |
||
2027 | { |
||
2028 | const_iterator __p = __lower_bound(__v, __root(), __end_node()); |
||
2029 | if (__p != end() && !value_comp()(__v, *__p)) |
||
2030 | return __p; |
||
2031 | return end(); |
||
2032 | } |
||
2033 | |||
2034 | template <class _Tp, class _Compare, class _Allocator> |
||
2035 | template <class _Key> |
||
2036 | typename __tree<_Tp, _Compare, _Allocator>::size_type |
||
2037 | __tree<_Tp, _Compare, _Allocator>::__count_unique(const _Key& __k) const |
||
2038 | { |
||
2039 | __node_const_pointer __result = __end_node(); |
||
2040 | __node_const_pointer __rt = __root(); |
||
2041 | while (__rt != nullptr) |
||
2042 | { |
||
2043 | if (value_comp()(__k, __rt->__value_)) |
||
2044 | { |
||
2045 | __result = __rt; |
||
2046 | __rt = static_cast<__node_const_pointer>(__rt->__left_); |
||
2047 | } |
||
2048 | else if (value_comp()(__rt->__value_, __k)) |
||
2049 | __rt = static_cast<__node_const_pointer>(__rt->__right_); |
||
2050 | else |
||
2051 | return 1; |
||
2052 | } |
||
2053 | return 0; |
||
2054 | } |
||
2055 | |||
2056 | template <class _Tp, class _Compare, class _Allocator> |
||
2057 | template <class _Key> |
||
2058 | typename __tree<_Tp, _Compare, _Allocator>::size_type |
||
2059 | __tree<_Tp, _Compare, _Allocator>::__count_multi(const _Key& __k) const |
||
2060 | { |
||
2061 | __node_const_pointer __result = __end_node(); |
||
2062 | __node_const_pointer __rt = __root(); |
||
2063 | while (__rt != nullptr) |
||
2064 | { |
||
2065 | if (value_comp()(__k, __rt->__value_)) |
||
2066 | { |
||
2067 | __result = __rt; |
||
2068 | __rt = static_cast<__node_const_pointer>(__rt->__left_); |
||
2069 | } |
||
2070 | else if (value_comp()(__rt->__value_, __k)) |
||
2071 | __rt = static_cast<__node_const_pointer>(__rt->__right_); |
||
2072 | else |
||
2073 | return _VSTD::distance( |
||
2074 | __lower_bound(__k, static_cast<__node_const_pointer>(__rt->__left_), __rt), |
||
2075 | __upper_bound(__k, static_cast<__node_const_pointer>(__rt->__right_), __result) |
||
2076 | ); |
||
2077 | } |
||
2078 | return 0; |
||
2079 | } |
||
2080 | |||
2081 | template <class _Tp, class _Compare, class _Allocator> |
||
2082 | template <class _Key> |
||
2083 | typename __tree<_Tp, _Compare, _Allocator>::iterator |
||
2084 | __tree<_Tp, _Compare, _Allocator>::__lower_bound(const _Key& __v, |
||
2085 | __node_pointer __root, |
||
2086 | __node_pointer __result) |
||
2087 | { |
||
2088 | while (__root != nullptr) |
||
2089 | { |
||
2090 | if (!value_comp()(__root->__value_, __v)) |
||
2091 | { |
||
2092 | __result = __root; |
||
2093 | __root = static_cast<__node_pointer>(__root->__left_); |
||
2094 | } |
||
2095 | else |
||
2096 | __root = static_cast<__node_pointer>(__root->__right_); |
||
2097 | } |
||
2098 | return iterator(__result); |
||
2099 | } |
||
2100 | |||
2101 | template <class _Tp, class _Compare, class _Allocator> |
||
2102 | template <class _Key> |
||
2103 | typename __tree<_Tp, _Compare, _Allocator>::const_iterator |
||
2104 | __tree<_Tp, _Compare, _Allocator>::__lower_bound(const _Key& __v, |
||
2105 | __node_const_pointer __root, |
||
2106 | __node_const_pointer __result) const |
||
2107 | { |
||
2108 | while (__root != nullptr) |
||
2109 | { |
||
2110 | if (!value_comp()(__root->__value_, __v)) |
||
2111 | { |
||
2112 | __result = __root; |
||
2113 | __root = static_cast<__node_const_pointer>(__root->__left_); |
||
2114 | } |
||
2115 | else |
||
2116 | __root = static_cast<__node_const_pointer>(__root->__right_); |
||
2117 | } |
||
2118 | return const_iterator(__result); |
||
2119 | } |
||
2120 | |||
2121 | template <class _Tp, class _Compare, class _Allocator> |
||
2122 | template <class _Key> |
||
2123 | typename __tree<_Tp, _Compare, _Allocator>::iterator |
||
2124 | __tree<_Tp, _Compare, _Allocator>::__upper_bound(const _Key& __v, |
||
2125 | __node_pointer __root, |
||
2126 | __node_pointer __result) |
||
2127 | { |
||
2128 | while (__root != nullptr) |
||
2129 | { |
||
2130 | if (value_comp()(__v, __root->__value_)) |
||
2131 | { |
||
2132 | __result = __root; |
||
2133 | __root = static_cast<__node_pointer>(__root->__left_); |
||
2134 | } |
||
2135 | else |
||
2136 | __root = static_cast<__node_pointer>(__root->__right_); |
||
2137 | } |
||
2138 | return iterator(__result); |
||
2139 | } |
||
2140 | |||
2141 | template <class _Tp, class _Compare, class _Allocator> |
||
2142 | template <class _Key> |
||
2143 | typename __tree<_Tp, _Compare, _Allocator>::const_iterator |
||
2144 | __tree<_Tp, _Compare, _Allocator>::__upper_bound(const _Key& __v, |
||
2145 | __node_const_pointer __root, |
||
2146 | __node_const_pointer __result) const |
||
2147 | { |
||
2148 | while (__root != nullptr) |
||
2149 | { |
||
2150 | if (value_comp()(__v, __root->__value_)) |
||
2151 | { |
||
2152 | __result = __root; |
||
2153 | __root = static_cast<__node_const_pointer>(__root->__left_); |
||
2154 | } |
||
2155 | else |
||
2156 | __root = static_cast<__node_const_pointer>(__root->__right_); |
||
2157 | } |
||
2158 | return const_iterator(__result); |
||
2159 | } |
||
2160 | |||
2161 | template <class _Tp, class _Compare, class _Allocator> |
||
2162 | template <class _Key> |
||
2163 | pair<typename __tree<_Tp, _Compare, _Allocator>::iterator, |
||
2164 | typename __tree<_Tp, _Compare, _Allocator>::iterator> |
||
2165 | __tree<_Tp, _Compare, _Allocator>::__equal_range_unique(const _Key& __k) |
||
2166 | { |
||
2167 | typedef pair<iterator, iterator> _Pp; |
||
2168 | __node_pointer __result = __end_node(); |
||
2169 | __node_pointer __rt = __root(); |
||
2170 | while (__rt != nullptr) |
||
2171 | { |
||
2172 | if (value_comp()(__k, __rt->__value_)) |
||
2173 | { |
||
2174 | __result = __rt; |
||
2175 | __rt = static_cast<__node_pointer>(__rt->__left_); |
||
2176 | } |
||
2177 | else if (value_comp()(__rt->__value_, __k)) |
||
2178 | __rt = static_cast<__node_pointer>(__rt->__right_); |
||
2179 | else |
||
2180 | return _Pp(iterator(__rt), |
||
2181 | iterator( |
||
2182 | __rt->__right_ != nullptr ? |
||
2183 | static_cast<__node_pointer>(__tree_min(__rt->__right_)) |
||
2184 | : __result)); |
||
2185 | } |
||
2186 | return _Pp(iterator(__result), iterator(__result)); |
||
2187 | } |
||
2188 | |||
2189 | template <class _Tp, class _Compare, class _Allocator> |
||
2190 | template <class _Key> |
||
2191 | pair<typename __tree<_Tp, _Compare, _Allocator>::const_iterator, |
||
2192 | typename __tree<_Tp, _Compare, _Allocator>::const_iterator> |
||
2193 | __tree<_Tp, _Compare, _Allocator>::__equal_range_unique(const _Key& __k) const |
||
2194 | { |
||
2195 | typedef pair<const_iterator, const_iterator> _Pp; |
||
2196 | __node_const_pointer __result = __end_node(); |
||
2197 | __node_const_pointer __rt = __root(); |
||
2198 | while (__rt != nullptr) |
||
2199 | { |
||
2200 | if (value_comp()(__k, __rt->__value_)) |
||
2201 | { |
||
2202 | __result = __rt; |
||
2203 | __rt = static_cast<__node_const_pointer>(__rt->__left_); |
||
2204 | } |
||
2205 | else if (value_comp()(__rt->__value_, __k)) |
||
2206 | __rt = static_cast<__node_const_pointer>(__rt->__right_); |
||
2207 | else |
||
2208 | return _Pp(const_iterator(__rt), |
||
2209 | const_iterator( |
||
2210 | __rt->__right_ != nullptr ? |
||
2211 | static_cast<__node_const_pointer>(__tree_min(__rt->__right_)) |
||
2212 | : __result)); |
||
2213 | } |
||
2214 | return _Pp(const_iterator(__result), const_iterator(__result)); |
||
2215 | } |
||
2216 | |||
2217 | template <class _Tp, class _Compare, class _Allocator> |
||
2218 | template <class _Key> |
||
2219 | pair<typename __tree<_Tp, _Compare, _Allocator>::iterator, |
||
2220 | typename __tree<_Tp, _Compare, _Allocator>::iterator> |
||
2221 | __tree<_Tp, _Compare, _Allocator>::__equal_range_multi(const _Key& __k) |
||
2222 | { |
||
2223 | typedef pair<iterator, iterator> _Pp; |
||
2224 | __node_pointer __result = __end_node(); |
||
2225 | __node_pointer __rt = __root(); |
||
2226 | while (__rt != nullptr) |
||
2227 | { |
||
2228 | if (value_comp()(__k, __rt->__value_)) |
||
2229 | { |
||
2230 | __result = __rt; |
||
2231 | __rt = static_cast<__node_pointer>(__rt->__left_); |
||
2232 | } |
||
2233 | else if (value_comp()(__rt->__value_, __k)) |
||
2234 | __rt = static_cast<__node_pointer>(__rt->__right_); |
||
2235 | else |
||
2236 | return _Pp(__lower_bound(__k, static_cast<__node_pointer>(__rt->__left_), __rt), |
||
2237 | __upper_bound(__k, static_cast<__node_pointer>(__rt->__right_), __result)); |
||
2238 | } |
||
2239 | return _Pp(iterator(__result), iterator(__result)); |
||
2240 | } |
||
2241 | |||
2242 | template <class _Tp, class _Compare, class _Allocator> |
||
2243 | template <class _Key> |
||
2244 | pair<typename __tree<_Tp, _Compare, _Allocator>::const_iterator, |
||
2245 | typename __tree<_Tp, _Compare, _Allocator>::const_iterator> |
||
2246 | __tree<_Tp, _Compare, _Allocator>::__equal_range_multi(const _Key& __k) const |
||
2247 | { |
||
2248 | typedef pair<const_iterator, const_iterator> _Pp; |
||
2249 | __node_const_pointer __result = __end_node(); |
||
2250 | __node_const_pointer __rt = __root(); |
||
2251 | while (__rt != nullptr) |
||
2252 | { |
||
2253 | if (value_comp()(__k, __rt->__value_)) |
||
2254 | { |
||
2255 | __result = __rt; |
||
2256 | __rt = static_cast<__node_const_pointer>(__rt->__left_); |
||
2257 | } |
||
2258 | else if (value_comp()(__rt->__value_, __k)) |
||
2259 | __rt = static_cast<__node_const_pointer>(__rt->__right_); |
||
2260 | else |
||
2261 | return _Pp(__lower_bound(__k, static_cast<__node_const_pointer>(__rt->__left_), __rt), |
||
2262 | __upper_bound(__k, static_cast<__node_const_pointer>(__rt->__right_), __result)); |
||
2263 | } |
||
2264 | return _Pp(const_iterator(__result), const_iterator(__result)); |
||
2265 | } |
||
2266 | |||
2267 | template <class _Tp, class _Compare, class _Allocator> |
||
2268 | typename __tree<_Tp, _Compare, _Allocator>::__node_holder |
||
2269 | __tree<_Tp, _Compare, _Allocator>::remove(const_iterator __p) _NOEXCEPT |
||
2270 | { |
||
2271 | __node_pointer __np = __p.__ptr_; |
||
2272 | if (__begin_node() == __np) |
||
2273 | { |
||
2274 | if (__np->__right_ != nullptr) |
||
2275 | __begin_node() = static_cast<__node_pointer>(__np->__right_); |
||
2276 | else |
||
2277 | __begin_node() = static_cast<__node_pointer>(__np->__parent_); |
||
2278 | } |
||
2279 | --size(); |
||
2280 | __tree_remove(__end_node()->__left_, |
||
2281 | static_cast<__node_base_pointer>(__np)); |
||
2282 | return __node_holder(__np, _Dp(__node_alloc(), true)); |
||
2283 | } |
||
2284 | |||
2285 | template <class _Tp, class _Compare, class _Allocator> |
||
2286 | inline _LIBCPP_INLINE_VISIBILITY |
||
2287 | void |
||
2288 | swap(__tree<_Tp, _Compare, _Allocator>& __x, |
||
2289 | __tree<_Tp, _Compare, _Allocator>& __y) |
||
2290 | _NOEXCEPT_(_NOEXCEPT_(__x.swap(__y))) |
||
2291 | { |
||
2292 | __x.swap(__y); |
||
2293 | } |
||
2294 | |||
2295 | _LIBCPP_END_NAMESPACE_STD |
||
2296 | |||
2297 | #endif // _LIBCPP___TREE |