home *** CD-ROM | disk | FTP | other *** search
- /*******************************************************************************
- +
- + LEDA 2.1.1 11-15-1991
- +
- +
- + _f_heap.c
- +
- +
- + Copyright (c) 1991 by Max-Planck-Institut fuer Informatik
- + Im Stadtwald, 6600 Saarbruecken, FRG
- + All rights reserved.
- +
- *******************************************************************************/
-
-
- #ifndef HEAPH
- #include <LEDA/f_heap.h>
- #endif
-
- #ifndef MATHH
- #include <math.h>
- #endif
-
- //-----------------------------------------------------------------------------
- // class f_heap_node
- //-----------------------------------------------------------------------------
-
-
- void f_heap_node::link(f_heap_node *sohn)
- // Vereinigung der beiden Heap geordneten Baeume h1 und h2
- // sohn wird neues Kind des Knotens
- // Vorbedingung: rank == sohn->rank && key <= sohn->key
- {
- //sohn aus seiner Liste loeschen
- sohn->left->right = sohn->right;
- sohn->right->left = sohn->left;
-
- // sohn in zirkulaere Liste der Kinder von vater aufnehmen
- if ( children == 0 )
- { children = sohn;
- // zirkulaere Liste aufbauen
- sohn->left = sohn;
- sohn->right = sohn;
- }
- else
- // in bestehende Liste aufnehmen
- { sohn->left = children;
- sohn->right = children->right;
- children->right->left = sohn;
- children->right = sohn;
- }
-
- sohn->parent = this;
- rank++;
- sohn->mark = 0;
-
- } // end of link()
-
- void f_heap_node::cut(f_heap_node* m_ptr)
- // loescht die Beziehung des Knotens zu seinem Elterknoten
- // und fuegt ihn in Wurzel-Liste (nach m_ptr) ein
- // Precondition: parent != 0
- {
- if ( parent->rank == 1 )
- parent->children = 0;
- else // mehrere Kinder
- { if ( parent->children == this ) parent->children = right;
- // x aus zirkulaerer Liste loeschen
- left->right = right;
- right->left = left;
- }
- parent->rank--;
- parent=0;
-
- // in zirkulaere Liste der Wurzeln aufnehmen
-
- left = m_ptr;
- right = m_ptr->right;
- m_ptr->right->left = this;
- m_ptr->right = this;
-
- } // end of cut()
-
-
- //-----------------------------------------------------------------------------
- // class f_heap
- //-----------------------------------------------------------------------------
-
- f_heap::f_heap()
- { node_count = 0;
- minptr = 0;
- node_list = 0;
- rank_field = new f_heap_node*[63];
- }
-
- f_heap_node* f_heap::first_item() const
- { while (node_list && node_list->deleted)
- { f_heap_node* p = node_list;
- f_heap_node *const *const q = &node_list;
- (*(f_heap_node**)q) = node_list->next;
- delete p;
- }
- return node_list;
- }
-
- f_heap_node* f_heap::next_item(f_heap_node* p) const
- { while (p->next && p->next->deleted)
- { f_heap_node* q = p->next->next;
- delete p->next;
- p->next = q;
- }
- return p->next;
- }
-
- f_heap::f_heap(const f_heap& H)
- { node_count = 0;
- minptr = 0;
- node_list = 0;
- rank_field = new f_heap_node*[63];
-
- f_heap_node* min_p=0;
-
- for(f_heap_node* p = H.first_item(); p; p = H.next_item(p))
- { f_heap_node* q = insert(p->key,p->inf);
- // base class insert: calls default virtuals => we must call virtuals of H
- // and compute the minimum
- H.copy_key(q->key);
- H.copy_inf(q->inf);
- if (min_p ==0) min_p = q;
- else if ( H.cmp(q->key,min_p->key) < 0 ) min_p = q;
- }
- minptr = min_p;
- }
-
- f_heap& f_heap::operator=(const f_heap& H)
- { if (this == &H) return *this;
- clear();
- for (f_heap_node* p = H.first_item(); p; p = H.next_item(p))
- insert(p->key,p->inf); // calls correct virtual functions
-
- }
-
-
-
- int f_heap::max_rank() const
- { // max_rank <= 1.4404 * log_2(node_count)
- register int x = 0;
- register int n = node_count;
- while (n) { x++;
- n >>= 1;
- }
- return int(1.5*x);
- }
-
- void f_heap::change_inf(f_heap_node* p, ent i)
- { clear_inf(p->inf);
- copy_inf(i);
- p->inf = i;
- }
-
-
- f_heap_node *f_heap::insert(ent k, ent info)
- { // Kreieren eines neuen heap ordered trees und Einfuegen
-
- copy_key(k);
- copy_inf(info);
-
- f_heap_node *neu = new_f_heap_node(k,info);
-
- if ( minptr == 0 )
- { minptr = neu;
- // zirkulaere Liste aufbauen
- neu->right = neu;
- neu->left = neu;
- }
- else
- // in zirkulaere Liste aufnehmen und minptr ueberpruefen
- { neu->left = minptr;
- neu->right = minptr->right;
- minptr->right->left = neu;
- minptr->right = neu;
- if ( cmp(k,minptr->key) < 0 ) minptr = neu;
- }
-
- node_count++;
-
- return ( neu );
-
- }
-
-
- void f_heap::decrease_key(f_heap_node *start, ent newkey)
- // neuer Distanzlabel fuer angegebenen Knoten
- { register f_heap_node* vater = start->parent;
- register f_heap_node* x = start;
-
- if (start->left == 0 || start->right == 0)
- error_handler(1,"f_heap decrease_key: item not in f_heap");
-
-
- int d = cmp(newkey,x->key);
-
- if ( d==0 && cmp(newkey,minptr->key) ) return;
-
- if ( d > 0 )
- { cout << "newkey = ";
- print_key(newkey);
- cout << " oldkey = ";
- print_key(x->key);
- cout << " minkey = ";
- print_key(minptr->key);
- cout << "\n";
- error_handler(1,"f_heap: key too large in decrease_key.");
-
- }
-
- copy_key(newkey);
- clear_key(x->key);
- x->key = newkey;
-
- if ( vater && cmp(newkey,vater->key) <= 0 )
- { // streiche Kante ( x, Vater(x) )
- x->cut(minptr);
-
- // errege(Vater(x))
- x = vater;
- while ( x->mark && x->parent )
- { vater = x->parent;
- x->cut(minptr);
- x = vater;
- }
- x->mark = 1;
- }
-
- // minptr testen
- if ( cmp(newkey,minptr->key) <= 0 ) minptr = start; // "<=" by s.n.
-
-
- } // end of decrease_key()
-
- void f_heap::del_min()
- // Knoten mit minimalem Distanzlabel wird geloescht
- { f_heap_node *ring1, *ring2, *lauf, *help;
-
- f_heap_node* erg = minptr;
-
- // leerer F-Heap ?
- if ( minptr == 0 ) return;
-
- if ( node_count > 0 ) node_count--;
-
- // letzter Knoten im F-Heap ?
- if ( node_count==0 )
- { minptr = 0;
- clear_key(erg->key);
- clear_inf(erg->inf);
- erg->deleted = 1;
- return;
- }
-
- // ring1 und ring2 zum Verschmelzen der Listen
- ring1 = minptr->right;
- ring2 = minptr->children;
-
- if ( ring2 )
- { // Elternbeziehung von ring2 loeschen
- while ( ring2->parent )
- { ring2->parent = 0;
- ring2 = ring2->right;
- }
-
- // Verschmelzen (altes Minimum bleibt zunaechst drin!)
- ring2->left->right = ring1;
- ring1->left->right = ring2;
- help = ring1->left;
- ring1->left = ring2->left;
- ring2->left = help;
- }
-
-
- // Vereinigung der Heap geordneten Baeume
-
- int max = max_rank();
-
- for ( int i = 0 ; i <= max ; i++ ) rank_field[i] = 0;
-
- lauf = minptr->right;
- help = lauf;
-
- while (lauf != minptr) // altes Minimum dient als Stopper
- { register f_heap_node* r = lauf;
- register f_heap_node* r1;
- register int rank = r->rank;
-
- lauf = lauf->right;
-
- while (r1=rank_field[rank])
- { rank_field[rank] = 0;
- if (cmp(r->key,r1->key) <= 0) r->link(r1);
- else { r1->link(r);
- r = r1;
- }
- rank++;
- }
- rank_field[rank] = r;
-
- if ( cmp(r->key,help->key) <= 0 ) help = r; // neues Minimum
-
- }
-
- // altesMinimum loeschen
- minptr->left->right = minptr->right;
- minptr->right->left = minptr->left;
-
- // minptr neu setzen
- minptr = help;
-
- clear_key(erg->key);
- clear_inf(erg->inf);
-
- erg->deleted = 1;
-
- } // end of del_min()
-
-
- void f_heap::clear()
- { f_heap_node* tail = node_list;
-
- if (tail==0) return;
-
- for(;;)
- { if (tail->deleted == 0)
- { clear_key(tail->key);
- clear_inf(tail->inf);
- }
- if (tail->next) tail = tail->next;
- else break;
- }
-
- deallocate_list(node_list,tail,10);
-
- node_count = 0;
- minptr = 0;
- node_list = 0;
- }
-
-