add: 添加实训 '数据结构课程设计'
This commit is contained in:
3
PracticalTrain/DataStructure/.gitignore
vendored
Normal file
3
PracticalTrain/DataStructure/.gitignore
vendored
Normal file
@@ -0,0 +1,3 @@
|
|||||||
|
main.cpp
|
||||||
|
bin
|
||||||
|
obj
|
||||||
52
PracticalTrain/DataStructure/Makefile
Normal file
52
PracticalTrain/DataStructure/Makefile
Normal file
@@ -0,0 +1,52 @@
|
|||||||
|
# Makefile for Bus Route Management System
|
||||||
|
|
||||||
|
CC = gcc
|
||||||
|
CFLAGS = -Wall -Wextra -g -I./include
|
||||||
|
LDFLAGS = -lm
|
||||||
|
|
||||||
|
# 目录
|
||||||
|
SRC_DIR = src
|
||||||
|
INC_DIR = include
|
||||||
|
OBJ_DIR = obj
|
||||||
|
BIN_DIR = bin
|
||||||
|
DATA_DIR = data
|
||||||
|
|
||||||
|
# 源文件和目标文件
|
||||||
|
SOURCES = $(wildcard $(SRC_DIR)/*.c)
|
||||||
|
OBJECTS = $(SOURCES:$(SRC_DIR)/%.c=$(OBJ_DIR)/%.o)
|
||||||
|
TARGET = $(BIN_DIR)/bus_system
|
||||||
|
|
||||||
|
# 默认目标
|
||||||
|
all: directories $(TARGET)
|
||||||
|
|
||||||
|
# 创建必要的目录
|
||||||
|
directories:
|
||||||
|
@mkdir -p $(OBJ_DIR)
|
||||||
|
@mkdir -p $(BIN_DIR)
|
||||||
|
@mkdir -p $(DATA_DIR)
|
||||||
|
|
||||||
|
# 链接目标文件生成可执行文件
|
||||||
|
$(TARGET): $(OBJECTS)
|
||||||
|
$(CC) $(OBJECTS) -o $(TARGET) $(LDFLAGS)
|
||||||
|
@cp -r $(DATA_DIR) $(BIN_DIR)
|
||||||
|
@echo "build successful: $(TARGET)"
|
||||||
|
|
||||||
|
# 编译源文件为目标文件
|
||||||
|
$(OBJ_DIR)/%.o: $(SRC_DIR)/%.c
|
||||||
|
$(CC) $(CFLAGS) -c $< -o $@
|
||||||
|
|
||||||
|
# 清理编译文件
|
||||||
|
clean:
|
||||||
|
rm -rf $(OBJ_DIR) $(BIN_DIR)
|
||||||
|
@echo "clean over"
|
||||||
|
|
||||||
|
# 运行程序
|
||||||
|
run: $(TARGET)
|
||||||
|
@cp -r $(DATA_DIR) $(BIN_DIR)
|
||||||
|
@cd $(BIN_DIR) && ./bus_system
|
||||||
|
|
||||||
|
# 安装数据文件(如果需要)
|
||||||
|
install-data:
|
||||||
|
@echo "请确保 data/ 目录包含 stations.csv 和 routes.csv"
|
||||||
|
|
||||||
|
.PHONY: all clean run directories install-data
|
||||||
33
PracticalTrain/DataStructure/README.md
Normal file
33
PracticalTrain/DataStructure/README.md
Normal file
@@ -0,0 +1,33 @@
|
|||||||
|
## 课题二十六: 校园巴士实时查询系统
|
||||||
|
|
||||||
|
### 一、设计目的
|
||||||
|
|
||||||
|
1. 掌握数据结构知识,强化C语言编程实现与算法设计的结合;
|
||||||
|
2. 提升对数据结构的逻辑设计与存储结构的理解。
|
||||||
|
|
||||||
|
|
||||||
|
### 二、设计任务与要求
|
||||||
|
|
||||||
|
**设计一个校园巴士线路查询系统,模拟巴士运行状态,提供实时到站预测和最优乘车方案。**
|
||||||
|
|
||||||
|
- 功能要求
|
||||||
|
|
||||||
|
1. 支持定义多条巴士线路,每条线路有固定站点序列,每个站点包含名称、位置坐标、停靠时间,线路信息可从配置文件加载;
|
||||||
|
2. 为每辆巴士维护当前位置、行驶方向、速度,模拟巴士在站点停靠(固定时间),实时更新所有巴士位置(每虚拟分钟更新一次);
|
||||||
|
3. 输入站点名,显示即将到达的巴士信息(线路号、预计到达时间),显示当前正在该站点停靠的巴士,显示该站点下一班各线路巴士的预计等待时间;
|
||||||
|
4. 输入起点和终点站点,推荐换乘方案,显示总行程时间、换乘次数、步行距离(简化),提供最快方案和最简方案(最少换乘)。
|
||||||
|
|
||||||
|
- 技术点要求
|
||||||
|
|
||||||
|
1. 使用邻接表存储巴士站点网络。
|
||||||
|
2. 实现Dijkstra算法计算最优路径。
|
||||||
|
3. 使用文本文件读写数据。
|
||||||
|
4. 程序结构清晰,功能模块划分合理。
|
||||||
|
|
||||||
|
### 三、设计步骤
|
||||||
|
|
||||||
|
1. 根据课题,查阅相关资料,确定结构体设计。
|
||||||
|
2. 明确相关功能,对功能部分进行设计及代码编写。
|
||||||
|
3. 对所写代码进行测试。
|
||||||
|
4. 撰写课程设计报告:字数约5000字(不包括程序清单)。
|
||||||
|
5. 答辩。
|
||||||
13
PracticalTrain/DataStructure/data/routes.csv
Normal file
13
PracticalTrain/DataStructure/data/routes.csv
Normal file
@@ -0,0 +1,13 @@
|
|||||||
|
id,routeName,stationCount
|
||||||
|
0,1ºÅÏß,4
|
||||||
|
0,1,2,3
|
||||||
|
5.0,6.0,7.0
|
||||||
|
1,2ºÅÏß,5
|
||||||
|
0,4,5,7,9
|
||||||
|
8.0,6.0,10.0,5.0
|
||||||
|
2,3ºÅÏß,4
|
||||||
|
1,6,4,2
|
||||||
|
4.0,5.0,6.0
|
||||||
|
3,4ºÅÏß,3
|
||||||
|
8,1,3
|
||||||
|
7.0,12.0
|
||||||
|
11
PracticalTrain/DataStructure/data/stations.csv
Normal file
11
PracticalTrain/DataStructure/data/stations.csv
Normal file
@@ -0,0 +1,11 @@
|
|||||||
|
id,name,latitude,longitude,stopTime
|
||||||
|
0,火车站,39.9042,116.4074,60
|
||||||
|
1,市中心,39.9100,116.4100,45
|
||||||
|
2,大学城,39.9200,116.4200,45
|
||||||
|
3,科技园,39.9300,116.4300,45
|
||||||
|
4,商业街,39.9150,116.4250,60
|
||||||
|
5,体育馆,39.9250,116.4350,45
|
||||||
|
6,公园,39.9180,116.4180,30
|
||||||
|
7,机场,39.9400,116.4400,90
|
||||||
|
8,医院,39.9050,116.4150,50
|
||||||
|
9,图书馆,39.9280,116.4280,40
|
||||||
|
49
PracticalTrain/DataStructure/include/graph.h
Normal file
49
PracticalTrain/DataStructure/include/graph.h
Normal file
@@ -0,0 +1,49 @@
|
|||||||
|
// include/graph.h
|
||||||
|
#ifndef GRAPH_H
|
||||||
|
#define GRAPH_H
|
||||||
|
|
||||||
|
#include <stdbool.h>
|
||||||
|
#include "station.h"
|
||||||
|
#include "route.h"
|
||||||
|
|
||||||
|
// 邻接表节点
|
||||||
|
typedef struct AdjNode {
|
||||||
|
int stationId;
|
||||||
|
int routeId;
|
||||||
|
double travelTime; // 行驶时间(分钟)
|
||||||
|
struct AdjNode* next;
|
||||||
|
} AdjNode;
|
||||||
|
|
||||||
|
// 邻接表
|
||||||
|
typedef struct AdjList {
|
||||||
|
AdjNode* head;
|
||||||
|
} AdjList;
|
||||||
|
|
||||||
|
// 图结构
|
||||||
|
typedef struct Graph {
|
||||||
|
AdjList adjLists[MAX_STATIONS];
|
||||||
|
int vertexCount;
|
||||||
|
} Graph;
|
||||||
|
|
||||||
|
// 路径节点
|
||||||
|
typedef struct PathNode {
|
||||||
|
int stationId;
|
||||||
|
int routeId;
|
||||||
|
double time;
|
||||||
|
struct PathNode* next;
|
||||||
|
} PathNode;
|
||||||
|
|
||||||
|
// 图操作函数
|
||||||
|
Graph* createGraph(int vertexCount);
|
||||||
|
void destroyGraph(Graph* graph);
|
||||||
|
void addEdge(Graph* graph, int from, int to, int routeId, double travelTime);
|
||||||
|
void buildGraphFromRoutes(Graph* graph, const BusRoute routes[], int routeCount,
|
||||||
|
const Station stations[], int stationCount);
|
||||||
|
|
||||||
|
// 路径查询函数
|
||||||
|
PathNode* dijkstra(Graph* graph, int start, int end, double* totalTime);
|
||||||
|
void freePath(PathNode* path);
|
||||||
|
void displayPath(PathNode* path, const Station stations[], int stationCount,
|
||||||
|
const BusRoute routes[], int routeCount);
|
||||||
|
|
||||||
|
#endif
|
||||||
22
PracticalTrain/DataStructure/include/route.h
Normal file
22
PracticalTrain/DataStructure/include/route.h
Normal file
@@ -0,0 +1,22 @@
|
|||||||
|
// include/route.h
|
||||||
|
#ifndef ROUTE_H
|
||||||
|
#define ROUTE_H
|
||||||
|
|
||||||
|
#include "station.h"
|
||||||
|
|
||||||
|
#define MAX_STATIONS_PER_ROUTE 50
|
||||||
|
|
||||||
|
typedef struct BusRoute {
|
||||||
|
int id;
|
||||||
|
char routeName[50];
|
||||||
|
int stationCount;
|
||||||
|
int stations[MAX_STATIONS_PER_ROUTE]; // 站点ID序列
|
||||||
|
double segmentTimes[MAX_STATIONS_PER_ROUTE]; // 每段行驶时间(分钟)
|
||||||
|
} BusRoute;
|
||||||
|
|
||||||
|
// 线路管理函数
|
||||||
|
int loadRoutes(const char* filename, BusRoute routes[], int maxRoutes);
|
||||||
|
void displayRoute(const BusRoute* route, const Station stations[], int stationCount);
|
||||||
|
void displayAllRoutes(const BusRoute routes[], int routeCount, const Station stations[], int stationCount);
|
||||||
|
|
||||||
|
#endif
|
||||||
23
PracticalTrain/DataStructure/include/station.h
Normal file
23
PracticalTrain/DataStructure/include/station.h
Normal file
@@ -0,0 +1,23 @@
|
|||||||
|
// include/station.h
|
||||||
|
#ifndef STATION_H
|
||||||
|
#define STATION_H
|
||||||
|
|
||||||
|
#define MAX_NAME 50
|
||||||
|
#define MAX_STATIONS 100
|
||||||
|
|
||||||
|
typedef struct Station {
|
||||||
|
int id;
|
||||||
|
char name[MAX_NAME];
|
||||||
|
double latitude;
|
||||||
|
double longitude;
|
||||||
|
int stopTime; // 停靠时间(秒)
|
||||||
|
} Station;
|
||||||
|
|
||||||
|
// 站点管理函数
|
||||||
|
int loadStations(const char* filename, Station stations[], int maxStations);
|
||||||
|
int findStationByName(const Station stations[], int count, const char* name);
|
||||||
|
int findStationById(const Station stations[], int count, int id);
|
||||||
|
void displayStation(const Station* station);
|
||||||
|
void displayAllStations(const Station stations[], int count);
|
||||||
|
|
||||||
|
#endif
|
||||||
169
PracticalTrain/DataStructure/src/graph.c
Normal file
169
PracticalTrain/DataStructure/src/graph.c
Normal file
@@ -0,0 +1,169 @@
|
|||||||
|
// src/graph.c
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <float.h>
|
||||||
|
#include "../include/graph.h"
|
||||||
|
|
||||||
|
// 创建图
|
||||||
|
Graph* createGraph(int vertexCount) {
|
||||||
|
Graph* graph = (Graph*)malloc(sizeof(Graph));
|
||||||
|
graph->vertexCount = vertexCount;
|
||||||
|
for (int i = 0; i < MAX_STATIONS; i++) {
|
||||||
|
graph->adjLists[i].head = NULL;
|
||||||
|
}
|
||||||
|
return graph;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 销毁图
|
||||||
|
void destroyGraph(Graph* graph) {
|
||||||
|
if (!graph) return;
|
||||||
|
|
||||||
|
for (int i = 0; i < MAX_STATIONS; i++) {
|
||||||
|
AdjNode* curr = graph->adjLists[i].head;
|
||||||
|
while (curr) {
|
||||||
|
AdjNode* temp = curr;
|
||||||
|
curr = curr->next;
|
||||||
|
free(temp);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
free(graph);
|
||||||
|
}
|
||||||
|
|
||||||
|
// 添加边
|
||||||
|
void addEdge(Graph* graph, int from, int to, int routeId, double travelTime) {
|
||||||
|
AdjNode* newNode = (AdjNode*)malloc(sizeof(AdjNode));
|
||||||
|
newNode->stationId = to;
|
||||||
|
newNode->routeId = routeId;
|
||||||
|
newNode->travelTime = travelTime;
|
||||||
|
newNode->next = graph->adjLists[from].head;
|
||||||
|
graph->adjLists[from].head = newNode;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 从线路构建图(双向)
|
||||||
|
void buildGraphFromRoutes(Graph* graph, const BusRoute routes[], int routeCount,
|
||||||
|
const Station stations[], int stationCount) {
|
||||||
|
for (int r = 0; r < routeCount; r++) {
|
||||||
|
for (int i = 0; i < routes[r].stationCount - 1; i++) {
|
||||||
|
int from = routes[r].stations[i];
|
||||||
|
int to = routes[r].stations[i + 1];
|
||||||
|
double segmentTime = routes[r].segmentTimes[i];
|
||||||
|
|
||||||
|
// 获取站点停靠时间
|
||||||
|
int fromIdx = findStationById(stations, stationCount, from);
|
||||||
|
int toIdx = findStationById(stations, stationCount, to);
|
||||||
|
|
||||||
|
if (fromIdx == -1 || toIdx == -1) continue;
|
||||||
|
|
||||||
|
double fromStopTime = stations[fromIdx].stopTime / 60.0;
|
||||||
|
double toStopTime = stations[toIdx].stopTime / 60.0;
|
||||||
|
|
||||||
|
// 正向边: from -> to
|
||||||
|
addEdge(graph, from, to, r, segmentTime + fromStopTime);
|
||||||
|
|
||||||
|
// 反向边: to -> from(支持返程)
|
||||||
|
addEdge(graph, to, from, r, segmentTime + toStopTime);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
printf("图构建完成(支持双向路线)\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
// Dijkstra算法
|
||||||
|
PathNode* dijkstra(Graph* graph, int start, int end, double* totalTime) {
|
||||||
|
double dist[MAX_STATIONS];
|
||||||
|
int prev[MAX_STATIONS];
|
||||||
|
int prevRoute[MAX_STATIONS];
|
||||||
|
bool visited[MAX_STATIONS] = {false};
|
||||||
|
|
||||||
|
// 初始化
|
||||||
|
for (int i = 0; i < MAX_STATIONS; i++) {
|
||||||
|
dist[i] = DBL_MAX;
|
||||||
|
prev[i] = -1;
|
||||||
|
prevRoute[i] = -1;
|
||||||
|
}
|
||||||
|
dist[start] = 0;
|
||||||
|
|
||||||
|
// Dijkstra主循环
|
||||||
|
for (int count = 0; count < graph->vertexCount; count++) {
|
||||||
|
double minDist = DBL_MAX;
|
||||||
|
int u = -1;
|
||||||
|
|
||||||
|
// 找到未访问的最小距离节点
|
||||||
|
for (int i = 0; i < MAX_STATIONS; i++) {
|
||||||
|
if (!visited[i] && dist[i] < minDist) {
|
||||||
|
minDist = dist[i];
|
||||||
|
u = i;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (u == -1 || u == end) break;
|
||||||
|
visited[u] = true;
|
||||||
|
|
||||||
|
// 更新相邻节点
|
||||||
|
AdjNode* node = graph->adjLists[u].head;
|
||||||
|
while (node != NULL) {
|
||||||
|
int v = node->stationId;
|
||||||
|
double weight = node->travelTime;
|
||||||
|
|
||||||
|
if (!visited[v] && dist[u] + weight < dist[v]) {
|
||||||
|
dist[v] = dist[u] + weight;
|
||||||
|
prev[v] = u;
|
||||||
|
prevRoute[v] = node->routeId;
|
||||||
|
}
|
||||||
|
node = node->next;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 检查是否找到路径
|
||||||
|
if (dist[end] == DBL_MAX) {
|
||||||
|
*totalTime = -1;
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
*totalTime = dist[end];
|
||||||
|
|
||||||
|
// 重建路径
|
||||||
|
PathNode* path = NULL;
|
||||||
|
for (int v = end; v != -1; v = prev[v]) {
|
||||||
|
PathNode* newNode = (PathNode*)malloc(sizeof(PathNode));
|
||||||
|
newNode->stationId = v;
|
||||||
|
newNode->routeId = prevRoute[v];
|
||||||
|
newNode->time = dist[v];
|
||||||
|
newNode->next = path;
|
||||||
|
path = newNode;
|
||||||
|
}
|
||||||
|
|
||||||
|
return path;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 释放路径
|
||||||
|
void freePath(PathNode* path) {
|
||||||
|
while (path) {
|
||||||
|
PathNode* temp = path;
|
||||||
|
path = path->next;
|
||||||
|
free(temp);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 显示路径
|
||||||
|
void displayPath(PathNode* path, const Station stations[], int stationCount,
|
||||||
|
const BusRoute routes[], int routeCount) {
|
||||||
|
(void)routeCount; // 标记为未使用,避免警告
|
||||||
|
|
||||||
|
if (!path) return;
|
||||||
|
|
||||||
|
PathNode* curr = path;
|
||||||
|
while (curr) {
|
||||||
|
int stationIdx = findStationById(stations, stationCount, curr->stationId);
|
||||||
|
if (stationIdx != -1) {
|
||||||
|
printf(" %s", stations[stationIdx].name);
|
||||||
|
|
||||||
|
if (curr->next && curr->next->routeId != -1) {
|
||||||
|
printf(" -[%s]-> ", routes[curr->next->routeId].routeName);
|
||||||
|
} else if (!curr->next) {
|
||||||
|
printf(" (到达)");
|
||||||
|
}
|
||||||
|
printf("\n");
|
||||||
|
}
|
||||||
|
curr = curr->next;
|
||||||
|
}
|
||||||
|
}
|
||||||
170
PracticalTrain/DataStructure/src/main.c
Normal file
170
PracticalTrain/DataStructure/src/main.c
Normal file
@@ -0,0 +1,170 @@
|
|||||||
|
// src/main.c
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <string.h>
|
||||||
|
#include "../include/station.h"
|
||||||
|
#include "../include/route.h"
|
||||||
|
#include "../include/graph.h"
|
||||||
|
|
||||||
|
#define MAX_ROUTES 20
|
||||||
|
|
||||||
|
// 全局变量
|
||||||
|
Station stations[MAX_STATIONS];
|
||||||
|
BusRoute routes[MAX_ROUTES];
|
||||||
|
int stationCount = 0;
|
||||||
|
int routeCount = 0;
|
||||||
|
Graph* graph = NULL;
|
||||||
|
|
||||||
|
// 函数声明
|
||||||
|
void printMenu();
|
||||||
|
void queryRoute();
|
||||||
|
void saveQueryResult(const char* filename, const char* startName, const char* endName,
|
||||||
|
PathNode* path, double totalTime);
|
||||||
|
|
||||||
|
// 打印菜单
|
||||||
|
void printMenu() {
|
||||||
|
printf("\n╔════════════════════════════════╗\n");
|
||||||
|
printf("║ 巴士路线管理系统 ║\n");
|
||||||
|
printf("╠════════════════════════════════╣\n");
|
||||||
|
printf("║ 1. 查询最短路径 ║\n");
|
||||||
|
printf("║ 2. 显示所有站点 ║\n");
|
||||||
|
printf("║ 3. 显示所有线路 ║\n");
|
||||||
|
printf("║ 4. 退出系统 ║\n");
|
||||||
|
printf("╚════════════════════════════════╝\n");
|
||||||
|
printf("请选择功能 (1-4): ");
|
||||||
|
}
|
||||||
|
|
||||||
|
// 查询路线
|
||||||
|
void queryRoute() {
|
||||||
|
char startName[MAX_NAME], endName[MAX_NAME];
|
||||||
|
|
||||||
|
printf("\n请输入起点站名称: ");
|
||||||
|
scanf("%s", startName);
|
||||||
|
printf("请输入终点站名称: ");
|
||||||
|
scanf("%s", endName);
|
||||||
|
|
||||||
|
int startId = findStationByName(stations, stationCount, startName);
|
||||||
|
int endId = findStationByName(stations, stationCount, endName);
|
||||||
|
|
||||||
|
if (startId == -1) {
|
||||||
|
printf("错误: 找不到站点 '%s'\n", startName);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (endId == -1) {
|
||||||
|
printf("错误: 找不到站点 '%s'\n", endName);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
double totalTime;
|
||||||
|
PathNode* path = dijkstra(graph, startId, endId, &totalTime);
|
||||||
|
|
||||||
|
if (!path || totalTime < 0) {
|
||||||
|
printf("\n没有找到从 %s 到 %s 的路线\n", startName, endName);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
printf("\n========== 最短路径查询结果 ==========\n");
|
||||||
|
printf("起点: %s\n", startName);
|
||||||
|
printf("终点: %s\n", endName);
|
||||||
|
printf("总时间: %.2f 分钟\n", totalTime);
|
||||||
|
printf("\n详细路线:\n");
|
||||||
|
|
||||||
|
displayPath(path, stations, stationCount, routes, routeCount);
|
||||||
|
|
||||||
|
printf("=====================================\n\n");
|
||||||
|
|
||||||
|
// 保存结果
|
||||||
|
saveQueryResult("data/query_results.txt", startName, endName, path, totalTime);
|
||||||
|
|
||||||
|
freePath(path);
|
||||||
|
}
|
||||||
|
|
||||||
|
// 保存查询结果
|
||||||
|
void saveQueryResult(const char* filename, const char* startName, const char* endName,
|
||||||
|
PathNode* path, double totalTime) {
|
||||||
|
FILE* fp = fopen(filename, "a");
|
||||||
|
if (!fp) {
|
||||||
|
printf("警告: 无法保存查询结果到文件\n");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
fprintf(fp, "================================\n");
|
||||||
|
fprintf(fp, "起点: %s\n", startName);
|
||||||
|
fprintf(fp, "终点: %s\n", endName);
|
||||||
|
fprintf(fp, "总时间: %.2f 分钟\n", totalTime);
|
||||||
|
fprintf(fp, "路径: ");
|
||||||
|
|
||||||
|
PathNode* curr = path;
|
||||||
|
while (curr) {
|
||||||
|
int stationIdx = findStationById(stations, stationCount, curr->stationId);
|
||||||
|
if (stationIdx != -1) {
|
||||||
|
fprintf(fp, "%s", stations[stationIdx].name);
|
||||||
|
if (curr->next) {
|
||||||
|
fprintf(fp, " -> ");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
curr = curr->next;
|
||||||
|
}
|
||||||
|
fprintf(fp, "\n");
|
||||||
|
|
||||||
|
fclose(fp);
|
||||||
|
}
|
||||||
|
|
||||||
|
// 主函数
|
||||||
|
int main() {
|
||||||
|
printf("========================================\n");
|
||||||
|
printf(" 巴士路线管理系统 v1.0\n");
|
||||||
|
printf("========================================\n\n");
|
||||||
|
|
||||||
|
// 加载数据
|
||||||
|
printf("正在加载系统数据...\n");
|
||||||
|
stationCount = loadStations("data/stations.csv", stations, MAX_STATIONS);
|
||||||
|
if (stationCount == 0) {
|
||||||
|
printf("错误: 无法加载站点数据\n");
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
routeCount = loadRoutes("data/routes.csv", routes, MAX_ROUTES);
|
||||||
|
if (routeCount == 0) {
|
||||||
|
printf("错误: 无法加载线路数据\n");
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 创建图
|
||||||
|
graph = createGraph(stationCount);
|
||||||
|
buildGraphFromRoutes(graph, routes, routeCount, stations, stationCount);
|
||||||
|
|
||||||
|
printf("\n系统初始化完成!\n");
|
||||||
|
|
||||||
|
// 主循环
|
||||||
|
int choice;
|
||||||
|
while (1) {
|
||||||
|
printMenu();
|
||||||
|
|
||||||
|
if (scanf("%d", &choice) != 1) {
|
||||||
|
while (getchar() != '\n');
|
||||||
|
printf("无效输入,请输入数字1-4\n");
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
switch (choice) {
|
||||||
|
case 1:
|
||||||
|
queryRoute();
|
||||||
|
break;
|
||||||
|
case 2:
|
||||||
|
displayAllStations(stations, stationCount);
|
||||||
|
break;
|
||||||
|
case 3:
|
||||||
|
displayAllRoutes(routes, routeCount, stations, stationCount);
|
||||||
|
break;
|
||||||
|
case 4:
|
||||||
|
printf("\n感谢使用巴士路线管理系统!\n");
|
||||||
|
destroyGraph(graph);
|
||||||
|
return 0;
|
||||||
|
default:
|
||||||
|
printf("无效选择,请输入1-4\n");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
83
PracticalTrain/DataStructure/src/route.c
Normal file
83
PracticalTrain/DataStructure/src/route.c
Normal file
@@ -0,0 +1,83 @@
|
|||||||
|
// src/route.c
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <string.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include "../include/route.h"
|
||||||
|
|
||||||
|
// 从文件加载线路信息
|
||||||
|
int loadRoutes(const char* filename, BusRoute routes[], int maxRoutes) {
|
||||||
|
FILE* fp = fopen(filename, "r");
|
||||||
|
if (!fp) {
|
||||||
|
printf("错误: 无法打开文件 %s\n", filename);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
int count = 0;
|
||||||
|
char line[512];
|
||||||
|
|
||||||
|
// 跳过标题行
|
||||||
|
if (fgets(line, sizeof(line), fp) == NULL) {
|
||||||
|
fclose(fp);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
while (count < maxRoutes) {
|
||||||
|
// 读取基本信息: id,routeName,stationCount
|
||||||
|
if (fscanf(fp, "%d,%49[^,],%d\n",
|
||||||
|
&routes[count].id,
|
||||||
|
routes[count].routeName,
|
||||||
|
&routes[count].stationCount) != 3) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 读取站点序列
|
||||||
|
if (fgets(line, sizeof(line), fp) == NULL) break;
|
||||||
|
char* token = strtok(line, ",\n");
|
||||||
|
int idx = 0;
|
||||||
|
while (token != NULL && idx < routes[count].stationCount) {
|
||||||
|
routes[count].stations[idx++] = atoi(token);
|
||||||
|
token = strtok(NULL, ",\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
// 读取各段行驶时间
|
||||||
|
if (fgets(line, sizeof(line), fp) == NULL) break;
|
||||||
|
token = strtok(line, ",\n");
|
||||||
|
idx = 0;
|
||||||
|
while (token != NULL && idx < routes[count].stationCount - 1) {
|
||||||
|
routes[count].segmentTimes[idx++] = atof(token);
|
||||||
|
token = strtok(NULL, ",\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
count++;
|
||||||
|
}
|
||||||
|
|
||||||
|
fclose(fp);
|
||||||
|
printf("成功加载 %d 条线路\n", count);
|
||||||
|
return count;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 显示单条线路
|
||||||
|
void displayRoute(const BusRoute* route, const Station stations[], int stationCount) {
|
||||||
|
printf("%s: ", route->routeName);
|
||||||
|
for (int i = 0; i < route->stationCount; i++) {
|
||||||
|
int stationIdx = findStationById(stations, stationCount, route->stations[i]);
|
||||||
|
if (stationIdx != -1) {
|
||||||
|
printf("%s", stations[stationIdx].name);
|
||||||
|
if (i < route->stationCount - 1) {
|
||||||
|
printf(" -> ");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
printf("\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
// 显示所有线路
|
||||||
|
void displayAllRoutes(const BusRoute routes[], int routeCount,
|
||||||
|
const Station stations[], int stationCount) {
|
||||||
|
printf("\n========== 所有线路信息 ==========\n");
|
||||||
|
for (int i = 0; i < routeCount; i++) {
|
||||||
|
displayRoute(&routes[i], stations, stationCount);
|
||||||
|
}
|
||||||
|
printf("总计: %d 条线路\n", routeCount);
|
||||||
|
printf("==================================\n");
|
||||||
|
}
|
||||||
75
PracticalTrain/DataStructure/src/station.c
Normal file
75
PracticalTrain/DataStructure/src/station.c
Normal file
@@ -0,0 +1,75 @@
|
|||||||
|
// src/station.c
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <string.h>
|
||||||
|
#include "../include/station.h"
|
||||||
|
|
||||||
|
// 从文件加载站点信息
|
||||||
|
int loadStations(const char* filename, Station stations[], int maxStations) {
|
||||||
|
FILE* fp = fopen(filename, "r");
|
||||||
|
if (!fp) {
|
||||||
|
printf("错误: 无法打开文件 %s\n", filename);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
int count = 0;
|
||||||
|
char line[256];
|
||||||
|
|
||||||
|
// 跳过标题行
|
||||||
|
if (fgets(line, sizeof(line), fp) == NULL) {
|
||||||
|
fclose(fp);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
while (count < maxStations &&
|
||||||
|
fscanf(fp, "%d,%49[^,],%lf,%lf,%d\n",
|
||||||
|
&stations[count].id,
|
||||||
|
stations[count].name,
|
||||||
|
&stations[count].latitude,
|
||||||
|
&stations[count].longitude,
|
||||||
|
&stations[count].stopTime) == 5) {
|
||||||
|
count++;
|
||||||
|
}
|
||||||
|
|
||||||
|
fclose(fp);
|
||||||
|
printf("成功加载 %d 个站点\n", count);
|
||||||
|
return count;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 根据名称查找站点
|
||||||
|
int findStationByName(const Station stations[], int count, const char* name) {
|
||||||
|
for (int i = 0; i < count; i++) {
|
||||||
|
if (strcmp(stations[i].name, name) == 0) {
|
||||||
|
return stations[i].id;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 根据ID查找站点索引
|
||||||
|
int findStationById(const Station stations[], int count, int id) {
|
||||||
|
for (int i = 0; i < count; i++) {
|
||||||
|
if (stations[i].id == id) {
|
||||||
|
return i;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 显示单个站点信息
|
||||||
|
void displayStation(const Station* station) {
|
||||||
|
printf(" ID: %d\n", station->id);
|
||||||
|
printf(" 名称: %s\n", station->name);
|
||||||
|
printf(" 经纬度: (%.4f, %.4f)\n", station->latitude, station->longitude);
|
||||||
|
printf(" 停靠时间: %d秒\n", station->stopTime);
|
||||||
|
}
|
||||||
|
|
||||||
|
// 显示所有站点
|
||||||
|
void displayAllStations(const Station stations[], int count) {
|
||||||
|
printf("\n========== 所有站点信息 ==========\n");
|
||||||
|
for (int i = 0; i < count; i++) {
|
||||||
|
printf("%d. %s (停靠时间: %d秒)\n",
|
||||||
|
stations[i].id, stations[i].name, stations[i].stopTime);
|
||||||
|
}
|
||||||
|
printf("总计: %d 个站点\n", count);
|
||||||
|
printf("==================================\n");
|
||||||
|
}
|
||||||
15
PracticalTrain/README.md
Normal file
15
PracticalTrain/README.md
Normal file
@@ -0,0 +1,15 @@
|
|||||||
|
<!--
|
||||||
|
Copyright (c) 2025 zhilv
|
||||||
|
|
||||||
|
This software is released under the MIT License.
|
||||||
|
https://opensource.org/licenses/MIT
|
||||||
|
-->
|
||||||
|
|
||||||
|
## 实训
|
||||||
|
|
||||||
|
### 文件介绍
|
||||||
|
|
||||||
|
```sh
|
||||||
|
.
|
||||||
|
└── DataStructure # 数据结构课程设计
|
||||||
|
```
|
||||||
@@ -11,6 +11,7 @@
|
|||||||
```sh
|
```sh
|
||||||
.
|
.
|
||||||
├── DataStructure # 数据结构
|
├── DataStructure # 数据结构
|
||||||
|
├── PracticalTrain # 实训
|
||||||
├── Server # Node.js 从基础到项目实践
|
├── Server # Node.js 从基础到项目实践
|
||||||
├── Spider # Python 网络爬虫基础教程
|
├── Spider # Python 网络爬虫基础教程
|
||||||
└── Web # Web 前端开发技术
|
└── Web # Web 前端开发技术
|
||||||
@@ -21,6 +22,7 @@
|
|||||||
- [`Node.js` 从基础到项目实践](Server/README.md)
|
- [`Node.js` 从基础到项目实践](Server/README.md)
|
||||||
- [`Python` 网络爬虫基础教程](Spider/README.md)
|
- [`Python` 网络爬虫基础教程](Spider/README.md)
|
||||||
- [`Web` 前端开发技术](Web/README.md)
|
- [`Web` 前端开发技术](Web/README.md)
|
||||||
|
- [实训](PracticalTrain/README.md)
|
||||||
|
|
||||||
## 📜 License
|
## 📜 License
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user