All pastes #2083266 Raw Edit

Unnamed

public text v1 · immutable
#2083266 ·published 2011-09-27 14:50 UTC
rendered paste body
/**
  \file shortestpath.c
  	\author Lucia Del Colombo
  Si dichiara che il contenuto di questo file e' in ogni sua parte opera
     originale dell' autore. 
   
   \brief Implementazione delle funzioni ausiliarie i cui prototipi si trovano nel file dgraph_aux.h */

#include <stdlib.h>
#include <string.h>
#include <float.h>
#include "shortestpath.h"
#include "graph_err.h"
#include "dgraph_aux.h"

/**
set: insieme dei nodi usati per calcolare i cammini minimi:
		se set[i] == 0 il nodo i non è stato ancora aggiunto all'insieme
		se set[i] == 1 il nodo è stato aggiunto all'insieme

*/
double *dijkstra(graph_t * g, unsigned int source, unsigned int **pprec)
{
    int *node_set, i, j, k, node_to_add;
    double *dist, dist_temp, dist_temp2, dist_w;
    edge_t *etemp;
    unsigned int *myprec = NULL;

/** Gestione errore */
    if (g == NULL || source > g->size) {
	errno = EINVAL;
	return NULL;
    }

/** Allocazione set di nodi, vettore delle distanze da restituire ed eventualmente del vettore pprec */
    ec_nullNULL_c((node_set =
		   (int *) calloc(g->size, sizeof(int))), errno = ENOMEM);
    ec_nullNULL_c((dist =
		   (double *) calloc(g->size, sizeof(double))), errno =
		  ENOMEM);
    if (pprec != NULL) {
	ec_nullNULL_c((myprec =
		       (unsigned int *) calloc(g->size,
					       sizeof(unsigned int))),
		      errno = ENOMEM);
    }

/** Inizializzazione: le distanze e l'insieme set di nodi usati per calcolare i costi minimi sono inizializzati a 0 */
    for (i = 0; i < g->size; i++) {
	if (i == source) {
	    node_set[i] = 1;
	    dist[i] = 0;
	} else {
	    node_set[i] = 0;
	    dist[i] = INFINITY;
	}
	if (pprec != NULL)
	    myprec[i] = UNDEF;
    }
/** Inizializzazione distanze dai nodi adiacenti all sorgente */
    for (etemp = g->node[source].adj; etemp != NULL; etemp = etemp->next) {
	dist[etemp->label] = etemp->km;
	if (pprec != NULL)
	    myprec[etemp->label] = source;
    }

/** Ciclo: inserisco tutti i nodi nell'insieme di quelli usati per calcolare i cammini minimi */
    for (i = 0; i < g->size; i++) {
	node_to_add = 0;
	dist_w = INFINITY;

/** Trovo il nodo non in set la cui distanza da w è minima */
	for (j = 0; j < g->size; j++) {
	    if (!node_set[j]
		&& ((dist_w == INFINITY && dist[j] != INFINITY)
		    || (dist_w != INFINITY && dist[j] != INFINITY
			&& dist[j] < dist_w))) {
		node_to_add = j;
		dist_w = dist[j];
	    }
	}
	node_set[node_to_add] = 1;

/** Trovo il costo minimo usando il nuovo nodo node_to_add */
	for (k = 0; k < g->size; k++) {
	    if ((dist_temp2 = trova_costo(g, node_to_add, k)) < 0)
		dist_temp = INFINITY;
	    else {
		dist_temp = dist_w + dist_temp2;

		if (!node_set[k]
		    && (dist[k] == INFINITY || dist_temp < dist[k])) {
		    dist[k] = dist_temp;
		    if (pprec != NULL && k != source)
			myprec[k] = node_to_add;
		}
	    }
	}

    }
    free(node_set);
    if (pprec != NULL)
	*pprec = myprec;
    return dist;
}


char *shpath_to_string(graph_t * g, unsigned int n1, unsigned int n2,
		       unsigned int *prec)
{
    char *route;
    int *vtemp, k, lroute, i = 0;

/** se non si è verificato un errore ma la rotta non esiste errno deve valere 0 */
    errno = 0;
    if (prec == NULL) {
	errno = EINVAL;
	return NULL;
    }

/** Gestione errore */
    if (g == NULL || n1 < 0 || n1 > g->size || n2 < 0 || n2 > g->size) {
	errno = EINVAL;
	return NULL;
    }

    if (prec[n2] == UNDEF) {
	errno = EINVAL;
	return NULL;
    }


/** Allocazione stringa */
    ec_nullNULL_c((vtemp =
		   (int *) calloc(g->size, sizeof(int))), errno = ENOMEM);
    k = prec[n2];
    lroute = strlen(g->node[n1].label) + 1;
    while (k != n1) {
	vtemp[i] = k;
	lroute += strlen(g->node[k].label) + 1;
	k = prec[k];
	i++;
    }
    lroute += strlen(g->node[n2].label) + 2;
    ec_nullNULL_c((route = (char *) malloc(lroute + 2)), errno = ENOMEM);
    route[0] = '\0';
    strcat(route, g->node[n1].label);
    while (i-- != 0) {
	strcat(strcat(route, "$"), g->node[vtemp[i]].label);
    }
    strcat(strcat(route, "$"), g->node[n2].label);
    free(vtemp);

    return route;

}