home *** CD-ROM | disk | FTP | other *** search
/ Power-Programmierung / CD2.mdf / c / library / dos / diverses / leda / src / basic / _f_heap.c < prev    next >
Encoding:
C/C++ Source or Header  |  1991-11-15  |  7.9 KB  |  347 lines

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