Porting of splib's dikh version (PQ as a heap) Graph is: /// /// Usata nella lista di adiacenti del grafo /// public struct Adj { public int id; // id dell'altro estremo public double d; // distanza (o costo) dell'arco public decimal arcid; // id dell'arco che congiunge } /// /// Un elemento del grafo stradale. Ogni nodo ha gli archi uscenti negli adiacenti /// public class Nodo { public int id; public double X; public double Y; public List adiacenti; public Nodo() { this.id= int.MinValue; this.X = 0.0; this.Y = 0.0; adiacenti = new List(); } public Nodo(int id, double x, double y) { this.id= id; this.X = x; this.Y = y; adiacenti = new List(); } } Then, Dijkstra is: public class Dijkstra_heap { public struct node { public double dist; // tentative shortest path length public int parent; // pointer to parent public int heap_pos; // number of position in heap } public node[] nodes; // questi sono i nodi di dijkstra, interni public Nodo[] grafo; // questo e' il grafo, come collection di nodi (!) #region definitions for heap struct heap { public int size; // the number of the last heap element public int[] nd; // heap of the pointers to nodes } heap d_heap; int h_current_pos, h_new_pos, h_pos, h_last_pos, h_degree; int node_j, node_k; double dist_k, dist_min; int HEAP_POWER = 2; int NILL = -1; bool NODE_IN_HEAP(int node_i ) { return(nodes[node_i].heap_pos != NILL); } bool NONEMPTY_HEAP() { return(d_heap.size > 0); } void PUT_TO_POS_IN_HEAP(int node_i, int pos ) { d_heap.nd[pos] = node_i; nodes[node_i].heap_pos = pos; } void Init_heap (int n, int source) { h_degree = 1 << HEAP_POWER; d_heap.size = 1; d_heap.nd = new int[n+1]; PUT_TO_POS_IN_HEAP( source, 0 ); } void Heap_decrease_key (int node_i, double dist_i) { for ( h_current_pos = nodes[node_i].heap_pos; h_current_pos > 0; h_current_pos = h_new_pos ) { h_new_pos = ( h_current_pos - 1 ) >> HEAP_POWER; node_j = d_heap.nd[h_new_pos]; if ( dist_i >= nodes[node_j].dist ) break; PUT_TO_POS_IN_HEAP ( node_j, h_current_pos ); } PUT_TO_POS_IN_HEAP ( node_i, h_current_pos ); } void Insert_to_heap (int node_i) { PUT_TO_POS_IN_HEAP ( node_i, d_heap.size ); d_heap.size++; Heap_decrease_key( node_i, nodes[node_i].dist); } int Extract_min () { int node_0; node_0 = d_heap.nd[0]; nodes[node_0].heap_pos = NILL; d_heap.size-- ; if ( d_heap.size > 0 ) { node_k = d_heap.nd [ d_heap.size ]; dist_k = nodes[node_k].dist; h_current_pos = 0; while ( true ) { h_new_pos = ( h_current_pos << HEAP_POWER ) + 1; if ( h_new_pos >= d_heap.size ) break; dist_min = nodes[d_heap.nd[h_new_pos]].dist; h_last_pos = h_new_pos + h_degree; if ( h_last_pos > d_heap.size ) h_last_pos = d_heap.size; for ( h_pos = h_new_pos + 1; h_pos < h_last_pos; h_pos ++ ) { if ( nodes[d_heap.nd[h_pos]].dist < dist_min ) { h_new_pos = h_pos; dist_min = nodes[d_heap.nd[h_pos]].dist; } } if ( dist_k <= dist_min ) break; PUT_TO_POS_IN_HEAP ( d_heap.nd[h_new_pos], h_current_pos ); h_current_pos = h_new_pos; } // end while PUT_TO_POS_IN_HEAP ( node_k, h_current_pos ); } // end if return(node_0); } #endregion /// /// Algoritmo di Dijkstra, PQ come heap, calcola tutto l'albero dei predecessori /// /// Sorgente public void dikh (int source) { double dist_new, dist_from; int n,node_from, node_to, node_last, i, arc_ij; int num_scans = 0; // initialization node_last = n = grafo.Length; nodes = new node[n]; for ( i = 0; i != node_last; i ++ ) { nodes[i].parent = -1; nodes[i].dist = Int32.MaxValue; nodes[i].heap_pos = NILL; } nodes[source].parent = source; nodes[source].dist = 0; Init_heap (n, source); while ( NONEMPTY_HEAP() ) { node_from = Extract_min(); dist_from = nodes[node_from].dist; num_scans ++; //for (arc_ij = index[node_from]; arc_ij < index[node_from+1]; arc_ij++) for (arc_ij = 0; arc_ij < grafo[node_from].adiacenti.Count; arc_ij++) { node_to = grafo[node_from].adiacenti[arc_ij].id; dist_new = dist_from + grafo[node_from].adiacenti[arc_ij].d; if ( dist_new < nodes[node_to].dist) { nodes[node_to].dist = dist_new; nodes[node_to].parent = node_from; if ( !NODE_IN_HEAP(node_to) ) Insert_to_heap ( node_to ); Heap_decrease_key ( node_to, dist_new ); } } } } // end dikh /// /// Algoritmo di Dijkstra, PQ come heap, calcola un percorso da un nodo ad un altro /// /// id nodo origine (pos in grafo) /// id nodo destinazione (pos in grafo) /// distanza fra orgine e dest. public double dikh (int source, int dest) { double dist_new, dist_from, dist=double.MaxValue; int n,node_from, node_to, node_last, i, arc_ij; int num_scans = 0; // initialization node_last = n = grafo.Length; nodes = new node[n]; for ( i = 0; i != node_last; i ++ ) { nodes[i].parent = -1; nodes[i].dist = Int32.MaxValue; nodes[i].heap_pos = NILL; } nodes[source].parent = source; nodes[source].dist = 0; Init_heap (n, source); while ( NONEMPTY_HEAP() ) { node_from = Extract_min(); if(node_from == dest) { dist = nodes[node_from].dist; goto end; } dist_from = nodes[node_from].dist; num_scans ++; //for (arc_ij = index[node_from]; arc_ij < index[node_from+1]; arc_ij++) for (arc_ij = 0; arc_ij < grafo[node_from].adiacenti.Count; arc_ij++) { node_to = grafo[node_from].adiacenti[arc_ij].id; dist_new = dist_from + grafo[node_from].adiacenti[arc_ij].d; if ( dist_new < nodes[node_to].dist) { nodes[node_to].dist = dist_new; nodes[node_to].parent = node_from; if ( !NODE_IN_HEAP(node_to) ) Insert_to_heap ( node_to ); Heap_decrease_key ( node_to, dist_new ); } } } end: return(dist); } // end dikh }