Example #1
0
File: graph.c Project: anhvir/c207
// 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);	
}
Example #2
0
File: graph.c Project: anhvir/c207
// 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);	
}
Example #3
0
/**
 * 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;
}