diff -r 9b078bc3ce13 -r abcbdcf36ab2 src/work/jacint/fib_heap.h --- a/src/work/jacint/fib_heap.h Wed Mar 10 17:49:55 2004 +0000 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,387 +0,0 @@ -// -*- C++ -*- -/* - *template > - * - *constructors: - * - *FibHeap(ItemIntMap), FibHeap(ItemIntMap, Compare) - * - *Member functions: - * - *int size() : returns the number of elements in the heap - * - *bool empty() : true iff size()=0 - * - *void set(Item, Prio) : calls push(Item, Prio) if Item is not - * in the heap, and calls decrease/increase(Item, Prio) otherwise - * - *void push(Item, Prio) : pushes Item to the heap with priority Prio. Item - * mustn't be in the heap. - * - *Item top() : returns the Item with least Prio - * - *Prio prio() : returns the least Prio - * - *Prio get(Item) : returns Prio of Item - * - *void pop() : deletes the Item with least Prio - * - *void erase(Item) : deletes Item from the heap if it was already there - * - *void decrease(Item, P) : decreases prio of Item to P. Item must be in the heap - * with prio at least P. - * - *void increase(Item, P) : sets prio of Item to P. - * - * - *In Fibonacci heaps, increase and erase are not efficient, in case of - *many calls to these operations, it is better to use bin_heap. - */ - -#ifndef FIB_HEAP_H -#define FIB_HEAP_H - -#include -#include -#include - -namespace hugo { - - template > - - class FibHeap { - - typedef Prio PrioType; - - class store; - - std::vector container; - int minimum; - bool blank; - ItemIntMap &iimap; - Compare comp; - - public : - - FibHeap(ItemIntMap &_iimap) : minimum(), blank(true), iimap(_iimap) {} - FibHeap(ItemIntMap &_iimap, const Compare &_comp) : minimum(), - blank(true), iimap(_iimap), comp(_comp) {} - - - int size() const { - int s=0; - for ( unsigned int i=0; i!=container.size(); ++i ) - if ( container[i].in ) ++s; - return s; - } - - - bool empty() const { return blank; } - - - void set (Item const it, PrioType const value) { - int i=iimap.get(it); - if ( i >= 0 && container[i].in ) { - if ( !comp(container[i].prio, value) ) decrease(it, value); - if ( comp(container[i].prio, value) ) increase(it, value); - } else push(it, value); - } - - - void push (Item const it, PrioType const value) { - int i=iimap.get(it); - if ( i < 0 ) { - int s=container.size(); - iimap.set( it, s ); - store st; - st.name=it; - container.push_back(st); - i=s; - } - - if ( !blank ) { - container[container[minimum].right_neighbor].left_neighbor=i; - container[i].right_neighbor=container[minimum].right_neighbor; - container[minimum].right_neighbor=i; - container[i].left_neighbor=minimum; - if ( !comp( container[minimum].prio, value) ) minimum=i; - - } else { - container[i].right_neighbor=container[i].left_neighbor=i; - minimum=i; - blank=false; - } - container[i].prio=value; - } - - - - Item top() const { - if ( !blank ) { - return container[minimum].name; - } else { - return Item(); - } - } - - - PrioType prio() const { - if ( !blank ) { - return container[minimum].prio; - } else { - return PrioType(); - } - } - - - const PrioType get(const Item& it) const - { - int i=iimap.get(it); - - if ( i >= 0 && container[i].in ) { - return container[i].prio; - } else { - return PrioType(); - } - } - - - void pop() { - if ( !blank ) { - - /*The first case is that there are only one root.*/ - if ( container[minimum].left_neighbor==minimum ) { - container[minimum].in=false; - if ( container[minimum].degree==0 ) blank=true; - else { - makeroot(container[minimum].child); - minimum=container[minimum].child; - balance(); - } - } else { - int right=container[minimum].right_neighbor; - unlace(minimum); - container[minimum].in=false; - if ( container[minimum].degree > 0 ) { - int left=container[minimum].left_neighbor; - int child=container[minimum].child; - int last_child=container[child].left_neighbor; - - container[left].right_neighbor=child; - container[child].left_neighbor=left; - container[right].left_neighbor=last_child; - container[last_child].right_neighbor=right; - - makeroot(child); - } - minimum=right; - balance(); - } // the case where there are more roots - } - } - - - void erase (const Item& it) { - int i=iimap.get(it); - - if ( i >= 0 && container[i].in ) { - - if ( container[i].parent!=-1 ) { - int p=container[i].parent; - cut(i,p); - cascade(p); - minimum=i; //As if its prio would be -infinity - } - pop(); - } - } - - - void decrease (Item it, PrioType const value) { - int i=iimap.get(it); - container[i].prio=value; - int p=container[i].parent; - - if ( p!=-1 && comp(value, container[p].prio) ) { - cut(i,p); - cascade(p); - if ( comp(value, container[minimum].prio) ) minimum=i; - } - } - - - void increase (Item it, PrioType const value) { - erase(it); - push(it, value); - } - - - private: - - void balance() { - int maxdeg=int( floor( 2.08*log(double(container.size()))))+1; - - std::vector A(maxdeg,-1); - - /* - *Recall that now minimum does not point to the minimum prio element. - *We set minimum to this during balance(). - */ - int anchor=container[minimum].left_neighbor; - int next=minimum; - bool end=false; - - do { - int active=next; - int d=container[active].degree; - if ( anchor==active ) end=true; - next = container[active].right_neighbor; - if ( !comp(container[minimum].prio, container[active].prio) ) - minimum=active; - - while (A[d]!=-1) { - - if( comp(container[active].prio, container[A[d]].prio) ) { - fuse(active,A[d]); - } else { - fuse(A[d],active); - active=A[d]; - } - A[d]=-1; - ++d; - } - - A[d]=active; - } while ( !end ); - } - - - - - /* - *All the siblings of a are made roots. - */ - void makeroot (int c) - { - int s=c; - do { - container[s].parent=-1; - s=container[s].right_neighbor; - } while ( s != c ); - } - - - void cut (int a, int b) - { - - /* - *Replacing a from the children of b. - */ - --container[b].degree; - - if ( container[b].degree !=0 ) { - int child=container[b].child; - if ( child==a ) - container[b].child=container[child].right_neighbor; - - unlace(a); - - } - - - /*Lacing i to the roots.*/ - int right=container[minimum].right_neighbor; - container[minimum].right_neighbor=a; - container[a].left_neighbor=minimum; - container[a].right_neighbor=right; - container[right].left_neighbor=a; - - container[a].parent=-1; - container[a].marked=false; - } - - - void cascade (int a) - { - if ( container[a].parent!=-1 ) { - int p=container[a].parent; - - if ( container[a].marked==false ) container[a].marked=true; - else { - cut(a,p); - cascade(p); - } - } - } - - - void fuse (int a, int b) - { - - unlace(b); - - - /*Lacing b under a.*/ - container[b].parent=a; - - if (container[a].degree==0) { - container[b].left_neighbor=b; - container[b].right_neighbor=b; - container[a].child=b; - } else { - int child=container[a].child; - int last_child=container[child].left_neighbor; - container[child].left_neighbor=b; - container[b].right_neighbor=child; - container[last_child].right_neighbor=b; - container[b].left_neighbor=last_child; - } - - ++container[a].degree; - - container[b].marked=false; - } - - - /* - *It is invoked only if a has siblings. - */ - - void unlace (int a) { - int leftn=container[a].left_neighbor; - int rightn=container[a].right_neighbor; - container[leftn].right_neighbor=rightn; - container[rightn].left_neighbor=leftn; - } - - - class store { - friend class FibHeap; - - Item name; - int parent; - int left_neighbor; - int right_neighbor; - int child; - int degree; - bool marked; - bool in; - PrioType prio; - - store() : parent(-1), child(-1), degree(), marked(false), in(true) {} - }; - - }; - -} //namespace hugo -#endif - - - - - -