home *** CD-ROM | disk | FTP | other *** search
/ Aminet 5 / Aminet 5 - March 1995.iso / Aminet / dev / misc / LEDA_src.lha / LEDA-3.1c-source / src / prio / _f_heap.c < prev    next >
Encoding:
C/C++ Source or Header  |  1994-11-17  |  7.6 KB  |  362 lines

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