00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034
00035
00036
00037
00038
00039
00040
00041
00042
00043
00044 # ifndef TPL_BINNODEXT_H
00045 # define TPL_BINNODEXT_H
00046
00047 # include <tpl_binNode.H>
00048 # include <tpl_binNodeUtils.H>
00049
00050 using namespace Aleph;
00051
00052 namespace Aleph {
00053
00054 class BinNodeXt_Data
00055 {
00056 size_t count;
00057
00058 public:
00059
00060 BinNodeXt_Data() : count(1) { }
00061 BinNodeXt_Data(SentinelCtor) : count(0) { }
00062 size_t & getCount() { return count; }
00063 const size_t & size() const { return count; }
00064 void reset() { count = 1; }
00065 };
00066
00067 DECLARE_BINNODE_SENTINEL(BinNodeXt, 255, BinNodeXt_Data);
00068
00074 # define COUNT(p) ((p)->getCount())
00075
00092 template <class Node> inline
00093 Node * select_rec(Node * r, const size_t & i)
00094
00095 throw(std::exception, std::out_of_range)
00096
00097 {
00098
00099 I(r != Node::NullPtr);
00100 I(COUNT(Node::NullPtr) == 0);
00101
00102 if (i >= COUNT(r))
00103 throw std::out_of_range("infix position out of range");
00104
00105 if (i == COUNT(LLINK(r)))
00106 return r;
00107
00108 if (i < COUNT(LLINK(r)))
00109 return select_rec(static_cast<Node*>(LLINK(r)), i);
00110
00111 return select_rec(static_cast<Node*>(RLINK(r)), i - COUNT(LLINK(r)) - 1);
00112 }
00130 template <class Node> inline
00131 Node * select(Node * r, const size_t & pos)
00132
00133 throw(std::exception, std::out_of_range)
00134
00135 {
00136
00137 I(COUNT(Node::NullPtr) == 0);
00138
00139 if (pos >= COUNT(r))
00140 throw std::out_of_range("infix position out of range");
00141
00142
00143 for (size_t i = pos; i != COUNT(LLINK(r)); )
00144
00145 {
00146 I(i < COUNT(r));
00147
00148 if (i < COUNT(LLINK(r)))
00149 r = static_cast<Node*>(LLINK(r));
00150 else
00151 {
00152 i -= COUNT(LLINK(r)) + 1;
00153 r = static_cast<Node*>(RLINK(r));
00154 }
00155
00156 }
00157
00158 return r;
00159 }
00183 template <class Node, class Compare> inline
00184 size_t inorder_position(Node * r,
00185 const typename Node::key_type & key,
00186 Node *& node)
00187 {
00188
00189 I(COUNT(Node::NullPtr) == 0);
00190
00191 if (r == Node::NullPtr)
00192 throw std::domain_error("Key not found");
00193
00194
00195 if (Compare () (key, KEY(r)))
00196 return inorder_position(static_cast<Node*>(LLINK(r)), key, node);
00197 else if (Compare () (KEY(r), key))
00198 return inorder_position(static_cast<Node*>(RLINK(r)), key, node) +
00199 COUNT(LLINK(r)) + 1;
00200 else
00201 return COUNT(LLINK(r));
00202 }
00203 template <class Node> inline
00204 int inorder_position(Node * r,
00205 const typename Node::key_type & key,
00206 Node *& node)
00207 {
00208 return
00209 inorder_position<Node, Aleph::less<typename Node::key_type> >(r, key, node);
00210 }
00229 template <class Node, class Compare> inline
00230 Node * insert_by_key_xt(Node *& r, Node * p)
00231 {
00232
00233 I(COUNT(Node::NullPtr) == 0);
00234
00235 if (r == Node::NullPtr)
00236 return r = p;
00237
00238 Node * q;
00239
00240 if (Compare () (KEY(p), KEY(r)))
00241 {
00242 q = insert_by_key_xt<Node, Compare>(static_cast<Node*&>(LLINK(r)), p);
00243
00244 if (q != Node::NullPtr)
00245 ++COUNT(r);
00246 }
00247 else if (Compare ()(KEY(r), KEY(p)))
00248 {
00249 q = insert_by_key_xt<Node, Compare>(static_cast<Node*&>(RLINK(r)), p);
00250
00251 if (q != Node::NullPtr)
00252 ++COUNT(r);
00253 }
00254 else
00255 return (Node*) Node::NullPtr;
00256
00257 return q;
00258 }
00259 template <class Node> inline
00260 Node * insert_by_key_xt(Node *& root, Node * p)
00261 {
00262 return insert_by_key_xt<Node, Aleph::less<typename Node::key_type> >(root, p);
00263 }
00264 # define SPLIT split_key_rec_xt<Node, Compare>
00265
00287 template <class Node, class Compare> inline
00288 bool split_key_rec_xt(Node * root, const typename Node::key_type & key,
00289 Node *& l, Node *& r)
00290 {
00291 if (root == Node::NullPtr)
00292 {
00293 l = r = Node::NullPtr;
00294
00295 return true;
00296 }
00297
00298 if (Compare() (key, KEY(root)))
00299 {
00300 if (not SPLIT(LLINK(root), key, l, LLINK(root)))
00301 return false;
00302
00303 r = root;
00304 COUNT(r) -= COUNT(l);
00305 }
00306 else if (Compare() (KEY(root), key))
00307 {
00308 if (not SPLIT(RLINK(root), key, RLINK(root), r))
00309 return false;
00310
00311 l = root;
00312 COUNT(l) -= COUNT(r);
00313 }
00314 else
00315 return false;
00316
00317 return true;
00318 }
00319 # undef SPLIT
00320
00321 template <class Node> inline
00322 bool split_key_rec_xt(Node * root, const typename Node::key_type & key,
00323 Node *& l, Node *& r)
00324 {
00325 return
00326 split_key_rec_xt<Node, Aleph::less<typename Node::key_type> >(root, key,
00327 l, r);
00328 }
00346 template <class Node, class Compare> inline
00347 Node * insert_root_xt(Node *& root, Node * p)
00348 {
00349 if (root == Node::NullPtr)
00350 return p;
00351
00352 if (not split_key_rec_xt<Node, Compare>(root, KEY(p), LLINK(p), RLINK(p)))
00353 return Node::NullPtr;
00354
00355 COUNT(p) = COUNT(LLINK(p)) + COUNT(RLINK(p)) + 1;
00356
00357 root = p;
00358
00359 return p;
00360 }
00381 template <class Node> inline
00382 void split_pos_rec(Node * r, const size_t & i, Node *& ts, Node *& tg)
00383 {
00384
00385 if (i > COUNT(r))
00386 throw std::out_of_range("infix position out of range");
00387
00388 if (i == COUNT(r))
00389 {
00390 ts = r;
00391 tg = Node::NullPtr;
00392
00393 return;
00394 }
00395
00396 if (i == COUNT(LLINK(r)))
00397 {
00398 ts = LLINK(r);
00399 tg = r;
00400 LLINK(tg) = Node::NullPtr;
00401 COUNT(tg) -= COUNT(ts);
00402
00403 return;
00404 }
00405
00406 if (i < COUNT(LLINK(r)))
00407 {
00408 split_pos_rec(static_cast<Node*>(LLINK(r)), i, ts,
00409 static_cast<Node*&>(LLINK(r)));
00410 tg = r;
00411 COUNT(r) -= COUNT(ts);
00412 }
00413 else
00414 {
00415 split_pos_rec(static_cast<Node*>(RLINK(r)), i - (COUNT(LLINK(r)) + 1),
00416 static_cast<Node*&>(RLINK(r)), tg);
00417 ts = r;
00418 COUNT(r) -= COUNT(tg);
00419 }
00420 }
00435 template <class Node> inline
00436 void insert_by_pos_xt(Node *& r, Node * p, const size_t & pos)
00437 {
00438
00439 I(COUNT(Node::NullPtr) == 0);
00440
00441 split_pos_rec(r, pos, static_cast<Node*&>(LLINK(p)),
00442 static_cast<Node*&>(RLINK(p)));
00443
00444 COUNT(p) = COUNT(LLINK(p)) + 1 + COUNT(RLINK(p));
00445
00446 r = p;
00447 }
00463 template <class Node> inline
00464 Node * join_exclusive_xt(Node *& ts, Node *& tg)
00465 {
00466 if (ts == Node::NullPtr)
00467 return tg;
00468
00469 if (tg == Node::NullPtr)
00470 return ts;
00471
00472 LLINK(tg) = join_exclusive_xt(RLINK(ts), LLINK(tg));
00473 RLINK(ts) = tg;
00474
00475 COUNT(tg) = COUNT(LLINK(tg)) + 1 + COUNT(RLINK(tg));
00476 COUNT(ts) = COUNT(LLINK(ts)) + 1 + COUNT(RLINK(ts));
00477
00478 Node * ret_val = ts;
00479
00480 ts = tg = Node::NullPtr;
00481
00482 return ret_val;
00483 }
00484 # define REMOVE remove_by_key_xt<Node, Compare>
00485
00503 template <class Node, class Compare> inline
00504 Node * remove_by_key_xt(Node *& root, const typename Node::key_type & key)
00505 {
00506
00507 I(root != Node::NullPtr);
00508
00509 if (root == Node::NullPtr)
00510 return (Node*) Node::NullPtr;
00511
00512 Node * ret_val = Node::NullPtr;
00513
00514 if (Compare () (key, KEY(root)))
00515 {
00516 ret_val = REMOVE(static_cast<Node*&>(LLINK(root)), key);
00517
00518 if (ret_val != Node::NullPtr)
00519 --COUNT(root);
00520
00521 return ret_val;
00522 }
00523 else if (Compare () (KEY(root), key))
00524 {
00525 ret_val = REMOVE(static_cast<Node*&>(RLINK(root)), key);
00526
00527 if (ret_val != Node::NullPtr)
00528 --COUNT(root);
00529
00530 return ret_val;
00531 }
00532
00533 ret_val = root;
00534
00535 root = join_exclusive_xt(static_cast<Node*&>(LLINK(root)),
00536 static_cast<Node*&>(RLINK(root)));
00537
00538 ret_val->reset();
00539
00540
00541 return ret_val;
00542 }
00543 # undef REMOVE
00544
00545 template <class Node> inline
00546 Node * remove_by_key_xt(Node *& root, const typename Node::key_type & key)
00547 {
00548 I(root != Node::NullPtr);
00549
00550 return remove_by_key_xt<Node, Aleph::less<typename Node::key_type> >
00551 (root, key);
00552 }
00569 template <class Node> inline
00570 Node * remove_by_pos_xt(Node *& root, const size_t & pos)
00571 {
00572
00573 if (pos >= COUNT(root))
00574 throw std::out_of_range("infix position out of range");
00575
00576 if (COUNT(LLINK(root)) == pos)
00577 {
00578 Node * ret_val = root;
00579
00580 root = join_exclusive_xt(static_cast<Node*&>(LLINK(root)),
00581 static_cast<Node*&>(RLINK(root)));
00582
00583 ret_val->reset();
00584
00585 return ret_val;
00586 }
00587
00588 Node * ret_val;
00589
00590 if (pos < COUNT(LLINK(root)))
00591 ret_val = remove_by_pos_xt(static_cast<Node*&>(LLINK(root)), pos);
00592 else
00593 ret_val = remove_by_pos_xt(static_cast<Node*&>(RLINK(root)),
00594 pos - (COUNT(LLINK(root)) + 1));
00595
00596 if (ret_val != Node::NullPtr)
00597 --COUNT(root);
00598
00599 return ret_val;
00600 }
00601 template <class Node> inline
00602 bool check_rank_tree(Node * root)
00603 {
00604 if (root == Node::NullPtr)
00605 return true;
00606
00607 if (COUNT(LLINK(root)) + COUNT(RLINK(root)) + 1 != COUNT(root))
00608 return false;
00609
00610 return check_rank_tree(LLINK(root)) and check_rank_tree(RLINK(root));
00611 }
00616 template <class Node> inline
00617 Node * rotate_to_right_xt(Node* p)
00618 {
00619
00620 I(p != Node::NullPtr);
00621
00622 Node * q = static_cast<Node*>(LLINK(p));
00623 LLINK(p) = RLINK(q);
00624 RLINK(q) = p;
00625 COUNT(p) -= 1 + COUNT(LLINK(q));
00626 COUNT(q) += 1 + COUNT(RLINK(p));
00627 return q;
00628 }
00633 template <class Node> inline
00634 Node * rotate_to_left_xt(Node* p)
00635 {
00636 I(p != Node::NullPtr);
00637
00638 Node * q = static_cast<Node*>(RLINK(p));
00639 RLINK(p) = LLINK(q);
00640 LLINK(q) = p;
00641
00642 COUNT(p) -= 1 + COUNT(RLINK(q));
00643 COUNT(q) += 1 + COUNT(LLINK(p));
00644
00645 return q;
00646 }
00647
00648 }
00649
00650 # endif // TPL_BINNODEXT_H
00651