_f_heap.c
上传用户:gzelex
上传日期:2007-01-07
资源大小:707k
文件大小:8k
开发平台:

MultiPlatform

  1. /*******************************************************************************
  2. +
  3. +  LEDA-R  3.2.3
  4. +
  5. +  _f_heap.c
  6. +
  7. +  Copyright (c) 1995  by  Max-Planck-Institut fuer Informatik
  8. +  Im Stadtwald, 66123 Saarbruecken, Germany     
  9. +  All rights reserved.
  10. *******************************************************************************/
  11. #include <LEDA/impl/f_heap.h>
  12. #include <math.h>
  13. //-----------------------------------------------------------------------------
  14. // class f_heap_node
  15. //-----------------------------------------------------------------------------
  16. f_heap_node* f_heap::first_item() const { return node_list; }
  17. f_heap_node* f_heap::next_item(f_heap_node* p) const { return p->next; }
  18. void f_heap_node::link(f_heap_node* child)
  19. // Vereinigung der beiden Heap geordneten Baeume h1 und h2
  20. // child wird neues Kind des Knotens
  21. // Vorbedingung: rank == child->rank && key <= child->key
  22.    //child aus seiner Liste loeschen
  23.    child->left->right = child->right;
  24.    child->right->left = child->left;
  25.    // child in zirkulaere Liste der Kinder von vater aufnehmen
  26.    if ( children == 0 )
  27.      { children = child;
  28.        // zirkulaere Liste aufbauen
  29.        child->left = child;
  30.        child->right = child;
  31.      }
  32.    else
  33.      // in bestehende Liste aufnehmen
  34.      { child->left = children;
  35.        child->right = children->right;
  36.        children->right->left = child;
  37.        children->right = child;
  38.      }
  39.    child->parent = this;
  40.    rank++;
  41.    child->mark = 0;
  42. }
  43. void f_heap_node::cut(f_heap_node* m_ptr)
  44. // loescht die Beziehung des Knotens zu seinem Elterknoten
  45. // und fuegt ihn in Wurzel-Liste (nach m_ptr) ein
  46. // Precondition: parent != 0 
  47.     if ( parent->rank == 1 )
  48.          parent->children = 0;
  49.      else  // mehrere Kinder
  50.         { if ( parent->children == this ) parent->children = right;
  51.           // x aus zirkulaerer Liste loeschen
  52.           left->right = right;
  53.           right->left = left;
  54.          } 
  55.      parent->rank--;
  56.      parent=0;
  57.     // in zirkulaere Liste der Wurzeln aufnehmen
  58.     left = m_ptr;
  59.     right = m_ptr->right;
  60.     m_ptr->right->left = this;
  61.     m_ptr->right = this;
  62. }
  63. //-----------------------------------------------------------------------------
  64. // class f_heap
  65. //-----------------------------------------------------------------------------
  66. f_heap::f_heap() 
  67. { node_count = 0;
  68.   minptr = 0;
  69.   node_list = 0;
  70.  }  
  71. f_heap::f_heap(const f_heap& H)
  72. { node_count = 0;
  73.   minptr = 0;
  74.   node_list = 0;
  75.   f_heap_node* min_p=0;
  76.   for(f_heap_node* p = H.first_item(); p; p = H.next_item(p))
  77.    { f_heap_node* q = insert(p->key,p->inf);  
  78.      // base class insert: calls default virtuals => we must call virtuals of H
  79.      // and compute the minimum
  80.      H.copy_key(q->key);    
  81.      H.copy_inf(q->inf);
  82.      if (min_p ==0) min_p = q;
  83.      else if ( H.cmp(q->key,min_p->key) < 0 ) min_p = q;
  84.     }
  85.    minptr = min_p;
  86. }
  87. f_heap& f_heap::operator=(const f_heap& H)
  88. { if (this != &H)
  89.   { clear();
  90.     for (f_heap_node* p = H.first_item(); p; p = H.next_item(p)) 
  91.      insert(p->key,p->inf);  // calls correct virtual functions 
  92.    }
  93.   return *this;
  94.  }
  95.   
  96. int f_heap::max_rank() const
  97. { // max_rank <= 1.4404 * log_2(node_count)
  98.   register int x = 0;
  99.   register int n = node_count;
  100.   while (n) { x++;
  101.               n >>= 1;
  102.              }
  103.   return int(1.5*x);
  104. }
  105. void f_heap::change_inf(f_heap_node* p, GenPtr i)
  106. { clear_inf(p->inf);
  107.   copy_inf(i);
  108.   p->inf = i;
  109. }
  110.   
  111. f_heap_node *f_heap::insert(GenPtr k, GenPtr info)
  112. {   // Kreieren eines neuen heap ordered trees und Einfuegen 
  113.     copy_key(k);
  114.     copy_inf(info);
  115.     f_heap_node *neu = new_f_heap_node(k,info);
  116.     if ( minptr == 0 )
  117.       { minptr = neu;
  118.         // zirkulaere Liste aufbauen
  119.         neu->right = neu;
  120.         neu->left = neu;
  121.       }
  122.     else  
  123.       // in zirkulaere Liste aufnehmen und minptr ueberpruefen
  124.       { neu->left = minptr;
  125.         neu->right = minptr->right;
  126.         minptr->right->left = neu;
  127.         minptr->right = neu;
  128.         if ( cmp(k,minptr->key) < 0 ) minptr = neu;
  129.        }
  130.     node_count++;
  131.     return ( neu );
  132.  } 
  133. void f_heap::decrease_key(f_heap_node *start, GenPtr newkey)
  134. { register f_heap_node* vater = start->parent;
  135.   register f_heap_node* x = start;
  136.   int d = cmp(newkey,x->key);
  137.   int dm =cmp(newkey,minptr->key);
  138.   if ( d==0  && dm != 0 ) return; 
  139.   if ( d > 0 )
  140.   { cout << "   new = "; print_key(newkey);
  141.     cout << "   old = "; print_key(x->key);
  142.     cout << "   min = "; print_key(minptr->key);
  143.     cout <<  "n";
  144.     error_handler(1,"f_heap: key too large in decrease_key.");
  145.    }
  146.   copy_key(newkey);
  147.   clear_key(x->key);
  148.   x->key = newkey; 
  149.   if ( vater && cmp(newkey,vater->key) <= 0 )
  150.   { // streiche Kante ( x, Vater(x) )
  151.     x->cut(minptr);
  152.     // errege(Vater(x))
  153.     x = vater;
  154.     while ( x->mark && x->parent )
  155.     { vater = x->parent;
  156.       x->cut(minptr);
  157.       x = vater;
  158.      }
  159.     x->mark = 1;
  160.    }
  161.   if ( dm <= 0 ) minptr = start;   // "=" --> del_item
  162. }
  163. void f_heap::del_min()
  164.   // remove node with minimal key
  165.   register f_heap_node* r1; 
  166.   register f_heap_node* r2; 
  167.   register f_heap_node* lauf; 
  168.   register f_heap_node* help; 
  169.   register int rank;
  170.   f_heap_node* res = minptr;
  171.   f_heap_node* rank_array[64];
  172.   // empty ?
  173.   if ( minptr == 0 ) return;
  174.   node_count--;
  175.   // last node ?
  176.   if (node_count==0 )
  177.   { minptr = 0;
  178.     clear_key(res->key);
  179.     clear_inf(res->inf);
  180.     delete res;
  181.     node_list = 0;
  182.     return;
  183.   }
  184.   // ring1 und ring2 zum Verschmelzen der Listen
  185.   r1 = minptr->right;
  186.   r2 = minptr->children;
  187.   if ( r2 )
  188.    {  // Elternbeziehung von ring2 loeschen
  189.      while ( r2->parent )
  190.       { r2->parent = 0;
  191.         r2 = r2->right;
  192.        }    
  193.      // Verschmelzen (altes Minimum bleibt zunaechst drin!)
  194.      r2->left->right = r1;
  195.      r1->left->right = r2;
  196.      help = r1->left;
  197.      r1->left = r2->left;
  198.      r2->left = help;
  199.     }
  200.   // Vereinigung der Heap geordneten Baeume
  201.   register f_heap_node** p;
  202.   register f_heap_node** q = rank_array+max_rank()+1;
  203.   for (p = rank_array; p < q; p++) *p = 0;
  204.   //int max = max_rank();
  205.   //for ( int i = 0 ; i <= max ; i++ ) rank_array[i] = 0;
  206.   lauf  = minptr->right;
  207.   help  = lauf;
  208.   if (!int_type())
  209.      while (lauf != minptr)   // altes Minimum dient als Stopper
  210.      { r1 = lauf;
  211.        rank = r1->rank;
  212.        lauf = lauf->right;
  213.        while (r2=rank_array[rank])
  214.        { rank_array[rank] = 0;
  215.          if (cmp(r1->key,r2->key) <= 0) r1->link(r2);
  216.          else { r2->link(r1);
  217.                 r1 = r2; 
  218.                }
  219.          rank++;
  220.         }
  221.        rank_array[rank] = r1;
  222.        if ( cmp(r1->key,help->key) <= 0 ) help = r1;  // neues Minimum
  223.       }
  224.   else 
  225.      while (lauf != minptr)  
  226.      { r1 = lauf;
  227.        rank = r1->rank;
  228.        lauf = lauf->right;
  229.        while (r2=rank_array[rank])
  230.        { rank_array[rank] = 0;
  231.          if (LEDA_ACCESS(int,r1->key) <= LEDA_ACCESS(int,r2->key)) r1->link(r2);
  232.          else { r2->link(r1);
  233.                 r1 = r2; 
  234.                }
  235.          rank++;
  236.         }
  237.        rank_array[rank] = r1;
  238.        if (LEDA_ACCESS(int,r1->key) <= LEDA_ACCESS(int,help->key)) help = r1;
  239.       }
  240.   // altes Minimum loeschen
  241.   minptr->left->right = minptr->right;
  242.   minptr->right->left = minptr->left;
  243.   // minptr neu setzen
  244.   minptr = help;
  245.   clear_key(res->key);
  246.   clear_inf(res->inf);
  247.   r1 = res->pred;
  248.   r2 = res->next;
  249.   if (r2) r2->pred = r1;
  250.   if (r1) 
  251.      r1->next  = r2;
  252.   else
  253.      node_list = r2;
  254.   delete res;
  255. }
  256. void f_heap::clear()
  257. { f_heap_node* tail = node_list;
  258.   if (tail==0) return;
  259.   for(;;)
  260.   { clear_key(tail->key);
  261.     clear_inf(tail->inf);
  262.     if (tail->next) 
  263.        tail = tail->next;
  264.     else 
  265.        break;
  266.    }
  267.    deallocate_list(node_list,tail,sizeof(f_heap_node));
  268.    node_count = 0;
  269.    minptr     = 0;
  270.    node_list  = 0;
  271. }