Ejemplo n.º 1
0
void
pq_delete_min(PQ pq, void *retval)
{
    int floater;        /* previous loser floating down */
    int small_child;    /* smaller child of floater */

    assert(!pq_is_empty(pq));

    /* first copy out the winner */
    memcpy(retval, REF(pq, 0), pq->element_length);

    --(pq->n);

    if(pq_is_empty(pq)) {
        /* pq empty, nothing to do */
        return;
    }

    /* else */
    memcpy(REF(pq, 0), REF(pq, pq->n), pq->element_length);

    floater = 0;

    for(;;) {
        /* find smaller child of floater */
        if(Child(floater, 0) >= pq->n) {
            return;     /* no children, bail out */
        } else if(Child(floater, 1) >= pq->n) {
            small_child = Child(floater, 0);
        } else if(pq->compare(REF(pq, Child(floater, 0)), REF(pq, Child(floater, 1))) < 0) {
            small_child = Child(floater, 0);
        } else {
            small_child = Child(floater, 1);
        }

        /* is floater <= small_child? */
        if(pq->compare(REF(pq, floater), REF(pq, small_child)) <= 0) {
            /* yes, we are done */
            return;
        } else {
            /* no, swap and continue floating down */
            pq_swap(pq, floater, small_child);
            floater = small_child;
        }
    }
}
Ejemplo n.º 2
0
PCB* pq_dequeue(process_queue* pq) {
  if (pq_is_empty(pq)) return NULL;
  PCB* ret = NULL;
  ret = pq->head;
  ret->p_next = NULL;
  pq->head = (pq->head)->p_next;
  if (pq->head == NULL)
    pq->tail = NULL;
  return ret;
}
Ejemplo n.º 3
0
void pq_enqueue(PCB* next, process_queue* pq) {
  assert(pq != NULL && next != NULL);
  next->p_next = NULL;
  if (pq_is_empty(pq)) {
    pq->head = next;
    pq->tail = pq->head;
  } else {
    (pq->tail)->p_next = next;
    pq->tail = next;
  }
}
Ejemplo n.º 4
0
void dijkstra(graph_t *graph, int source, int *dist, int *parent)
{
    push_data_t data;
    pq_elem_t e;
    int n, i;

    if (!dist) return;

    data.dist = dist;
    data.pq = pq_create(sizeof(pq_elem_t), pq_elem_compare);
    if (!data.pq) return;

    n = graph_vertex_count(graph);

    for (i=0; i<n; i++)
        dist[i] = INT_MAX;

    if (parent) {
        for (i=0; i<n; i++) {
            parent[i] = DIJKSTRA_NULL_PARENT;
        }
    }

    push(graph, source, source, -INT_MAX, &data);

    while(! pq_is_empty(data.pq)) {
        pq_delete_min(data.pq, &e);
        printf("%d -> %d: %d\n", e.source, e.sink, e.distance);

        if (dist[e.sink] == INT_MAX) {
            /* new edge */
            dist[e.sink] = e.distance;
            if (parent)
                parent[e.sink] = e.source;

            graph_foreach_weighted(graph, e.sink, push, &data);
        }
    }

    pq_destroy(data.pq);
}
Ejemplo n.º 5
0
/*************************************************************
 * Support Functionality
 *************************************************************/
static int compute_shortest_path_dijkstra(netloc_data_collection_handle_t *handle,
                                          netloc_node_t *src_node,
                                          netloc_node_t *dest_node,
                                          int *num_edges,
                                          netloc_edge_t ***edges)
{
    int exit_status = NETLOC_SUCCESS;
    int i;
    pq_queue_t *queue = NULL;
    int *distance = NULL;
    bool *not_seen = NULL;
    netloc_node_t *node_u = NULL;
    netloc_node_t *node_v = NULL;
    netloc_node_t **prev_node = NULL;
    netloc_edge_t **prev_edge = NULL;
    int alt;
    int idx_u, idx_v;

    int num_rev_edges;
    netloc_edge_t **rev_edges = NULL;

    struct netloc_dt_lookup_table_iterator *hti = NULL;
    netloc_node_t *cur_node = NULL;

    unsigned long key_int;

    // Just in case things go poorly below
    (*num_edges) = 0;
    (*edges) = NULL;


    /*
     * Allocate some data structures
     */
    queue = pq_queue_t_construct();
    if( NULL == queue ) {
        fprintf(stderr, "Error: Failed to allocate the queue\n");
        exit_status = NETLOC_ERROR;
        goto cleanup;
    }

    distance = (int*)malloc(sizeof(int) * netloc_lookup_table_size(handle->node_list));
    if( NULL == distance ) {
        fprintf(stderr, "Error: Failed to allocate the distance array\n");
        exit_status = NETLOC_ERROR;
        goto cleanup;
    }

    not_seen = (bool*)malloc(sizeof(bool) * netloc_lookup_table_size(handle->node_list));
    if( NULL == not_seen ) {
        fprintf(stderr, "Error: Failed to allocate the 'not_seen' array\n");
        exit_status = NETLOC_ERROR;
        goto cleanup;
    }

    prev_node = (netloc_node_t**)malloc(sizeof(netloc_node_t*) * netloc_lookup_table_size(handle->node_list));
    if( NULL == prev_node ) {
        fprintf(stderr, "Error: Failed to allocate the 'prev_node' array\n");
        exit_status = NETLOC_ERROR;
        goto cleanup;
    }

    prev_edge = (netloc_edge_t**)malloc(sizeof(netloc_edge_t*) * netloc_lookup_table_size(handle->node_list));
    if( NULL == prev_edge ) {
        fprintf(stderr, "Error: Failed to allocate the 'prev_edge' array\n");
        exit_status = NETLOC_ERROR;
        goto cleanup;
    }

    /*
     * Initialize the data structures
     */
    // Make sure to initialize the arrays
    for( i = 0; i < netloc_lookup_table_size(handle->node_list); ++i){
        distance[i] = INT_MAX;
        not_seen[i] = true;
        prev_node[i] = NULL;
        prev_edge[i] = NULL;
    }

    i = 0;
    hti = netloc_dt_lookup_table_iterator_t_construct(handle->node_list);
    while( !netloc_lookup_table_iterator_at_end(hti) ) {
        cur_node = (netloc_node_t*)netloc_lookup_table_iterator_next_entry(hti);
        if( NULL == cur_node ) {
            break;
        }

        if( cur_node == src_node ) {
            pq_push(queue, 0, cur_node);
            distance[i] = 0;
        } else {
            pq_push(queue, INT_MAX, cur_node);
            distance[i] = INT_MAX;
        }

        not_seen[i] = true;

        prev_node[i] = NULL;
        prev_edge[i] = NULL;

        cur_node->__uid__ = i;
        ++i;
    }

    /*
     * Search
     */
    while( !pq_is_empty(queue) ) {
        //pq_dump(queue);

        // Grab the next hop
        node_u = pq_pop(queue);
        // Mark as seen
        idx_u = -1;
        i = 0;
        idx_u = node_u->__uid__;
        not_seen[idx_u] = false;

        // For all the edges from this node
        for(i = 0; i < node_u->num_edges; ++i ) {
            node_v = NULL;
            idx_v  = -1;

            // Lookup the "dest" node
            node_v = node_u->edges[i]->dest_node;
            idx_v = node_v->__uid__;

            // If the node has been seen, skip
            if( !not_seen[idx_v] ) {
                continue;
            }

            // Otherwise check to see if we found a shorter path
            // Future Work: Add a weight factor other than 1.
            //              Maybe calculated based on speed/width
            alt = distance[idx_u] + 1;
            if( alt < distance[idx_v] ) {
                distance[idx_v] = alt;
                prev_node[idx_v] = node_u;
                prev_edge[idx_v] = node_u->edges[i];

                // Adjust the priority queue as needed
                pq_reorder(queue, alt, node_v);
            }
        }
    }

    /*
     * Reconstruct the path by picking up the edges
     * The edges will be in reverse order (dest to source).
     */
    num_rev_edges = 0;
    rev_edges     = NULL;

    // Find last hop
    SUPPORT_CONVERT_ADDR_TO_INT(dest_node->physical_id,
                                handle->network->network_type,
                                key_int);
    node_u  = netloc_lookup_table_access_with_int( handle->node_list,
                                                   dest_node->physical_id,
                                                   key_int);
    idx_u = node_u->__uid__;

    node_v = NULL;
    idx_v  = -1;
    while( prev_node[idx_u] != NULL ) {
        // Find the linking edge
        if( node_u != dest_node) {
            for(i = 0; i < node_u->num_edges; ++i ) {
                if( node_v->physical_id_int == node_u->edges[i]->dest_node->physical_id_int ) {
                    ++num_rev_edges;
                    rev_edges = (netloc_edge_t**)realloc(rev_edges, sizeof(netloc_edge_t*) * num_rev_edges);
                    if( NULL == rev_edges ) {
                        fprintf(stderr, "Error: Failed to re-allocate the 'rev_edges' array with %d elements\n",
                                num_rev_edges);
                        exit_status = NETLOC_ERROR;
                        goto cleanup;
                    }
                    rev_edges[num_rev_edges-1] = node_u->edges[i];
                    break;
                }
            }
        }
        node_v = node_u;
        idx_v  = idx_u;

        // Find the next node
        SUPPORT_CONVERT_ADDR_TO_INT(prev_node[idx_u]->physical_id,
                                    handle->network->network_type,
                                    key_int);
        node_u = netloc_lookup_table_access_with_int( handle->node_list,
                                                      prev_node[idx_u]->physical_id,
                                                      key_int);
        idx_u = node_u->__uid__;
    }

    for(i = 0; i < src_node->num_edges; ++i ) {
        if( NULL == node_v ) {
            fprintf(stderr, "Error: This should never happen, but node_v is NULL at line %d in file %s\n",
                    __LINE__, __FILE__);
            exit_status = NETLOC_ERROR;
            goto cleanup;
        }
        if( node_v->physical_id_int == src_node->edges[i]->dest_node->physical_id_int ) {
            ++num_rev_edges;
            rev_edges = (netloc_edge_t**)realloc(rev_edges, sizeof(netloc_edge_t*) * num_rev_edges);
            if( NULL == rev_edges ) {
                fprintf(stderr, "Error: Failed to re-allocate the 'rev_edges' array with %d elements\n",
                        num_rev_edges);
                exit_status = NETLOC_ERROR;
                goto cleanup;
            }
            rev_edges[num_rev_edges-1] = node_u->edges[i];

            break;
        }
    }


    /*
     * Copy the edges back in correct order
     */
    (*num_edges) = num_rev_edges;
    (*edges) = (netloc_edge_t**)malloc(sizeof(netloc_edge_t*) * (*num_edges));
    if( NULL == (*edges) ) {
        fprintf(stderr, "Error: Failed to allocate the edges array\n");
        exit_status = NETLOC_ERROR;
        goto cleanup;
    }

    for( i = 0; i < num_rev_edges; ++i ) {
        (*edges)[i] = rev_edges[num_rev_edges-1-i];
        //printf("DEBUG: \t Edge: %s\n", netloc_pretty_print_edge_t( (*edges)[i] ) );
    }


    /*
     * Cleanup
     */
 cleanup:
    if( NULL != queue ) {
        pq_queue_t_destruct(queue);
        queue = NULL;
    }

    if( NULL != rev_edges ) {
        free(rev_edges);
        rev_edges = NULL;
    }

    if( NULL != distance ) {
        free(distance);
        distance = NULL;
    }

    if( NULL != not_seen ) {
        free(not_seen);
        not_seen = NULL;
    }

    if( NULL != prev_node ) {
        free(prev_node);
        prev_node = NULL;
    }

    if( NULL != prev_edge ) {
        free(prev_edge);
        prev_edge = NULL;
    }

    netloc_dt_lookup_table_iterator_t_destruct(hti);

    return exit_status;
}
Ejemplo n.º 6
0
Archivo: graph.c Proyecto: 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);	
}
Ejemplo n.º 7
0
Archivo: graph.c Proyecto: 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);	
}