实验内容与要求: 用C语言设计江西服装学院的校园平面图,所含景点不少于8个。以图中顶点表示学校内各景点,存放景点的名称、景点介绍信息等;以边表示路径,存放路径长度信息。要求将这些信息保存在文件graph.txt中,系统执行时所处理的数据要对此文件分别进行读写操作。 1.从文件graph.txt中读取相应数据, 创建一个图,使用邻接矩阵表示图; 2.景点信息查询:为来访客人提供校园任意景点相关信息的介绍; 3.问路查询:为来访客人提供校园任意两个景点之间的一条最短路径。
时间: 2024-01-22 10:20:16 浏览: 33
本实验要求用C语言设计江西服装学院的校园平面图,包含不少于8个景点,将这些景点及其路径长度信息保存在文件graph.txt中。下面按照实验要求进行详细讲解。
1. 从文件graph.txt中读取相应数据, 创建一个图,使用邻接矩阵表示图
读取文件graph.txt中的数据可以使用C语言中的文件操作函数fopen、fscanf等。首先需要定义一个结构体来存储景点信息,包括景点名称和景点介绍信息。
```c
typedef struct {
char name[50]; // 景点名称
char intro[200]; // 景点介绍信息
} Vertex;
```
然后需要定义一个二维数组来表示邻接矩阵,即每个景点之间的路径长度。由于是无向图,所以邻接矩阵是对称的。
```c
#define MAX_VERTICES 20
int adjMatrix[MAX_VERTICES][MAX_VERTICES];
```
接下来,我们可以编写一个函数来读取文件中的数据,并创建邻接矩阵表示的图。
```c
void readGraphFromFile(char* filename, Vertex vertices[], int* numVertices) {
FILE* fp = fopen(filename, "r");
if (fp == NULL) {
printf("Failed to open file %s.\n", filename);
exit(1);
}
fscanf(fp, "%d", numVertices); // 读取顶点数
for (int i = 0; i < *numVertices; i++) {
fscanf(fp, "%s %[^\n]", vertices[i].name, vertices[i].intro);
}
// 初始化邻接矩阵
for (int i = 0; i < *numVertices; i++) {
for (int j = 0; j < *numVertices; j++) {
adjMatrix[i][j] = -1; // -1表示不可达
}
adjMatrix[i][i] = 0; // 自己到自己的距离为0
}
int u, v, w;
while (fscanf(fp, "%d %d %d", &u, &v, &w) == 3) {
adjMatrix[u][v] = w;
adjMatrix[v][u] = w; // 无向图,需要更新对称位置
}
fclose(fp);
}
```
这个函数首先打开文件,读取文件中的顶点数和每个顶点的名称和介绍信息。然后初始化邻接矩阵,将所有路径长度初始化为-1表示不可达,将自己到自己的距离初始化为0。接着,从文件中读取每条边的信息,并将对应位置的邻接矩阵元素更新为路径长度。读取完毕后关闭文件。
2. 景点信息查询:为来访客人提供校园任意景点相关信息的介绍
景点信息查询需要根据用户输入的景点名称在vertices数组中查找对应的景点信息并输出。需要注意的是,用户输入的景点名称可能不完全匹配,所以需要使用字符串匹配函数strstr进行模糊匹配。
```c
void searchVertexInfo(Vertex vertices[], int numVertices) {
char name[50];
printf("请输入要查询的景点名称:");
scanf("%s", name);
for (int i = 0; i < numVertices; i++) {
if (strstr(vertices[i].name, name) != NULL) {
printf("景点名称:%s\n", vertices[i].name);
printf("景点介绍:%s\n", vertices[i].intro);
return;
}
}
printf("未找到名称包含'%s'的景点。\n", name);
}
```
3. 问路查询:为来访客人提供校园任意两个景点之间的一条最短路径
问路查询需要使用Dijkstra算法来找到任意两个景点之间的最短路径。这里可以先编写一个辅助函数minDistance来找到当前未访问节点中距离起点最近的节点。
```c
int minDistance(int dist[], bool visited[], int numVertices) {
int minDist = INT_MAX, minIndex = -1;
for (int i = 0; i < numVertices; i++) {
if (!visited[i] && dist[i] < minDist) {
minDist = dist[i];
minIndex = i;
}
}
return minIndex;
}
```
然后就可以编写Dijkstra算法的主函数来计算最短路径。需要使用一个dist数组来保存当前起点到每个节点的最短距离,以及一个prev数组来保存当前节点的前驱节点。每次遍历时找到距离起点最近的未访问节点,将其标记为已访问,并更新与其相邻节点的最短距离和前驱节点。最后根据prev数组回溯出起点到终点的路径。
```c
void shortestPath(Vertex vertices[], int numVertices, int start, int end) {
int dist[MAX_VERTICES], prev[MAX_VERTICES];
bool visited[MAX_VERTICES] = { false };
for (int i = 0; i < numVertices; i++) {
dist[i] = INT_MAX;
prev[i] = -1;
}
dist[start] = 0;
for (int i = 0; i < numVertices - 1; i++) {
int u = minDistance(dist, visited, numVertices);
visited[u] = true;
for (int v = 0; v < numVertices; v++) {
if (!visited[v] && adjMatrix[u][v] != -1 &&
dist[u] != INT_MAX && dist[u] + adjMatrix[u][v] < dist[v]) {
dist[v] = dist[u] + adjMatrix[u][v];
prev[v] = u;
}
}
}
// 回溯路径
if (dist[end] == INT_MAX) {
printf("起点和终点之间不存在路径。\n");
} else {
printf("起点:%s\n终点:%s\n路径长度:%d\n路径:",
vertices[start].name, vertices[end].name, dist[end]);
int path[MAX_VERTICES], len = 0;
int curr = end;
while (curr != start) {
path[len++] = curr;
curr = prev[curr];
}
path[len++] = start;
for (int i = len - 1; i >= 0; i--) {
printf("%s", vertices[path[i]].name);
if (i > 0) printf(" -> ");
}
printf("\n");
}
}
```
这个函数首先初始化dist数组和prev数组,将起点到每个节点的距离都设为无穷大,将每个节点的前驱节点都设为-1。然后从起点开始遍历,每次找到距离起点最近的未访问节点,并更新与其相邻节点的最短距离和前驱节点。最后根据prev数组回溯出起点到终点的路径。如果终点不可达,则输出提示信息。
完整代码如下: