// NON-standard version of Dijkstra's: // Print out the shortest paths from the source node to each other node void dijkstras(graph_t *g, int source) { int i; int u, v; double weight; // generous vars for edge (u->v,weight) double new_weight; // To store current min-costs and previous vertices int *prev; // prev[v]=u if v was reached from u double *dist; // dist[v]= current best dist from source to v assert(prev= malloc( g->n * sizeof(*prev) ) ); assert(dist= malloc( g->n * sizeof(*dist) ) ); /* Initialization ------------------------------ */ for (i = 0; i < g->n; i++) { prev[i] = NO_PREV; dist[i] = INFINITY; } dist[source] = 0; // enqueue "source" - the only one that has limitted dist pq_t *queue = new_pq(); pq_enqueue(queue, source, dist[source]); /* Main loop of Dijkstra's ------------------------------ */ // buddy array of n elements to store the adjacency list of a vertex data_t *neighbours; int n; assert(neighbours= malloc( g->n * sizeof(*neighbours) ) ); while (!pq_is_empty(queue)) { // remove min vertex u = pq_remove_min(queue); // With this vertex u: // * first, copies the adjacency list of u to array neighbours n= list_2_array(g->vs[u].A, neighbours); // * then, inspects each of the neighbour for (i = 0; i < n; i++) { v = neighbours[i].id; // looking at edge (u-->v,weight) weight = neighbours[i].weight; new_weight = dist[u] + weight; // if v was reached before with a better outcome // then we just ignore the edge u-->v if ( dist[v] <= new_weight) continue; // updates vertex v in the queue if (dist[v] == INFINITY) { // if v never been reached before, adds it to queue pq_enqueue(queue, v, new_weight); } else { // otherwise, updates weight of v in the queue // note that the update must be successful if ( !pq_update(queue, v, new_weight) ){ fprintf(stderr, "Internal error: Something wrong " "in code or in data (such as negative weight)\n"); exit(EXIT_FAILURE); } } // now updaes dist[v] and prev[v] dist[v] = new_weight; prev[v] = u; } } /* Prints out all shortest paths ------------------------------ */ print_all_path(dist, prev, g, source); // free the dynamic data structures free(dist); free(prev); free(neighbours); free_pq(queue); }
// The "standard" version of Dijkstra's, // ie the one that is the same as shown in the lecture // see page 16 of lec08.pdf // Comments starting with //* are the lines from pseudocode in page 16 // Print out the shortest paths from the source node to each other node void dijkstras(graph_t *g, int v0) { int v; int u, w; double weight; // generous vars for edge (u->w,weight) // To store current min-costs and previous vertices int *prev; // prev[v]=u if v was reached from u double *dist; // dist[v]= current best dist from source to v bool *inQ; // a helping array for quick check if v in Q assert(prev= malloc( g->n * sizeof(*prev) ) ); assert(dist= malloc( g->n * sizeof(*dist) ) ); assert(inQ= malloc( g->n * sizeof(*inQ) ) ); /* Initialization ------------------------------ */ for (v = 0; v < g->n; v++) { //* foreach v in V prev[v] = NO_PREV; //* prev[v]= nil dist[v] = INFINITY; //* dist[v]= infinity } dist[v0] = 0; //* dist[v0]=0 //* Q = InitPriorityQueue(V) pq_t *Q = new_pq(); for (v = 0; v < g->n; v++) { pq_enqueue(Q, v, dist[v]); inQ[v]= true; // marks v as being inside the queue } /* Main loop of Dijkstra's ------------------------------ */ // buddy array of n elements to store the adjacency list of a vertex data_t *neighbours; int n; assert(neighbours= malloc( g->n * sizeof(*neighbours) ) ); while (!pq_is_empty(Q)) { //* while Q is non empty do // remove min vertex u = pq_remove_min(Q); //* u= EjectMin(Q) inQ[u]= false; // marks u as not in Q anymore // With this vertex u: // first, copies the adjacency list of u to array neighbours n= list_2_array(g->vs[u].A, neighbours); for (v = 0; v < n; v++) { //* for each (u,w) in E do w = neighbours[v].id; // having:edge (u-->w,weight) weight= neighbours[v].weight; //* if (w in Q && dist[v]+weight(u,w) <dist[v] if ( inQ[w] && dist[w] > dist[u]+weight) { dist[w] = dist[u]+weight; //* dist[w]= dist[u]+weight(u,v) prev[w] = u; //* prev[w]= u //* Update(Q, w, dist[w]) pq_update(Q, w, dist[w]); } } } /* Prints out all shortest paths ------------------------------ */ print_all_path(dist, prev, g, v0); // free the dynamic data structures free(dist); free(prev); free(neighbours); free_pq(Q); }
/** * Repeatedly merge the closest pair of the given markers until they don't overlap. * * The centroid rule is used for merging. I.e. each marker's area represents * a population of points. Merging two markers removes the originals and creates a * new marker with area the sum of the originals and center at the average position * of the two merged populations. * * The markers array must include extra buffer space. If there are n markers, the * array must have 2n-1 spaces, with only the first n initialized. * * The number of markers after merging is returned. Zero or more of these will be * marked deleted_p and should be ignored. * * This algorithm is O(n k log n), where k is the maximum number of simultaneously * overlapping markers in the original, unmerged set. */ int merge_markers_fast(MARKER_INFO *info, MARKER *markers, int n_markers) { int augmented_length = 2 * n_markers - 1; NewArrayDecl(int, n_nghbr, augmented_length); NewArrayDecl(MARKER_DISTANCE, mindist, augmented_length); NewArrayDecl(int, inv_nghbr_head, augmented_length); NewArrayDecl(int, inv_nghbr_next, augmented_length); NewArrayDecl(int, tmp, augmented_length); // Too big // Do not free the following array! It's owned by the priority queue. NewArrayDecl(int, heap, augmented_length); // Too big // Specialized quadtree supports finding closest marker to any given one. QUADTREE_DECL(qt); // Priority queue keyed on distances of overlapping pairs of markers. PRIORITY_QUEUE_DECL(pq); /// Extent of markers in the domain. MARKER_EXTENT ext[1]; // Get a bounding box for the whole collection of markers. get_marker_array_extent(markers, n_markers, ext); // Set up the quadtree with the bounding box. Choose tree depth heuristically. int max_depth = high_bit_position(n_markers) / 4 + 3; qt_setup(qt, max_depth, ext->x, ext->y, ext->w, ext->h, info); // Insert all the markers in the quadtree. for (int i = 0; i < n_markers; i++) qt_insert(qt, markers + i); // Set all the inverse nearest neighbor links to null. for (int i = 0; i < augmented_length; i++) inv_nghbr_head[i] = inv_nghbr_next[i] = -1; // Initialize the heap by adding an index for each overlapping pair. The // The heap holds indices into the array of min-distance keys. An index for // pair a->bis added iff markers with indices a and b overlap and b < a. int heap_size = 0; for (int a = 0; a < n_markers; a++) { int b = qt_nearest_wrt(markers, qt, a); if (0 <= b && b < a) { n_nghbr[a] = b; mindist[a] = mr_distance(info, markers + a, markers + b); heap[heap_size++] = a; // Here we are building a linked list of markers that have b as nearest. inv_nghbr_next[a] = inv_nghbr_head[b]; inv_nghbr_head[b] = a; } } // Now install the raw heap array into the priority queue. After this it's owned by the queue. pq_set_up_heap(pq, heap, heap_size, mindist, augmented_length); // Too big while (!pq_empty_p(pq)) { // Get nearest pair from priority queue. int a = pq_get_min(pq); int b = n_nghbr[a]; // Delete both of the nearest pair from all data structures. pq_delete(pq, b); qt_delete(qt, markers + a); qt_delete(qt, markers + b); mr_set_deleted(markers + a); mr_set_deleted(markers + b); // Capture the inv lists of both a and b in tmp. int tmp_size = 0; for (int p = inv_nghbr_head[a]; p >= 0; p = inv_nghbr_next[p]) if (!markers[p].deleted_p) tmp[tmp_size++] = p; for (int p = inv_nghbr_head[b]; p >= 0; p = inv_nghbr_next[p]) if (!markers[p].deleted_p) tmp[tmp_size++] = p; // Create a new merged marker. Adding it after all others means // nothing already in the heap could have it as nearest. int aa = n_markers++; mr_merge(info, markers, aa, a, b); // Add to quadtree. qt_insert(qt, markers + aa); // Find nearest overlapping neighbor of the merged marker, if any. int bb = qt_nearest_wrt(markers, qt, aa); if (0 <= bb) { n_nghbr[aa] = bb; mindist[aa] = mr_distance(info, markers + aa, markers + bb); pq_add(pq, aa); inv_nghbr_next[aa] = inv_nghbr_head[bb]; inv_nghbr_head[bb] = aa; } // Reset the nearest neighbors of the inverse neighbors of the deletions. for (int i = 0; i < tmp_size; i++) { int aa = tmp[i]; int bb = qt_nearest_wrt(markers, qt, aa); if (0 <= bb && bb < aa) { n_nghbr[aa] = bb; mindist[aa] = mr_distance(info, markers + aa, markers + bb); pq_update(pq, aa); inv_nghbr_next[aa] = inv_nghbr_head[bb]; inv_nghbr_head[bb] = aa; } else { pq_delete(pq, aa); } } } qt_clear(qt); pq_clear(pq); Free(n_nghbr); Free(mindist); Free(inv_nghbr_head); Free(inv_nghbr_next); Free(tmp); return n_markers; }