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