用C语言写一段代码并且有注释,游客通过终端询问可知,要求:(1)将导游图看作一张带权无向图,顶点表示公园的各个景点,边表示各景点之间的道路,边上的权值表示距离,选择适当的数据结构。 (2)为游客提供图中任意景点相关信息的查询。 (3)为游客提供任意两个景点之间最短的简单路径。 (4)为游客选择最佳游览路径。(5)以邻接表为存储结构,利用Dijkstra算法或Floy算法求最短路径,利用搜索求最佳路径。
时间: 2024-02-05 08:14:10 浏览: 84
C语言寻找无向图两点间的最短路径
以下是基于邻接表的图的最短路径查询和最佳路径选择的C语言代码,包括注释:
```c
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define MAX_VERTICES 100 // 最大顶点数
#define INF 1000000 // 无穷大的距离(即不存在的边的距离)
// 邻接表中的边结构体
typedef struct Edge {
int dest; // 目标顶点的下标
int weight; // 边的权重(距离)
struct Edge *next; // 指向下一个邻接点的指针
} Edge;
// 邻接表中的顶点结构体
typedef struct Vertex {
char name[20]; // 顶点的名称
Edge *head; // 指向第一个邻接点的指针
} Vertex;
// 图结构体
typedef struct Graph {
int num_vertices; // 顶点数
Vertex vertices[MAX_VERTICES]; // 顶点数组
} Graph;
// 初始化一个图
void init_graph(Graph *graph) {
graph->num_vertices = 0;
for (int i = 0; i < MAX_VERTICES; i++) {
graph->vertices[i].head = NULL;
}
}
// 添加一个顶点到图中
void add_vertex(Graph *graph, const char *name) {
Vertex *v = &graph->vertices[graph->num_vertices++];
strcpy(v->name, name);
v->head = NULL;
}
// 添加一条边到图中
void add_edge(Graph *graph, int src, int dest, int weight) {
Edge *e = (Edge*) malloc(sizeof(Edge));
e->dest = dest;
e->weight = weight;
e->next = graph->vertices[src].head;
graph->vertices[src].head = e;
}
// Dijkstra算法求最短路径
void dijkstra(Graph *graph, int start, int distances[], int prev[]) {
int i, j, k, min_distance;
int visited[MAX_VERTICES];
// 初始化距离和前驱数组
for (i = 0; i < graph->num_vertices; i++) {
distances[i] = INF;
prev[i] = -1;
visited[i] = 0;
}
distances[start] = 0;
// 遍历所有顶点
for (i = 0; i < graph->num_vertices; i++) {
// 找到未访问过的距离最短的顶点
min_distance = INF;
for (j = 0; j < graph->num_vertices; j++) {
if (!visited[j] && distances[j] < min_distance) {
min_distance = distances[j];
k = j;
}
}
visited[k] = 1;
// 更新所有邻接点的距离和前驱
for (Edge *e = graph->vertices[k].head; e != NULL; e = e->next) {
j = e->dest;
if (!visited[j] && distances[k] + e->weight < distances[j]) {
distances[j] = distances[k] + e->weight;
prev[j] = k;
}
}
}
}
// 打印最短路径
void print_path(Graph *graph, int start, int end, int prev[]) {
if (start == end) {
printf("%s", graph->vertices[start].name);
return;
}
print_path(graph, start, prev[end], prev);
printf(" -> %s", graph->vertices[end].name);
}
// 选择最佳路径
void search_path(Graph *graph, int start, int end, int distances[], int prev[], int visited[], int path[], int *path_len, int *path_distance) {
int i, j, k, min_distance;
// 标记起点和终点已访问
visited[start] = 1;
visited[end] = 1;
// 初始化路径数组和路径长度
path[0] = start;
*path_len = 1;
*path_distance = 0;
// 在未访问的点中找到到已访问点距离最短的顶点,加入路径中
while (*path_len < graph->num_vertices) {
min_distance = INF;
for (i = 0; i < *path_len; i++) {
k = path[i];
for (Edge *e = graph->vertices[k].head; e != NULL; e = e->next) {
j = e->dest;
if (!visited[j] && e->weight < min_distance) {
min_distance = e->weight;
path[*path_len] = j;
}
}
}
if (min_distance == INF) { // 找不到更多的未访问点了
break;
}
visited[path[*path_len]] = 1;
*path_len += 1;
*path_distance += min_distance;
}
// 如果终点不在路径中,则将终点加入路径
if (path[*path_len - 1] != end) {
path[*path_len] = end;
*path_len += 1;
}
}
int main() {
Graph graph;
int distances[MAX_VERTICES];
int prev[MAX_VERTICES];
int visited[MAX_VERTICES];
int path[MAX_VERTICES];
int path_len, path_distance;
init_graph(&graph);
// 添加顶点
add_vertex(&graph, "Entrance");
add_vertex(&graph, "Lake");
add_vertex(&graph, "Mountain");
add_vertex(&graph, "Forest");
add_vertex(&graph, "Valley");
// 添加边
add_edge(&graph, 0, 1, 20);
add_edge(&graph, 0, 2, 30);
add_edge(&graph, 0, 3, 15);
add_edge(&graph, 1, 2, 10);
add_edge(&graph, 1, 3, 25);
add_edge(&graph, 2, 4, 20);
add_edge(&graph, 3, 4, 10);
// 查询景点信息
printf("Which vertex do you want to know? ");
char name[20];
scanf("%s", name);
for (int i = 0; i < graph.num_vertices; i++) {
if (strcmp(graph.vertices[i].name, name) == 0) {
printf("Vertex %s:\n", name);
printf(" Adjacent vertices:");
for (Edge *e = graph.vertices[i].head; e != NULL; e = e->next) {
printf(" %s", graph.vertices[e->dest].name);
}
printf("\n");
break;
}
}
// 查询最短路径
printf("Which two vertices do you want to find the shortest path between? ");
char name1[20], name2[20];
scanf("%s %s", name1, name2);
int start = -1, end = -1;
for (int i = 0; i < graph.num_vertices; i++) {
if (strcmp(graph.vertices[i].name, name1) == 0) {
start = i;
}
if (strcmp(graph.vertices[i].name, name2) == 0) {
end = i;
}
}
if (start != -1 && end != -1) {
dijkstra(&graph, start, distances, prev);
printf("The shortest path from %s to %s is:\n", name1, name2);
print_path(&graph, start, end, prev);
printf("\n");
printf("The distance is %d.\n", distances[end]);
} else {
printf("Cannot find the vertices.\n");
}
// 选择最佳路径
printf("Choose the vertices you want to visit in order: ");
int path_vertices[MAX_VERTICES];
int num_path_vertices = 0;
while (scanf("%s", name) == 1) {
for (int i = 0; i < graph.num_vertices; i++) {
if (strcmp(graph.vertices[i].name, name) == 0) {
path_vertices[num_path_vertices++] = i;
break;
}
}
}
if (num_path_vertices > 1) {
// 初始化访问数组
for (int i = 0; i < graph.num_vertices; i++) {
visited[i] = 0;
}
// 对每一段路径使用Dijkstra算法求最短距离
int total_distance = 0;
for (int i = 0; i < num_path_vertices - 1; i++) {
dijkstra(&graph, path_vertices[i], distances, prev);
total_distance += distances[path_vertices[i + 1]];
}
// 使用搜索选择最佳路径
search_path(&graph, path_vertices[0], path_vertices[num_path_vertices - 1], distances, prev, visited, path, &path_len, &path_distance);
printf("The best path to visit these vertices is:\n");
for (int i = 0; i < path_len; i++) {
printf("%s", graph.vertices[path[i]].name);
if (i < path_len - 1) {
printf(" -> ");
}
}
printf("\n");
printf("The total distance is %d.\n", total_distance);
} else {
printf("Please input at least two vertices.\n");
}
return 0;
}
```
这个程序可以在终端中运行,用户可以通过输入不同的命令来查询图中的信息。其中,输入数字、图中顶点的名称等信息时,需要按照程序中规定的格式输入。
阅读全文