1 // Copyright 2004 The Trustees of Indiana University. 2 3 // Use, modification and distribution is subject to the Boost Software 4 // License, Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at 5 // http://www.boost.org/LICENSE_1_0.txt) 6 7 // Authors: Douglas Gregor 8 // Andrew Lumsdaine 9 #warning \ 10 "Use of relaxed_heap is depreciated; please use the standard heap functions." 11 #ifndef BOOST_RELAXED_HEAP_HEADER 12 #define BOOST_RELAXED_HEAP_HEADER 13 14 #include <boost/config/header_deprecated.hpp> 15 BOOST_HEADER_DEPRECATED("the standard heap functions") 16 17 #include <functional> 18 #include <boost/property_map/property_map.hpp> 19 #include <boost/optional.hpp> 20 #include <vector> 21 #include <climits> // for CHAR_BIT 22 #include <boost/none.hpp> 23 24 #ifdef BOOST_RELAXED_HEAP_DEBUG 25 #include <iostream> 26 #endif // BOOST_RELAXED_HEAP_DEBUG 27 28 #if defined(BOOST_MSVC) 29 #pragma warning(push) 30 #pragma warning(disable : 4355) // complaint about using 'this' to 31 #endif // initialize a member 32 33 namespace boost 34 { 35 36 template < typename IndexedType, typename Compare = std::less< IndexedType >, 37 typename ID = identity_property_map > 38 class relaxed_heap 39 { 40 struct group; 41 42 typedef relaxed_heap self_type; 43 typedef std::size_t rank_type; 44 45 public: 46 typedef IndexedType value_type; 47 typedef rank_type size_type; 48 49 private: 50 /** 51 * The kind of key that a group has. The actual values are discussed 52 * in-depth in the documentation of the @c kind field of the @c group 53 * structure. Note that the order of the enumerators *IS* important 54 * and must not be changed. 55 */ 56 enum group_key_kind 57 { 58 smallest_key, 59 stored_key, 60 largest_key 61 }; 62 63 struct group 64 { groupboost::relaxed_heap::group65 explicit group(group_key_kind kind = largest_key) 66 : kind(kind), parent(this), rank(0) 67 { 68 } 69 70 /** The value associated with this group. This value is only valid 71 * when @c kind!=largest_key (which indicates a deleted 72 * element). Note that the use of boost::optional increases the 73 * memory requirements slightly but does not result in extraneous 74 * memory allocations or deallocations. The optional could be 75 * eliminated when @c value_type is a model of 76 * DefaultConstructible. 77 */ 78 ::boost::optional< value_type > value; 79 80 /** 81 * The kind of key stored at this group. This may be @c 82 * smallest_key, which indicates that the key is infinitely small; 83 * @c largest_key, which indicates that the key is infinitely 84 * large; or @c stored_key, which means that the key is unknown, 85 * but its relationship to other keys can be determined via the 86 * comparison function object. 87 */ 88 group_key_kind kind; 89 90 /// The parent of this group. Will only be NULL for the dummy root group 91 group* parent; 92 93 /// The rank of this group. Equivalent to the number of children in 94 /// the group. 95 rank_type rank; 96 97 /** The children of this group. For the dummy root group, these are 98 * the roots. This is an array of length log n containing pointers 99 * to the child groups. 100 */ 101 group** children; 102 }; 103 log_base_2(size_type n)104 size_type log_base_2(size_type n) // log2 is a macro on some platforms 105 { 106 size_type leading_zeroes = 0; 107 do 108 { 109 size_type next = n << 1; 110 if (n == (next >> 1)) 111 { 112 ++leading_zeroes; 113 n = next; 114 } 115 else 116 { 117 break; 118 } 119 } while (true); 120 return sizeof(size_type) * CHAR_BIT - leading_zeroes - 1; 121 } 122 123 public: relaxed_heap(size_type n,const Compare & compare=Compare (),const ID & id=ID ())124 relaxed_heap( 125 size_type n, const Compare& compare = Compare(), const ID& id = ID()) 126 : compare(compare), id(id), root(smallest_key), groups(n), smallest_value(0) 127 { 128 if (n == 0) 129 { 130 root.children = new group*[1]; 131 return; 132 } 133 134 log_n = log_base_2(n); 135 if (log_n == 0) 136 log_n = 1; 137 size_type g = n / log_n; 138 if (n % log_n > 0) 139 ++g; 140 size_type log_g = log_base_2(g); 141 size_type r = log_g; 142 143 // Reserve an appropriate amount of space for data structures, so 144 // that we do not need to expand them. 145 index_to_group.resize(g); 146 A.resize(r + 1, 0); 147 root.rank = r + 1; 148 root.children = new group*[(log_g + 1) * (g + 1)]; 149 for (rank_type i = 0; i < r + 1; ++i) 150 root.children[i] = 0; 151 152 // Build initial heap 153 size_type idx = 0; 154 while (idx < g) 155 { 156 root.children[r] = &index_to_group[idx]; 157 idx = build_tree(root, idx, r, log_g + 1); 158 if (idx != g) 159 r = static_cast< size_type >(log_base_2(g - idx)); 160 } 161 } 162 ~relaxed_heap()163 ~relaxed_heap() { delete[] root.children; } 164 push(const value_type & x)165 void push(const value_type& x) 166 { 167 groups[get(id, x)] = x; 168 update(x); 169 } 170 update(const value_type & x)171 void update(const value_type& x) 172 { 173 group* a = &index_to_group[get(id, x) / log_n]; 174 if (!a->value || *a->value == x || compare(x, *a->value)) 175 { 176 if (a != smallest_value) 177 smallest_value = 0; 178 a->kind = stored_key; 179 a->value = x; 180 promote(a); 181 } 182 } 183 remove(const value_type & x)184 void remove(const value_type& x) 185 { 186 group* a = &index_to_group[get(id, x) / log_n]; 187 assert(groups[get(id, x)]); 188 a->value = x; 189 a->kind = smallest_key; 190 promote(a); 191 smallest_value = a; 192 pop(); 193 } 194 top()195 value_type& top() 196 { 197 find_smallest(); 198 assert(smallest_value->value != none); 199 return *smallest_value->value; 200 } 201 top() const202 const value_type& top() const 203 { 204 find_smallest(); 205 assert(smallest_value->value != none); 206 return *smallest_value->value; 207 } 208 empty() const209 bool empty() const 210 { 211 find_smallest(); 212 return !smallest_value || (smallest_value->kind == largest_key); 213 } 214 contains(const value_type & x) const215 bool contains(const value_type& x) const 216 { 217 return static_cast< bool >(groups[get(id, x)]); 218 } 219 pop()220 void pop() 221 { 222 // Fill in smallest_value. This is the group x. 223 find_smallest(); 224 group* x = smallest_value; 225 smallest_value = 0; 226 227 // Make x a leaf, giving it the smallest value within its group 228 rank_type r = x->rank; 229 group* p = x->parent; 230 { 231 assert(x->value != none); 232 233 // Find x's group 234 size_type start = get(id, *x->value) - get(id, *x->value) % log_n; 235 size_type end = start + log_n; 236 if (end > groups.size()) 237 end = groups.size(); 238 239 // Remove the smallest value from the group, and find the new 240 // smallest value. 241 groups[get(id, *x->value)].reset(); 242 x->value.reset(); 243 x->kind = largest_key; 244 for (size_type i = start; i < end; ++i) 245 { 246 if (groups[i] && (!x->value || compare(*groups[i], *x->value))) 247 { 248 x->kind = stored_key; 249 x->value = groups[i]; 250 } 251 } 252 } 253 x->rank = 0; 254 255 // Combine prior children of x with x 256 group* y = x; 257 for (size_type c = 0; c < r; ++c) 258 { 259 group* child = x->children[c]; 260 if (A[c] == child) 261 A[c] = 0; 262 y = combine(y, child); 263 } 264 265 // If we got back something other than x, let y take x's place 266 if (y != x) 267 { 268 y->parent = p; 269 p->children[r] = y; 270 271 assert(r == y->rank); 272 if (A[y->rank] == x) 273 A[y->rank] = do_compare(y, p) ? y : 0; 274 } 275 } 276 277 #ifdef BOOST_RELAXED_HEAP_DEBUG 278 /************************************************************************* 279 * Debugging support * 280 *************************************************************************/ dump_tree()281 void dump_tree() { dump_tree(std::cout); } dump_tree(std::ostream & out)282 void dump_tree(std::ostream& out) { dump_tree(out, &root); } 283 dump_tree(std::ostream & out,group * p,bool in_progress=false)284 void dump_tree(std::ostream& out, group* p, bool in_progress = false) 285 { 286 if (!in_progress) 287 { 288 out << "digraph heap {\n" 289 << " edge[dir=\"back\"];\n"; 290 } 291 292 size_type p_index = 0; 293 if (p != &root) 294 while (&index_to_group[p_index] != p) 295 ++p_index; 296 297 for (size_type i = 0; i < p->rank; ++i) 298 { 299 group* c = p->children[i]; 300 if (c) 301 { 302 size_type c_index = 0; 303 if (c != &root) 304 while (&index_to_group[c_index] != c) 305 ++c_index; 306 307 out << " "; 308 if (p == &root) 309 out << 'p'; 310 else 311 out << p_index; 312 out << " -> "; 313 if (c == &root) 314 out << 'p'; 315 else 316 out << c_index; 317 if (A[c->rank] == c) 318 out << " [style=\"dotted\"]"; 319 out << ";\n"; 320 dump_tree(out, c, true); 321 322 // Emit node information 323 out << " "; 324 if (c == &root) 325 out << 'p'; 326 else 327 out << c_index; 328 out << " [label=\""; 329 if (c == &root) 330 out << 'p'; 331 else 332 out << c_index; 333 out << ":"; 334 size_type start = c_index * log_n; 335 size_type end = start + log_n; 336 if (end > groups.size()) 337 end = groups.size(); 338 while (start != end) 339 { 340 if (groups[start]) 341 { 342 out << " " << get(id, *groups[start]); 343 if (*groups[start] == *c->value) 344 out << "(*)"; 345 } 346 ++start; 347 } 348 out << '"'; 349 350 if (do_compare(c, p)) 351 { 352 out << " "; 353 if (c == &root) 354 out << 'p'; 355 else 356 out << c_index; 357 out << ", style=\"filled\", fillcolor=\"gray\""; 358 } 359 out << "];\n"; 360 } 361 else 362 { 363 assert(p->parent == p); 364 } 365 } 366 if (!in_progress) 367 out << "}\n"; 368 } 369 valid()370 bool valid() 371 { 372 // Check that the ranks in the A array match the ranks of the 373 // groups stored there. Also, the active groups must be the last 374 // child of their parent. 375 for (size_type r = 0; r < A.size(); ++r) 376 { 377 if (A[r] && A[r]->rank != r) 378 return false; 379 380 if (A[r] && A[r]->parent->children[A[r]->parent->rank - 1] != A[r]) 381 return false; 382 } 383 384 // The root must have no value and a key of -Infinity 385 if (root.kind != smallest_key) 386 return false; 387 388 return valid(&root); 389 } 390 valid(group * p)391 bool valid(group* p) 392 { 393 for (size_type i = 0; i < p->rank; ++i) 394 { 395 group* c = p->children[i]; 396 if (c) 397 { 398 // Check link structure 399 if (c->parent != p) 400 return false; 401 if (c->rank != i) 402 return false; 403 404 // A bad group must be active 405 if (do_compare(c, p) && A[i] != c) 406 return false; 407 408 // Check recursively 409 if (!valid(c)) 410 return false; 411 } 412 else 413 { 414 // Only the root may 415 if (p != &root) 416 return false; 417 } 418 } 419 return true; 420 } 421 422 #endif // BOOST_RELAXED_HEAP_DEBUG 423 424 private: build_tree(group & parent,size_type idx,size_type r,size_type max_rank)425 size_type build_tree( 426 group& parent, size_type idx, size_type r, size_type max_rank) 427 { 428 group& this_group = index_to_group[idx]; 429 this_group.parent = &parent; 430 ++idx; 431 432 this_group.children = root.children + (idx * max_rank); 433 this_group.rank = r; 434 for (size_type i = 0; i < r; ++i) 435 { 436 this_group.children[i] = &index_to_group[idx]; 437 idx = build_tree(this_group, idx, i, max_rank); 438 } 439 return idx; 440 } 441 find_smallest() const442 void find_smallest() const 443 { 444 group** roots = root.children; 445 446 if (!smallest_value) 447 { 448 std::size_t i; 449 for (i = 0; i < root.rank; ++i) 450 { 451 if (roots[i] 452 && (!smallest_value 453 || do_compare(roots[i], smallest_value))) 454 { 455 smallest_value = roots[i]; 456 } 457 } 458 for (i = 0; i < A.size(); ++i) 459 { 460 if (A[i] 461 && (!smallest_value || do_compare(A[i], smallest_value))) 462 smallest_value = A[i]; 463 } 464 } 465 } 466 do_compare(group * x,group * y) const467 bool do_compare(group* x, group* y) const 468 { 469 return (x->kind < y->kind 470 || (x->kind == y->kind && x->kind == stored_key 471 && compare(*x->value, *y->value))); 472 } 473 promote(group * a)474 void promote(group* a) 475 { 476 assert(a != 0); 477 rank_type r = a->rank; 478 group* p = a->parent; 479 assert(p != 0); 480 if (do_compare(a, p)) 481 { 482 // s is the rank + 1 sibling 483 group* s = p->rank > r + 1 ? p->children[r + 1] : 0; 484 485 // If a is the last child of p 486 if (r == p->rank - 1) 487 { 488 if (!A[r]) 489 A[r] = a; 490 else if (A[r] != a) 491 pair_transform(a); 492 } 493 else 494 { 495 assert(s != 0); 496 if (A[r + 1] == s) 497 active_sibling_transform(a, s); 498 else 499 good_sibling_transform(a, s); 500 } 501 } 502 } 503 combine(group * a1,group * a2)504 group* combine(group* a1, group* a2) 505 { 506 assert(a1->rank == a2->rank); 507 if (do_compare(a2, a1)) 508 do_swap(a1, a2); 509 a1->children[a1->rank++] = a2; 510 a2->parent = a1; 511 clean(a1); 512 return a1; 513 } 514 clean(group * q)515 void clean(group* q) 516 { 517 if (2 > q->rank) 518 return; 519 group* qp = q->children[q->rank - 1]; 520 rank_type s = q->rank - 2; 521 group* x = q->children[s]; 522 group* xp = qp->children[s]; 523 assert(s == x->rank); 524 525 // If x is active, swap x and xp 526 if (A[s] == x) 527 { 528 q->children[s] = xp; 529 xp->parent = q; 530 qp->children[s] = x; 531 x->parent = qp; 532 } 533 } 534 pair_transform(group * a)535 void pair_transform(group* a) 536 { 537 #if defined(BOOST_RELAXED_HEAP_DEBUG) && BOOST_RELAXED_HEAP_DEBUG > 1 538 std::cerr << "- pair transform\n"; 539 #endif 540 rank_type r = a->rank; 541 542 // p is a's parent 543 group* p = a->parent; 544 assert(p != 0); 545 546 // g is p's parent (a's grandparent) 547 group* g = p->parent; 548 assert(g != 0); 549 550 // a' <- A(r) 551 assert(A[r] != 0); 552 group* ap = A[r]; 553 assert(ap != 0); 554 555 // A(r) <- nil 556 A[r] = 0; 557 558 // let a' have parent p' 559 group* pp = ap->parent; 560 assert(pp != 0); 561 562 // let a' have grandparent g' 563 group* gp = pp->parent; 564 assert(gp != 0); 565 566 // Remove a and a' from their parents 567 assert(ap 568 == pp->children[pp->rank - 1]); // Guaranteed because ap is active 569 --pp->rank; 570 571 // Guaranteed by caller 572 assert(a == p->children[p->rank - 1]); 573 --p->rank; 574 575 // Note: a, ap, p, pp all have rank r 576 if (do_compare(pp, p)) 577 { 578 do_swap(a, ap); 579 do_swap(p, pp); 580 do_swap(g, gp); 581 } 582 583 // Assuming k(p) <= k(p') 584 // make p' the rank r child of p 585 assert(r == p->rank); 586 p->children[p->rank++] = pp; 587 pp->parent = p; 588 589 // Combine a, ap into a rank r+1 group c 590 group* c = combine(a, ap); 591 592 // make c the rank r+1 child of g' 593 assert(gp->rank > r + 1); 594 gp->children[r + 1] = c; 595 c->parent = gp; 596 597 #if defined(BOOST_RELAXED_HEAP_DEBUG) && BOOST_RELAXED_HEAP_DEBUG > 1 598 std::cerr << "After pair transform...\n"; 599 dump_tree(); 600 #endif 601 602 if (A[r + 1] == pp) 603 A[r + 1] = c; 604 else 605 promote(c); 606 } 607 active_sibling_transform(group * a,group * s)608 void active_sibling_transform(group* a, group* s) 609 { 610 #if defined(BOOST_RELAXED_HEAP_DEBUG) && BOOST_RELAXED_HEAP_DEBUG > 1 611 std::cerr << "- active sibling transform\n"; 612 #endif 613 group* p = a->parent; 614 group* g = p->parent; 615 616 // remove a, s from their parents 617 assert(s->parent == p); 618 assert(p->children[p->rank - 1] == s); 619 --p->rank; 620 assert(p->children[p->rank - 1] == a); 621 --p->rank; 622 623 rank_type r = a->rank; 624 A[r + 1] = 0; 625 a = combine(p, a); 626 group* c = combine(a, s); 627 628 // make c the rank r+2 child of g 629 assert(g->children[r + 2] == p); 630 g->children[r + 2] = c; 631 c->parent = g; 632 if (A[r + 2] == p) 633 A[r + 2] = c; 634 else 635 promote(c); 636 } 637 good_sibling_transform(group * a,group * s)638 void good_sibling_transform(group* a, group* s) 639 { 640 #if defined(BOOST_RELAXED_HEAP_DEBUG) && BOOST_RELAXED_HEAP_DEBUG > 1 641 std::cerr << "- good sibling transform\n"; 642 #endif 643 rank_type r = a->rank; 644 group* c = s->children[s->rank - 1]; 645 assert(c->rank == r); 646 if (A[r] == c) 647 { 648 #if defined(BOOST_RELAXED_HEAP_DEBUG) && BOOST_RELAXED_HEAP_DEBUG > 1 649 std::cerr << "- good sibling pair transform\n"; 650 #endif 651 A[r] = 0; 652 group* p = a->parent; 653 654 // Remove c from its parent 655 --s->rank; 656 657 // Make s the rank r child of p 658 s->parent = p; 659 p->children[r] = s; 660 661 // combine a, c and let the result by the rank r+1 child of p 662 assert(p->rank > r + 1); 663 group* x = combine(a, c); 664 x->parent = p; 665 p->children[r + 1] = x; 666 667 if (A[r + 1] == s) 668 A[r + 1] = x; 669 else 670 promote(x); 671 672 #if defined(BOOST_RELAXED_HEAP_DEBUG) && BOOST_RELAXED_HEAP_DEBUG > 1 673 dump_tree(std::cerr); 674 #endif 675 // pair_transform(a); 676 } 677 else 678 { 679 // Clean operation 680 group* p = a->parent; 681 s->children[r] = a; 682 a->parent = s; 683 p->children[r] = c; 684 c->parent = p; 685 686 promote(a); 687 } 688 } 689 do_swap(group * & x,group * & y)690 static void do_swap(group*& x, group*& y) 691 { 692 group* tmp = x; 693 x = y; 694 y = tmp; 695 } 696 697 /// Function object that compares two values in the heap 698 Compare compare; 699 700 /// Mapping from values to indices in the range [0, n). 701 ID id; 702 703 /** The root group of the queue. This group is special because it will 704 * never store a value, but it acts as a parent to all of the 705 * roots. Thus, its list of children is the list of roots. 706 */ 707 group root; 708 709 /** Mapping from the group index of a value to the group associated 710 * with that value. If a value is not in the queue, then the "value" 711 * field will be empty. 712 */ 713 std::vector< group > index_to_group; 714 715 /** Flat data structure containing the values in each of the 716 * groups. It will be indexed via the id of the values. The groups 717 * are each log_n long, with the last group potentially being 718 * smaller. 719 */ 720 std::vector< ::boost::optional< value_type > > groups; 721 722 /** The list of active groups, indexed by rank. When A[r] is null, 723 * there is no active group of rank r. Otherwise, A[r] is the active 724 * group of rank r. 725 */ 726 std::vector< group* > A; 727 728 /** The group containing the smallest value in the queue, which must 729 * be either a root or an active group. If this group is null, then we 730 * will need to search for this group when it is needed. 731 */ 732 mutable group* smallest_value; 733 734 /// Cached value log_base_2(n) 735 size_type log_n; 736 }; 737 738 } // end namespace boost 739 740 #if defined(BOOST_MSVC) 741 #pragma warning(pop) 742 #endif 743 744 #endif // BOOST_RELAXED_HEAP_HEADER 745