/* Problem 8--DOT This is a straightforward application of Dijkstra's algorithm. There was a certain amount of tediousness, however, in reading the input in the proper format. */ #include #include #include typedef char CT[18]; typedef struct ELT { /* How far apart a given city is from another */ int node, len; struct ELT *next; } ELT; typedef struct ELN { /* Each city has an adjacency list */ int back, plen, inf, coll; /* Each node contains a back pointer to the previous node in the path, a path length from the starting node, flags indicating whether the path length is infinite and whether it has already been added to the collection. */ ELT *head; /* The head of the linked list of adjacent nodes. */ } ELN; FILE *in, *out; ELN *AdjList; int size; int main (int argc, char **argv); int CTcmp (const void *a, const void *b); int ReadCity (CT City); void FreeELT (ELT *p); void FreeList (void); void Dijkstra (int p1, int p2); int main (int argc, char **argv) { CT *Cities, City1, City2, temp; void *pos1, *pos2; int i, dist, p1, p2; ELT *entry; in = fopen ("prob8.in","r"); out = fopen ("prob8.out","w"); fscanf (in,"%d",&size); /* Get number of cities. */ Cities = malloc (size*sizeof(CT)); AdjList = calloc (size,sizeof(ELN)); fgets(temp,18,in); /* Skip EOLN. */ for (i=0;inode = p2; /* for both cities. */ entry->len = dist; entry->next = AdjList[p1].head; AdjList[p1].head = entry; entry = malloc (sizeof (ELT)); entry->node = p1; entry->len = dist; entry->next = AdjList[p2].head; AdjList[p2].head = entry; } while (!ReadCity (City1)) { /* Read in cities to find detour */ ReadCity (City2); pos1 = bsearch (City1,Cities,size,sizeof(CT),CTcmp); p1 = (CT*)pos1-Cities; pos2 = bsearch (City2,Cities,size,sizeof(CT),CTcmp); p2 = (CT*)pos2-Cities; Dijkstra (p1,p2); /* Run Dijkstra's algorithm on these cities */ fprintf (out,"Detour from %s to %s\n",Cities[p2],Cities[p1]); for (i=p2;i != -1; i = AdjList[i].back) fprintf (out,"%s\n",Cities[i]); fprintf (out,"Total distance: %d miles\n\n",AdjList[p2].plen); } free (Cities); FreeList (); return EXIT_SUCCESS; } /* CTcmp is a standard string comparison function for sorting. */ int CTcmp (const void *a, const void *b) { return strcmp ((char *)a,(char *)b); } /* ReadCity reads in a city name from the keyboard. It returns 1 if EOF is reached, 0 otherwise. */ int ReadCity (CT City) { CT temp; int l,c; if (EOF==fscanf (in,"%s",temp)) return 1; if (temp[0]!='\"') { /* if it didn't begin with " */ strcpy (City,temp); return 0; } strcpy (City,&temp[1]); /* otherwise, keep reading until " is found. */ l = strlen (City); while ((c=fgetc(in)) != '\"') City[l++]=c; City[l]=0; return 0; } /* FreeELT frees up the memory stored by the adjacency list. */ void FreeELT (ELT *p) { if (p==NULL) return; FreeELT (p->next); free (p); } /* FreeList frees up the adjacency list data structure. */ void FreeList (void) { int i; for (i=0;i= minlen) continue; minlen = AdjList[i].plen; minnode = i; found = 1; } if (minnode==p2) break; /* If this nearest node is p2, we're done. */ AdjList[minnode].coll = 1; /* Otherwise, add it to the collection. */ for (P=AdjList[minnode].head;P!=NULL;P=P->next) { n = P->node; /* go through everything connecting to the minnode */ if (AdjList[n].coll) continue; /* Skip if already found */ if (minnode==p1 && n==p2) continue; /* Ignore the p1->p2 connection*/ if (AdjList[n].inf||AdjList[n].plen>AdjList[minnode].plen + P->len) { AdjList[n].inf = 0;/* If we found a shorter path, adjust the path*/ AdjList[n].plen = AdjList[minnode].plen + P->len; AdjList[n].back = minnode; /* length and set the back pointer */ } } } }