Init Repo
This commit is contained in:
+16
@@ -0,0 +1,16 @@
|
||||
# 编译产物
|
||||
obj/
|
||||
*.o
|
||||
*.exe
|
||||
train_ticket
|
||||
|
||||
# IDE
|
||||
.vscode/
|
||||
.idea/
|
||||
*.swp
|
||||
*.swo
|
||||
*~
|
||||
|
||||
# 系统文件
|
||||
.DS_Store
|
||||
Thumbs.db
|
||||
@@ -0,0 +1,18 @@
|
||||
MIT License
|
||||
|
||||
Copyright (c) 2026 JYUGod
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy of this software and
|
||||
associated documentation files (the "Software"), to deal in the Software without restriction, including
|
||||
without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the
|
||||
following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all copies or substantial
|
||||
portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT
|
||||
LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO
|
||||
EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
|
||||
IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
|
||||
USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
@@ -0,0 +1,29 @@
|
||||
# Makefile - 火车票务管理系统 (C++)
|
||||
# 编译:mingw32-make 或 make(Linux/Mac)
|
||||
# 清理:mingw32-make clean
|
||||
|
||||
CXX = g++
|
||||
CXXFLAGS = -Wall -Wextra -std=c++17 -g
|
||||
TARGET = train_ticket.exe
|
||||
SRCDIR = src
|
||||
OBJDIR = obj
|
||||
|
||||
SRCS = $(wildcard $(SRCDIR)/*.cpp)
|
||||
OBJS = $(patsubst $(SRCDIR)/%.cpp, $(OBJDIR)/%.o, $(SRCS))
|
||||
|
||||
$(TARGET): $(OBJDIR) $(OBJS)
|
||||
$(CXX) $(CXXFLAGS) -o $@ $(OBJS)
|
||||
|
||||
$(OBJDIR):
|
||||
mkdir -p $(OBJDIR)
|
||||
|
||||
$(OBJDIR)/%.o: $(SRCDIR)/%.cpp
|
||||
$(CXX) $(CXXFLAGS) -c $< -o $@
|
||||
|
||||
run: $(TARGET)
|
||||
./$(TARGET)
|
||||
|
||||
clean:
|
||||
rm -rf $(OBJDIR) $(TARGET)
|
||||
|
||||
.PHONY: run clean
|
||||
@@ -0,0 +1,250 @@
|
||||
# 数据结构课程设计 —— 设计文档
|
||||
|
||||
## 〇、选题名称
|
||||
|
||||
**《火车票务管理系统》**
|
||||
|
||||
---
|
||||
|
||||
## 一、项目背景与意义
|
||||
|
||||
模拟一个小型火车票务平台,乘客可以查询车次、购票、退票、查看换乘方案;管理员可以维护车次信息。
|
||||
目的是综合运用本学期学过的**线性表、栈、队列、图、查找、排序**这几类数据结构,做一个"看得见、能跑起来"的系统,而不是单独练习某一种数据结构。
|
||||
|
||||
---
|
||||
|
||||
## 二、需求分析
|
||||
|
||||
### 2.1 用户角色
|
||||
|
||||
| 角色 | 权限 |
|
||||
|---|---|
|
||||
| 管理员 | 增/删/改车次信息,查看销售统计 |
|
||||
| 普通乘客 | 查询车次、购票、退票、查看自己的订单、查询换乘方案 |
|
||||
|
||||
### 2.2 功能需求(对应任务书"增删改查排序统计"要求)
|
||||
|
||||
- **增**:新增车次(管理员);生成购票订单(乘客)
|
||||
- **删**:删除/停运车次(管理员);退票/取消订单(乘客)
|
||||
- **改**:修改车次信息(票价、时间、余票);改签订单
|
||||
- **查**:按车次号/出发站/到达站/日期查询车次;按身份证号/订单号查询订单;模糊查询
|
||||
- **排序**:按出发时间、票价、剩余票数排序展示
|
||||
- **统计**:统计某车次销售量、某线路客流量、某时间段总收入
|
||||
|
||||
### 2.3 非功能需求
|
||||
|
||||
- 界面采用菜单驱动(一级菜单 + 二级菜单),文字交互即可,不强制图形界面
|
||||
- 数据用文件持久化(`.csv`),程序启动时加载,操作后及时写回
|
||||
- 输入要做基本合法性校验(如车次号不能重复、余票不能为负)
|
||||
|
||||
---
|
||||
|
||||
## 三、个体数据描述(数据项设计)
|
||||
|
||||
### 3.1 车次信息 TrainInfo
|
||||
|
||||
| 字段 | 说明 | 类型示例 |
|
||||
|---|---|---|
|
||||
| trainNo | 车次号(唯一,如 G1234) | char[8] |
|
||||
| startStation | 始发站 | char[20] |
|
||||
| endStation | 终点站 | char[20] |
|
||||
| departTime | 出发时间 | char[10] |
|
||||
| arriveTime | 到达时间 | char[10] |
|
||||
| price | 票价 | float |
|
||||
| totalSeats | 总票数 | int |
|
||||
| remainSeats | 余票 | int |
|
||||
|
||||
### 3.2 订单信息 OrderInfo
|
||||
|
||||
| 字段 | 说明 |
|
||||
|---|---|
|
||||
| orderId | 订单号(唯一) |
|
||||
| trainNo | 关联车次号 |
|
||||
| passengerName | 乘客姓名 |
|
||||
| idCard | 身份证号(唯一标识乘客,可作哈希查找键) |
|
||||
| seatNo | 座位号 |
|
||||
| orderTime | 购票时间 |
|
||||
| status | 状态:已支付 / 候补中 / 已退票 |
|
||||
|
||||
### 3.3 站点/线路信息 Station(供图结构使用)
|
||||
|
||||
| 字段 | 说明 |
|
||||
|---|---|
|
||||
| stationId | 站点编号 |
|
||||
| stationName | 站点名称 |
|
||||
| adjList | 相邻站点及边权(时长或票价)—— 即图的邻接表 |
|
||||
|
||||
---
|
||||
|
||||
## 四、数据结构设计(核心部分)
|
||||
|
||||
这是整个课程设计评分的重点,下面把"用在哪、为什么用、要实现哪些算法"都列清楚,方便写报告时直接展开。
|
||||
|
||||
### 4.1 车次信息表 —— 顺序表(顺序存储结构)
|
||||
|
||||
作为本系统的**主线性表**,对应任务书"线性表若选顺序存储结构"的要求:
|
||||
|
||||
- 查找:**顺序查找** + **二分查找**(按车次号排序后二分)—— 满足"顺序查找 + 其他查找方式选一种"
|
||||
- 排序:**直接插入排序**(按车次号初始化排序)、**快速排序**(按票价排序)、**堆排序**(按余票数排序)—— 满足"三种以上排序算法"
|
||||
|
||||
```c
|
||||
typedef struct {
|
||||
TrainInfo data[MaxSize];
|
||||
int length;
|
||||
} TrainList;
|
||||
|
||||
bool ListInsert(TrainList *&L, int i, TrainInfo e);
|
||||
bool ListDelete(TrainList *&L, int i, TrainInfo &e);
|
||||
int SeqSearch(TrainList *L, char trainNo[]); // 顺序查找
|
||||
int BinSearch(TrainList *L, char trainNo[]); // 二分查找(要求按trainNo有序)
|
||||
void QuickSort(TrainList *&L, int low, int high); // 按票价快排
|
||||
void HeapSort(TrainList *&L); // 按余票堆排序
|
||||
```
|
||||
|
||||
### 4.2 线路网络 —— 图(邻接表存储)
|
||||
|
||||
这是本系统的**创新亮点**,对应任务书"图存储结构"的加分项:
|
||||
|
||||
- 顶点 = 车站,边 = 两站之间存在的车次(边权可设为"时长"或"票价")
|
||||
- **图的两种遍历**:DFS(深度优先,找某站出发能到达的所有站点)、BFS(广度优先,找最少换乘次数的路径)
|
||||
- **最短路径算法(Dijkstra)**:实现"最优换乘路径推荐"——给定起点和终点,算出耗时最短或票价最低的换乘方案
|
||||
- (可选加分)**最小生成树**:模拟"以最小总里程把所有站点连通"的线路规划场景
|
||||
|
||||
```c
|
||||
typedef struct {
|
||||
int stationId;
|
||||
char stationName[20];
|
||||
EdgeNode *firstEdge; // 邻接表头指针
|
||||
} VertexNode;
|
||||
|
||||
typedef struct EdgeNode {
|
||||
int toStationId;
|
||||
float weight; // 时长或票价
|
||||
struct EdgeNode *next;
|
||||
} EdgeNode;
|
||||
|
||||
void DFS(Graph G, int v);
|
||||
void BFS(Graph G, int v);
|
||||
void Dijkstra(Graph G, int src, float dist[], int path[]); // 最优换乘路径
|
||||
```
|
||||
|
||||
### 4.3 候补购票队列 —— 队列
|
||||
|
||||
当某车次余票为0时,乘客可加入候补队列;一旦有人退票释放余票,按**先进先出**原则自动给候补队列里排在最前面的乘客出票。
|
||||
|
||||
```c
|
||||
typedef struct {
|
||||
OrderInfo data[MaxSize];
|
||||
int front, rear;
|
||||
} WaitQueue;
|
||||
|
||||
bool EnQueue(WaitQueue *&Q, OrderInfo e); // 进入候补
|
||||
bool DeQueue(WaitQueue *&Q, OrderInfo &e); // 候补转正出票
|
||||
```
|
||||
|
||||
### 4.4 操作撤销栈 —— 栈
|
||||
|
||||
记录最近若干次"购票/退票/改签"操作,支持"撤销上一步",避免误操作(也是一个容易讲的创新点)。
|
||||
|
||||
```c
|
||||
typedef struct {
|
||||
OperationLog data[MaxSize];
|
||||
int top;
|
||||
} OpStack;
|
||||
|
||||
bool Push(OpStack *&S, OperationLog op);
|
||||
bool Pop(OpStack *&S, OperationLog &op); // 撤销最近一次操作
|
||||
```
|
||||
|
||||
### 4.5 订单快速查找 —— 哈希表
|
||||
|
||||
按身份证号哈希定位订单,避免每次都要顺序扫描全部订单,对应"分块查找/哈希表查找选一种"的要求(这里选哈希表)。
|
||||
|
||||
```c
|
||||
int Hash(char idCard[]); // 简单除留余数法或字符累加法
|
||||
bool HashInsert(OrderInfo orders[], OrderInfo e);
|
||||
OrderInfo* HashSearch(OrderInfo orders[], char idCard[]);
|
||||
```
|
||||
|
||||
> 小结:本系统用到 **顺序表 + 图 + 队列 + 栈 + 哈希表** 五种数据结构,覆盖面广,五个模块分给3人小组刚好可以人均2类结构、4个以上核心函数模块,工作量和创新点都比较容易达标。
|
||||
|
||||
---
|
||||
|
||||
## 五、系统功能模块划分(建议3人分工)
|
||||
|
||||
| 负责人 | 模块 | 核心数据结构 |
|
||||
|---|---|---|
|
||||
| 组员A — 李 | ① 车次信息增删改 ② 顺序/二分查找 ③ 三种排序 ④ 文件读写(trains.csv) | 顺序表 |
|
||||
| 组员B — 刘 | ① 购票下单 ② 退票/改签 ③ 候补排队 ④ 操作撤销栈 | 队列、栈 |
|
||||
| 组员C — 朱 | ① 线路图构建 ② 图的遍历(DFS/BFS) ③ 最短路径换乘推荐 ④ 订单哈希查找与销量统计 | 图、哈希表 |
|
||||
| 共同 | 菜单系统、登录权限、主程序整合 | — |
|
||||
|
||||
每人独立完成的模块均≥4个,预计人均代码量400行以上,总代码量轻松超过900行(任务书最低要求)。
|
||||
|
||||
---
|
||||
|
||||
## 六、文件存储格式设计
|
||||
|
||||
**trains.csv**
|
||||
```
|
||||
车次号,始发站,终点站,出发时间,到达时间,票价,总票数,余票
|
||||
G1907,北京,上海,08:00,13:28,553.0,800,800
|
||||
```
|
||||
|
||||
**orders.csv**
|
||||
```
|
||||
订单号,车次号,乘客姓名,身份证号,座位号,购票时间,状态
|
||||
O00001,G1907,张三,1101**********1234,03A,2026-07-08 09:12,已支付
|
||||
```
|
||||
|
||||
**stations.csv**(辅助构建图)
|
||||
```
|
||||
站点编号,站点名称,相邻站点(车次号:边权)
|
||||
1,北京,2:553.0
|
||||
2,上海,1:553.0;3:120.0
|
||||
```
|
||||
|
||||
> 建议至少录入30条以上"看起来真实"的车次/乘客数据,可以参考12306的真实城市和车次号编一套,满足"30条以上相对真实个体信息"的要求。
|
||||
|
||||
---
|
||||
|
||||
## 七、业务流程(文字版,写报告时可画成流程图)
|
||||
|
||||
**购票流程**:
|
||||
登录 → 查询车次(条件查询+排序展示)→ 选择车次 → 判断余票
|
||||
├ 有余票 → 生成订单、扣减余票、写回文件
|
||||
└ 无余票 → 询问是否进入候补队列 → 进入WaitQueue
|
||||
退票时若有候补,自动从队首取出一人补票。
|
||||
|
||||
**换乘查询流程**:
|
||||
输入起点/终点 → 在图中用Dijkstra计算最短路径(按时长或票价)→ 输出换乘方案(经过哪些站、换乘几次)
|
||||
|
||||
**数据流向**:
|
||||
用户输入 → 内存数据结构(顺序表/图/队列/栈/哈希表)→ 算法处理(查找/排序/最短路径)→ 显示结果 → 写回csv文件
|
||||
|
||||
---
|
||||
|
||||
## 八、创新点设计(用于答辩加分)
|
||||
|
||||
1. **最优换乘路径推荐**(图+Dijkstra)—— 力度最大的创新点
|
||||
2. **候补购票自动转正**(队列)
|
||||
3. **操作撤销/回退功能**(栈)
|
||||
4. **模糊查询/多条件组合查询**(如同时按出发站+价格区间筛选)
|
||||
5. (可选)简单密码哈希存储,提升登录安全性
|
||||
|
||||
> 任务书规定:每个创新点加5分,一组总加分不超过60分。上面5个点选3-4个做扎实,比贪多但都做得浅更划算。
|
||||
|
||||
---
|
||||
|
||||
## 九、工作量自查清单
|
||||
|
||||
- [ ] 每人源码 ≥ 300行(建议人均400行留余量)
|
||||
- [ ] 总代码量 ≥ 900行
|
||||
- [ ] 录入 ≥ 30条相对真实的车次/乘客数据
|
||||
- [ ] 顺序表满足:顺序查找 + 二分查找;三种以上排序算法
|
||||
- [ ] 图结构满足:两种遍历 + 最短路径算法
|
||||
- [ ] 报告正文(不含图、代码、运行截图)≥ 3000字
|
||||
- [ ] 与参考书同类型选题代码重复率 < 50%(本选题与参考书的"通讯录系统"差异较大,基本不存在重复风险)
|
||||
- [ ] 全程使用 C/C++(过程性语言),未使用Python等被禁止的语言
|
||||
|
||||
---
|
||||
+51
@@ -0,0 +1,51 @@
|
||||
# TODO List — 组员A
|
||||
|
||||
**负责模块**: 车次信息管理(顺序表)
|
||||
**核心数据结构**: 顺序表 `TrainList`
|
||||
**文件**: `src/train.h`、`src/train.cpp`
|
||||
**分支**: `feature/train`
|
||||
|
||||
---
|
||||
|
||||
## 一、顺序表基础操作
|
||||
|
||||
- [ ] `ListInsert` — 在位置 i 插入车次(检查越界/满/重复)
|
||||
- [ ] `ListDelete` — 删除位置 i 的车次(元素前移)
|
||||
- [ ] `ListUpdate` — 更新位置 i 的车次信息
|
||||
|
||||
## 二、查找算法(两种)
|
||||
|
||||
- [ ] `SeqSearch` — 顺序查找(按车次号逐个比较)
|
||||
- [ ] `BinSearch` — 二分查找(需先按 trainNo 排序)
|
||||
- [ ] `SearchByStation` — 按始发站/终点站模糊查找
|
||||
- [ ] `AdvancedSearch` — 多条件组合查询(站名 + 票价区间)
|
||||
|
||||
## 三、排序算法(三种)
|
||||
|
||||
- [ ] `InsertSort` — 直接插入排序(按车次号升序)
|
||||
- [ ] `QuickSort` — 快速排序(按票价排序)
|
||||
- [ ] `HeapSort` — 堆排序(按余票数排序)
|
||||
|
||||
## 四、文件读写
|
||||
|
||||
- [ ] `loadTrainsFromFile` — 从 `data/trains.csv` 读取车次数据
|
||||
- [ ] `saveTrainsToFile` — 将车次数据写回 `data/trains.csv`
|
||||
|
||||
## 五、管理员交互接口
|
||||
|
||||
- [ ] `adminAddTrain` — 交互式新增车次(录入各字段,校验合法性)
|
||||
- [ ] `adminDeleteTrain` — 按车次号查找并删除
|
||||
- [ ] `adminModifyTrain` — 查找后选择字段修改
|
||||
- [ ] `adminListTrains` — 遍历输出所有车次(格式化表格)
|
||||
- [ ] `adminSearchTrain` — 菜单选择查找方式(顺序/二分/模糊)
|
||||
- [ ] `adminSortTrains` — 菜单选择排序方式(票价快排 / 余票堆排)
|
||||
- [ ] `adminShowStatistics` — 调用 hash 模块统计函数展示
|
||||
|
||||
## 六、乘客交互接口
|
||||
|
||||
- [ ] `passengerSearchTrain` — 乘客查车次(按站名/时间/票价筛选)
|
||||
|
||||
---
|
||||
|
||||
> **依赖关系**: 先完成基础操作(增删改)和文件读写 → 再做查找 → 再做排序 → 最后做交互接口
|
||||
> **验收标准**: 管理员能完成车次增删改查全流程,排序结果正确,数据重启后不丢失
|
||||
+63
@@ -0,0 +1,63 @@
|
||||
# TODO List — 组员B
|
||||
|
||||
**负责模块**: 订单管理 + 撤销栈
|
||||
**核心数据结构**: 候补队列 `WaitQueue`(循环队列)、撤销栈 `OpStack`(顺序栈)
|
||||
**文件**: `src/order.h`、`src/order.cpp`、`src/stack.h`、`src/stack.cpp`
|
||||
**分支**: `feature/order`
|
||||
|
||||
---
|
||||
|
||||
## 一、候补队列(循环队列)
|
||||
|
||||
- [ ] `InitQueue` — 初始化队列(front = rear = count = 0)
|
||||
- [ ] `EnQueue` — 候补入队(循环队列,检查队满)
|
||||
- [ ] `DeQueue` — 候补转正出票(循环队列,检查队空)
|
||||
- [ ] `QueueEmpty` — 判空
|
||||
- [ ] `QueueFull` — 判满
|
||||
|
||||
## 二、订单操作
|
||||
|
||||
- [ ] `GenerateOrderId` — 生成 O00001 格式自增订单号
|
||||
- [ ] `BuyTicket` — 购票核心逻辑
|
||||
- 查找车次 → 判断余票
|
||||
- 有余票:`remainSeats--`,生成订单,`Push` 到撤销栈
|
||||
- 无余票:询问是否进入候补队列 → `EnQueue`
|
||||
- [ ] `RefundTicket` — 退票核心逻辑
|
||||
- 订单状态改为 `REFUNDED`,车次 `remainSeats++`
|
||||
- 检查候补队列是否非空 → 自动 `DeQueue` 补票
|
||||
- `Push` 到撤销栈
|
||||
- [ ] `ChangeTicket` — 改签核心逻辑
|
||||
- 退原票 + 购新票,更新订单车次号和座位号
|
||||
- `Push` 到撤销栈
|
||||
- [ ] `SearchOrdersByIdCard` — 按身份证号查询订单(遍历数组)
|
||||
- [ ] `SearchOrderById` — 按订单号精确查找
|
||||
|
||||
## 三、文件读写
|
||||
|
||||
- [ ] `loadOrdersFromFile` — 从 `data/orders.csv` 读取订单数据
|
||||
- [ ] `saveOrdersToFile` — 将订单数据写回 `data/orders.csv`
|
||||
|
||||
## 四、撤销栈(顺序栈)
|
||||
|
||||
- [ ] `InitStack` — 初始化(top = -1)
|
||||
- [ ] `Push` — 入栈记录操作日志
|
||||
- [ ] `Pop` — 出栈获取最近操作
|
||||
- [ ] `StackEmpty` — 判空
|
||||
- [ ] `StackFull` — 判满
|
||||
- [ ] `ExecuteUndo` — 执行撤销
|
||||
- 购票 → 退票、退票 → 恢复购票、改签 → 改回原车次
|
||||
- 撤销操作本身不再次入栈
|
||||
|
||||
## 五、乘客交互接口
|
||||
|
||||
- [ ] `passengerBuyTicket` — 购票菜单交互(选择车次 → 输入姓名/身份证 → 确认购票)
|
||||
- [ ] `passengerRefundTicket` — 退票菜单交互(输入订单号 → 确认退票)
|
||||
- [ ] `passengerChangeTicket` — 改签菜单交互(输入订单号 + 新车次号 → 确认改签)
|
||||
- [ ] `passengerViewOrders` — 查看我的订单(输入身份证号 → 显示所有订单)
|
||||
- [ ] `passengerUndo` — 撤销菜单交互(显示最近操作 → 确认撤销 → `ExecuteUndo`)
|
||||
|
||||
---
|
||||
|
||||
> **依赖关系**: `order.cpp` 需要 `#include "train.h"`(操作余票)和 `#include "stack.h"`(记录操作)
|
||||
> **时序关键**: 购票扣减余票 / 退票释放余票 / 候补自动转正 这三个联动的正确性最重要
|
||||
> **验收标准**: 乘客能完成购票→退票→撤销→候补自动补票全流程,队列 FIFO 顺序正确
|
||||
+70
@@ -0,0 +1,70 @@
|
||||
# TODO List — 组员C
|
||||
|
||||
**负责模块**: 线路网络图 + 订单哈希查找与统计
|
||||
**核心数据结构**: 图 `StationGraph`(邻接表)、哈希表 `HashNode`(链地址法)
|
||||
**文件**: `src/graph.h`、`src/graph.cpp`、`src/hash.h`、`src/hash.cpp`
|
||||
**分支**: `feature/graph`
|
||||
|
||||
---
|
||||
|
||||
## 一、图基础操作(邻接表)
|
||||
|
||||
- [ ] `InitGraph` — 初始化图(`vertexCount = 0`,`firstEdge = nullptr`)
|
||||
- [ ] `AddVertex` — 添加站点顶点(检查重复 / 越界)
|
||||
- [ ] `AddEdge` — 添加线路边(无向图,需同时添加两条边)
|
||||
- [ ] `FindVertex` — 按 `stationId` 查找顶点下标
|
||||
|
||||
## 二、图遍历算法
|
||||
|
||||
- [ ] `DFS` — 深度优先遍历(递归实现)
|
||||
- 从 `startIdx` 出发,标记已访问,输出能到达的所有站点
|
||||
- [ ] `BFS` — 广度优先遍历(队列辅助)
|
||||
- 输出最少换乘次数的路径
|
||||
|
||||
## 三、最短路径算法(核心加分项)
|
||||
|
||||
- [ ] `Dijkstra` — Dijkstra 最短路径算法
|
||||
- 初始化 `dist[] = INF`,`visited[] = false`,`dist[src] = 0`
|
||||
- 循环选最小未访问顶点,遍历邻接表松弛
|
||||
- [ ] `PrintPath` — 递归回溯 path[] 数组打印路径
|
||||
- [ ] `RecommendTransfer` — 换乘推荐入口
|
||||
- 输入起点/终点站名 → 调用 Dijkstra → 输出换乘方案
|
||||
- 方案包含:经过站点、换乘次数、总时长/总票价
|
||||
|
||||
## 四、最小生成树(可选加分)
|
||||
|
||||
- [ ] `PrimMST` — Prim 算法,以最小总里程连通所有站点
|
||||
|
||||
## 五、站点文件读写
|
||||
|
||||
- [ ] `loadStationsFromFile` — 从 `data/stations.csv` 读取站点和边数据
|
||||
- 解析顶点行和邻接边(格式: `相邻站点(车次号:边权);...`)
|
||||
- 调用 `AddVertex` / `AddEdge` 构建图
|
||||
|
||||
## 六、哈希表操作(链地址法)
|
||||
|
||||
- [ ] `Hash` — 哈希函数(身份证号字符累加 % `HASH_SIZE`)
|
||||
- [ ] `InitHashTable` — 初始化所有桶为 `nullptr`
|
||||
- [ ] `HashInsert` — 插入订单(头插法)
|
||||
- [ ] `HashSearch` — 按身份证号查找订单
|
||||
- [ ] `HashSearchByOrderId` — 按订单号查找(遍历所有桶)
|
||||
- [ ] `HashDelete` — 从哈希表中删除订单
|
||||
- [ ] `DestroyHashTable` — 释放所有链表节点内存
|
||||
|
||||
## 七、统计功能
|
||||
|
||||
- [ ] `CountSalesByTrain` — 统计某车次已支付订单数
|
||||
- [ ] `CountTrafficByRoute` — 统计某线路(始发站-终点站)客流量
|
||||
- [ ] `CountRevenueByPeriod` — 统计某时间段总收入
|
||||
- [ ] `HotTrainRanking` — 热门车次排行(按销量降序,取前 N)
|
||||
|
||||
## 八、乘客交互接口
|
||||
|
||||
- [ ] `passengerFindTransfer` — 换乘查询菜单交互
|
||||
- 输入起点站名和终点站名 → 调用 `RecommendTransfer`
|
||||
|
||||
---
|
||||
|
||||
> **依赖关系**: `graph.cpp` 需 `#include <queue>`(BFS 辅助队列),`hash.cpp` 需 `#include "train.h"`(统计关联车次表)
|
||||
> **算法重点**: Dijkstra 是最大加分项,务必写清注释便于答辩
|
||||
> **验收标准**: 能正确构建线路图,DFS/BFS 遍历正确,Dijkstra 给出最优换乘方案,哈希查找快速定位,统计数据准确
|
||||
@@ -0,0 +1,11 @@
|
||||
订单号,车次号,乘客姓名,身份证号,座位号,购票时间,状态
|
||||
O00001,G101,张三,110101199001011234,01A,2026-06-20 08:00,已支付
|
||||
O00002,G101,李四,110102199102022345,02B,2026-06-20 08:15,已支付
|
||||
O00003,G301,王五,320101199203033456,03C,2026-06-20 09:00,已支付
|
||||
O00004,G401,赵六,440101199304044567,01A,2026-06-20 09:30,已支付
|
||||
O00005,G501,孙七,610101199405055678,05A,2026-06-20 10:00,已支付
|
||||
O00006,G101,周八,110103199506066789,03A,2026-06-21 07:30,已支付
|
||||
O00007,G201,吴九,420101199607077890,02A,2026-06-21 08:00,已退票
|
||||
O00008,G601,郑十,510101199708088901,01A,2026-06-21 09:00,已支付
|
||||
O00009,G101,冯十一,110104199809099012,04D,2026-06-22 06:30,已支付
|
||||
O00010,G701,陈十二,430101199910101023,01A,2026-06-22 07:45,候补中
|
||||
|
@@ -0,0 +1,19 @@
|
||||
站点编号,站点名称,相邻站点(车次号:边权)
|
||||
1,北京,2:553.0;3:862.0;5:520.0;9:515.0;17:360.0;21:309.0;31:54.5
|
||||
2,上海,1:553.0;6:145.0;11:73.0;33:39.5
|
||||
3,广州,1:862.0;7:74.5;27:314.0
|
||||
4,深圳,3:74.5;35:225.0
|
||||
5,武汉,1:520.0;13:164.0;25:130.0
|
||||
6,南京,2:145.0;15:117.5
|
||||
7,西安,9:515.0;23:174.5;29:263.0
|
||||
8,成都,11:154.0;29:263.0
|
||||
9,重庆,8:154.0
|
||||
10,长沙,13:164.0;27:314.0
|
||||
11,杭州,15:117.5;11:73.0
|
||||
12,沈阳,17:360.0
|
||||
13,郑州,21:309.0
|
||||
14,兰州,23:174.5
|
||||
15,合肥,25:130.0
|
||||
16,天津,31:54.5
|
||||
17,苏州,33:39.5
|
||||
18,厦门,35:225.0
|
||||
|
@@ -0,0 +1,39 @@
|
||||
车次号,始发站,终点站,出发时间,到达时间,票价,总票数,余票
|
||||
G101,北京,上海,06:00,10:28,553.0,800,800
|
||||
G102,上海,北京,07:00,11:28,553.0,800,800
|
||||
G103,北京,广州,08:00,16:00,862.0,600,600
|
||||
G104,广州,北京,09:00,17:00,862.0,600,600
|
||||
G201,北京,武汉,06:30,10:30,520.0,500,500
|
||||
G202,武汉,北京,07:30,11:30,520.0,500,500
|
||||
G301,上海,南京,08:00,09:15,145.0,400,400
|
||||
G302,南京,上海,09:30,10:45,145.0,400,400
|
||||
G401,广州,深圳,06:00,06:36,74.5,300,300
|
||||
G402,深圳,广州,07:00,07:36,74.5,300,300
|
||||
G501,北京,西安,08:00,12:30,515.0,450,450
|
||||
G502,西安,北京,09:00,13:30,515.0,450,450
|
||||
G601,成都,重庆,08:00,09:30,154.0,350,350
|
||||
G602,重庆,成都,10:00,11:30,154.0,350,350
|
||||
G701,武汉,长沙,07:00,08:15,164.0,300,300
|
||||
G702,长沙,武汉,08:30,09:45,164.0,300,300
|
||||
G801,南京,杭州,09:00,10:15,117.5,380,380
|
||||
G802,杭州,南京,10:30,11:45,117.5,380,380
|
||||
G901,北京,沈阳,07:00,10:00,360.0,350,350
|
||||
G902,沈阳,北京,08:00,11:00,360.0,350,350
|
||||
G1001,上海,杭州,06:00,06:50,73.0,400,400
|
||||
G1002,杭州,上海,07:00,07:50,73.0,400,400
|
||||
G1101,北京,郑州,08:00,10:30,309.0,300,300
|
||||
G1102,郑州,北京,11:00,13:30,309.0,300,300
|
||||
G1201,西安,兰州,07:30,10:00,174.5,250,250
|
||||
G1202,兰州,西安,10:30,13:00,174.5,250,250
|
||||
G1301,武汉,合肥,08:00,10:00,130.0,200,200
|
||||
G1302,合肥,武汉,10:30,12:30,130.0,200,200
|
||||
G1401,广州,长沙,09:00,11:30,314.0,300,300
|
||||
G1402,长沙,广州,12:00,14:30,314.0,300,300
|
||||
G1501,成都,西安,07:00,10:30,263.0,280,280
|
||||
G1502,西安,成都,11:00,14:30,263.0,280,280
|
||||
G1601,北京,天津,06:30,07:00,54.5,500,500
|
||||
G1602,天津,北京,07:30,08:00,54.5,500,500
|
||||
G1701,上海,苏州,08:00,08:25,39.5,450,450
|
||||
G1702,苏州,上海,08:50,09:15,39.5,450,450
|
||||
G1801,深圳,厦门,07:00,10:30,225.0,220,220
|
||||
G1802,厦门,深圳,11:00,14:30,225.0,220,220
|
||||
|
+106
@@ -0,0 +1,106 @@
|
||||
/**
|
||||
* common.h - 火车票务管理系统公共头文件
|
||||
* 定义所有模块共享的数据类型、常量、枚举
|
||||
* C++ 版本
|
||||
*/
|
||||
|
||||
#ifndef COMMON_H
|
||||
#define COMMON_H
|
||||
|
||||
#include <iostream>
|
||||
#include <iomanip>
|
||||
#include <fstream>
|
||||
#include <string>
|
||||
#include <cstring>
|
||||
#include <cstdlib>
|
||||
using namespace std;
|
||||
|
||||
/* ==================== 系统常量 ==================== */
|
||||
|
||||
constexpr int MAX_TRAINS = 100; // 最大车次数
|
||||
constexpr int MAX_ORDERS = 500; // 最大订单数
|
||||
constexpr int MAX_STATIONS = 50; // 最大站点数
|
||||
constexpr int MAX_QUEUE_SIZE = 100; // 候补队列最大长度
|
||||
constexpr int MAX_STACK_SIZE = 100; // 撤销栈最大深度
|
||||
|
||||
/* ==================== 枚举 ==================== */
|
||||
|
||||
// 订单状态
|
||||
enum class OrderStatus {
|
||||
PAID, // 已支付
|
||||
WAITING, // 候补中
|
||||
REFUNDED // 已退票
|
||||
};
|
||||
|
||||
// 用户角色
|
||||
enum class UserRole {
|
||||
ADMIN, // 管理员
|
||||
PASSENGER // 普通乘客
|
||||
};
|
||||
|
||||
// 操作类型(用于撤销栈)
|
||||
enum class OpType {
|
||||
BUY, // 购票
|
||||
REFUND, // 退票
|
||||
CHANGE // 改签
|
||||
};
|
||||
|
||||
/* ==================== 结构体定义 ==================== */
|
||||
|
||||
// --- 车次信息 ---
|
||||
struct TrainInfo {
|
||||
string trainNo; // 车次号(唯一,如 G1234)
|
||||
string startStation; // 始发站
|
||||
string endStation; // 终点站
|
||||
string departTime; // 出发时间
|
||||
string arriveTime; // 到达时间
|
||||
float price = 0.0f; // 票价
|
||||
int totalSeats = 0; // 总票数
|
||||
int remainSeats = 0; // 余票
|
||||
};
|
||||
|
||||
// --- 订单信息 ---
|
||||
struct OrderInfo {
|
||||
string orderId; // 订单号(唯一,如 O00001)
|
||||
string trainNo; // 关联车次号
|
||||
string passengerName; // 乘客姓名
|
||||
string idCard; // 身份证号
|
||||
int seatNo = 0; // 座位号
|
||||
string orderTime; // 购票时间
|
||||
OrderStatus status = OrderStatus::PAID; // 订单状态
|
||||
};
|
||||
|
||||
// --- 站点/线路信息 ---
|
||||
struct EdgeNode {
|
||||
int toStationId; // 相邻站点编号
|
||||
float weight; // 边权(时长或票价)
|
||||
EdgeNode* next = nullptr;// 下一条边
|
||||
};
|
||||
|
||||
struct VertexNode {
|
||||
int stationId; // 站点编号
|
||||
string stationName; // 站点名称
|
||||
EdgeNode* firstEdge = nullptr; // 邻接表头指针
|
||||
};
|
||||
|
||||
// --- 撤销操作日志 ---
|
||||
struct OperationLog {
|
||||
OpType type; // 操作类型
|
||||
string orderId; // 相关订单号
|
||||
string trainNo; // 相关车次号
|
||||
int seatNo = 0; // 座位号
|
||||
string idCard; // 乘客身份证号
|
||||
string timestamp; // 操作时间
|
||||
};
|
||||
|
||||
// --- 订单状态输出辅助 ---
|
||||
inline const char* OrderStatusStr(OrderStatus s) {
|
||||
switch (s) {
|
||||
case OrderStatus::PAID: return "已支付";
|
||||
case OrderStatus::WAITING: return "候补中";
|
||||
case OrderStatus::REFUNDED:return "已退票";
|
||||
default: return "未知";
|
||||
}
|
||||
}
|
||||
|
||||
#endif /* COMMON_H */
|
||||
+104
@@ -0,0 +1,104 @@
|
||||
/**
|
||||
* graph.cpp - 线路网络图模块实现(邻接表存储)
|
||||
* 负责人:组员C
|
||||
*
|
||||
* TODO: 组员C 请在此文件中实现所有声明的函数
|
||||
* C++ 版本
|
||||
*/
|
||||
|
||||
#include "graph.h"
|
||||
#include <queue> // BFS 可用 STL queue 辅助,或自己用数组模拟
|
||||
#include <climits> // INT_MAX
|
||||
|
||||
/* ==================== 全局变量 ==================== */
|
||||
|
||||
StationGraph stationGraph;
|
||||
|
||||
/* ==================== 图基础操作 ==================== */
|
||||
|
||||
void InitGraph(StationGraph& G) {
|
||||
// TODO: vertexCount = 0, edgeCount = 0
|
||||
// 遍历 vertices[],firstEdge = nullptr
|
||||
}
|
||||
|
||||
int AddVertex(StationGraph& G, int stationId, const string& stationName) {
|
||||
// TODO: 检查是否已存在、是否超过 MAX_STATIONS
|
||||
// 创建新顶点,vertexCount++
|
||||
return -1;
|
||||
}
|
||||
|
||||
bool AddEdge(StationGraph& G, int fromId, int toId, float weight) {
|
||||
// TODO: 无向图,需同时添加两条边
|
||||
// 1. 创建 EdgeNode{toId, weight} 插入 from 的邻接表头
|
||||
// 2. 创建 EdgeNode{fromId, weight} 插入 to 的邻接表头
|
||||
// edgeCount++
|
||||
return false;
|
||||
}
|
||||
|
||||
int FindVertex(const StationGraph& G, int stationId) {
|
||||
// TODO: 遍历 vertices[],按 stationId 查找下标
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* ==================== 图遍历算法 ==================== */
|
||||
|
||||
void DFS(const StationGraph& G, int startIdx, bool visited[]) {
|
||||
// TODO: 递归深度优先遍历
|
||||
// 1. 标记 visited[startIdx] = true,输出站点名
|
||||
// 2. 遍历该顶点的邻接表,对每个未访问的邻接点递归 DFS
|
||||
}
|
||||
|
||||
void BFS(const StationGraph& G, int startIdx) {
|
||||
// TODO: 广度优先遍历,输出最少换乘次数的路径
|
||||
// 用 queue<int> 辅助
|
||||
}
|
||||
|
||||
/* ==================== 最短路径算法 ==================== */
|
||||
|
||||
void Dijkstra(const StationGraph& G, int srcIdx,
|
||||
float dist[], int path[]) {
|
||||
// TODO: Dijkstra 最短路径算法
|
||||
// 1. 初始化 dist[] = INF, visited[] = false
|
||||
// 2. dist[src] = 0, path[src] = -1
|
||||
// 3. 循环 vertexCount 次:
|
||||
// a. 选未访问中 dist 最小的顶点 u
|
||||
// b. 标记 visited[u] = true
|
||||
// c. 遍历 u 的邻接表,松弛操作
|
||||
}
|
||||
|
||||
void PrintPath(const StationGraph& G, int path[], int destIdx) {
|
||||
// TODO: 递归回溯打印路径
|
||||
// if (path[destIdx] != -1) PrintPath(G, path, path[destIdx])
|
||||
// cout << G.vertices[destIdx].stationName
|
||||
}
|
||||
|
||||
void RecommendTransfer(const StationGraph& G,
|
||||
const string& startName, const string& endName) {
|
||||
// TODO:
|
||||
// 1. 按站名查找顶点下标
|
||||
// 2. 调用 Dijkstra
|
||||
// 3. 调用 PrintPath 输出换乘方案
|
||||
}
|
||||
|
||||
/* ==================== 最小生成树(可选加分) ==================== */
|
||||
|
||||
void PrimMST(const StationGraph& G) {
|
||||
// TODO: Prim 算法实现最小生成树
|
||||
}
|
||||
|
||||
/* ==================== 文件读写 ==================== */
|
||||
|
||||
int loadStationsFromFile(const string& filename) {
|
||||
// TODO: 用 ifstream 读取 CSV
|
||||
// 解析站点顶点和邻接边,调用 AddVertex / AddEdge 构建图
|
||||
// 边的格式: "相邻站点(车次号:边权)",多条边用 ; 分隔
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* ==================== 乘客接口 ==================== */
|
||||
|
||||
void passengerFindTransfer() {
|
||||
// TODO:
|
||||
// 1. 输入起点站名和终点站名
|
||||
// 2. 调用 RecommendTransfer
|
||||
}
|
||||
+66
@@ -0,0 +1,66 @@
|
||||
/**
|
||||
* graph.h - 线路网络图模块(邻接表存储)
|
||||
* 负责人:组员C
|
||||
*
|
||||
* 核心数据结构:图 StationGraph(邻接表)
|
||||
* 算法:DFS 深度优先遍历、BFS 广度优先遍历、Dijkstra 最短路径
|
||||
* C++ 版本
|
||||
*/
|
||||
|
||||
#ifndef GRAPH_H
|
||||
#define GRAPH_H
|
||||
|
||||
#include "common.h"
|
||||
|
||||
/* ==================== 图结构 ==================== */
|
||||
|
||||
struct StationGraph {
|
||||
VertexNode vertices[MAX_STATIONS]; // 顶点数组
|
||||
int vertexCount = 0; // 当前顶点数
|
||||
int edgeCount = 0; // 边数
|
||||
};
|
||||
|
||||
/* ==================== 图基础操作 ==================== */
|
||||
|
||||
void InitGraph(StationGraph& G);
|
||||
int AddVertex(StationGraph& G, int stationId, const string& stationName);
|
||||
bool AddEdge(StationGraph& G, int fromId, int toId, float weight);
|
||||
int FindVertex(const StationGraph& G, int stationId);
|
||||
|
||||
/* ==================== 图遍历算法 ==================== */
|
||||
|
||||
// 深度优先遍历(DFS)—— 递归实现
|
||||
void DFS(const StationGraph& G, int startIdx, bool visited[]);
|
||||
|
||||
// 广度优先遍历(BFS)—— 队列实现,找最少换乘次数路径
|
||||
void BFS(const StationGraph& G, int startIdx);
|
||||
|
||||
/* ==================== 最短路径算法 ==================== */
|
||||
|
||||
// Dijkstra 最短路径 —— 最优换乘推荐
|
||||
// dist[]: 从 src 到各站点的最短距离
|
||||
// path[]: 前驱节点数组,用于回溯路径
|
||||
void Dijkstra(const StationGraph& G, int srcIdx,
|
||||
float dist[], int path[]);
|
||||
|
||||
// 打印路径(回溯 path[] 数组)
|
||||
void PrintPath(const StationGraph& G, int path[], int destIdx);
|
||||
|
||||
// 推荐换乘方案(用户接口:输入起点/终点站名,输出最优方案)
|
||||
void RecommendTransfer(const StationGraph& G,
|
||||
const string& startName, const string& endName);
|
||||
|
||||
/* ==================== 最小生成树(可选加分) ==================== */
|
||||
|
||||
// Prim 算法 —— 最小总里程连通所有站点
|
||||
void PrimMST(const StationGraph& G);
|
||||
|
||||
/* ==================== 文件读写 ==================== */
|
||||
|
||||
int loadStationsFromFile(const string& filename);
|
||||
|
||||
/* ==================== 乘客接口 ==================== */
|
||||
|
||||
void passengerFindTransfer();
|
||||
|
||||
#endif /* GRAPH_H */
|
||||
@@ -0,0 +1,82 @@
|
||||
/**
|
||||
* hash.cpp - 订单哈希查找与销售统计模块实现
|
||||
* 负责人:组员C
|
||||
*
|
||||
* TODO: 组员C 请在此文件中实现所有声明的函数
|
||||
* C++ 版本
|
||||
*/
|
||||
|
||||
#include "hash.h"
|
||||
#include "train.h" // 需要 trainList 做统计关联
|
||||
|
||||
/* ==================== 全局变量 ==================== */
|
||||
|
||||
HashNode* orderHashTable[HASH_SIZE] = {nullptr};
|
||||
|
||||
/* ==================== 哈希表操作 ==================== */
|
||||
|
||||
int Hash(const string& idCard) {
|
||||
// TODO: 哈希函数
|
||||
// 方案1:取身份证后6位 % HASH_SIZE
|
||||
// 方案2:逐字符累加 ASCII 值 % HASH_SIZE
|
||||
return 0;
|
||||
}
|
||||
|
||||
bool HashInsert(HashNode* hashTable[], const OrderInfo& order) {
|
||||
// TODO: 链地址法插入
|
||||
// 1. 计算 hash = Hash(order.idCard)
|
||||
// 2. 创建新 HashNode,头插法插入 hashTable[hash]
|
||||
return false;
|
||||
}
|
||||
|
||||
const HashNode* HashSearch(HashNode* const hashTable[], const string& idCard) {
|
||||
// TODO: 哈希查找
|
||||
// 1. 计算 hash = Hash(idCard)
|
||||
// 2. 遍历 hashTable[hash] 链表,匹配 idCard
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
const OrderInfo* HashSearchByOrderId(HashNode* const hashTable[],
|
||||
const string& orderId) {
|
||||
// TODO: 按订单号查找(需遍历所有桶)
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
bool HashDelete(HashNode* hashTable[], const string& orderId) {
|
||||
// TODO: 哈希删除
|
||||
// 遍历链表找到目标节点,从链表中移除并 delete
|
||||
return false;
|
||||
}
|
||||
|
||||
void InitHashTable(HashNode* hashTable[]) {
|
||||
// TODO: 所有桶置为 nullptr
|
||||
}
|
||||
|
||||
void DestroyHashTable(HashNode* hashTable[]) {
|
||||
// TODO: 遍历每个桶,释放链表所有节点
|
||||
}
|
||||
|
||||
/* ==================== 统计功能 ==================== */
|
||||
|
||||
int CountSalesByTrain(const string& trainNo) {
|
||||
// TODO: 统计某车次已支付订单数
|
||||
// 遍历所有桶的链表,匹配 trainNo 且 status == PAID
|
||||
return 0;
|
||||
}
|
||||
|
||||
int CountTrafficByRoute(const string& startStation, const string& endStation) {
|
||||
// TODO: 统计某线路客流量
|
||||
// 需要关联车次表(trainList)判断始发-终点站
|
||||
return 0;
|
||||
}
|
||||
|
||||
float CountRevenueByPeriod(const string& startTime, const string& endTime) {
|
||||
// TODO: 统计某时间段总收入
|
||||
// 匹配 orderTime 在区间内的已支付订单,累加对应车次的票价
|
||||
return 0.0f;
|
||||
}
|
||||
|
||||
void HotTrainRanking(TrainInfo ranking[], int topN) {
|
||||
// TODO: 热门车次排行
|
||||
// 统计每个车次销售量 → 排序 → 取前 topN
|
||||
}
|
||||
+54
@@ -0,0 +1,54 @@
|
||||
/**
|
||||
* hash.h - 订单哈希查找与销售统计模块
|
||||
* 负责人:组员C
|
||||
*
|
||||
* 核心数据结构:哈希表(链地址法解决冲突)
|
||||
* 功能:按身份证号快速查找订单、销售统计
|
||||
* C++ 版本
|
||||
*/
|
||||
|
||||
#ifndef HASH_H
|
||||
#define HASH_H
|
||||
|
||||
#include "common.h"
|
||||
|
||||
/* ==================== 哈希表结构 ==================== */
|
||||
|
||||
constexpr int HASH_SIZE = 101; // 哈希表大小(素数,减少冲突)
|
||||
|
||||
// 哈希表节点(链表)
|
||||
struct HashNode {
|
||||
OrderInfo order; // 订单数据
|
||||
HashNode* next = nullptr; // 链表下一节点
|
||||
};
|
||||
|
||||
/* ==================== 哈希表操作 ==================== */
|
||||
|
||||
// 哈希函数(字符累加法 + 除留余数)
|
||||
int Hash(const string& idCard);
|
||||
|
||||
// 插入订单到哈希表
|
||||
bool HashInsert(HashNode* hashTable[], const OrderInfo& order);
|
||||
|
||||
// 按身份证号查找订单
|
||||
const HashNode* HashSearch(HashNode* const hashTable[], const string& idCard);
|
||||
|
||||
// 按订单号查找(顺序扫描哈希表)
|
||||
const OrderInfo* HashSearchByOrderId(HashNode* const hashTable[],
|
||||
const string& orderId);
|
||||
|
||||
// 删除哈希表中的订单
|
||||
bool HashDelete(HashNode* hashTable[], const string& orderId);
|
||||
|
||||
// 初始化 / 销毁哈希表
|
||||
void InitHashTable(HashNode* hashTable[]);
|
||||
void DestroyHashTable(HashNode* hashTable[]);
|
||||
|
||||
/* ==================== 统计功能 ==================== */
|
||||
|
||||
int CountSalesByTrain(const string& trainNo);
|
||||
int CountTrafficByRoute(const string& startStation, const string& endStation);
|
||||
float CountRevenueByPeriod(const string& startTime, const string& endTime);
|
||||
void HotTrainRanking(TrainInfo ranking[], int topN);
|
||||
|
||||
#endif /* HASH_H */
|
||||
+146
@@ -0,0 +1,146 @@
|
||||
/**
|
||||
* main.cpp - 火车票务管理系统主程序
|
||||
* 负责菜单调度、登录验证、模块整合
|
||||
* C++ 版本
|
||||
*/
|
||||
|
||||
#include "common.h"
|
||||
#include "train.h"
|
||||
#include "order.h"
|
||||
#include "graph.h"
|
||||
#include "hash.h"
|
||||
#include "stack.h"
|
||||
|
||||
/* ==================== 全局数据 ==================== */
|
||||
|
||||
TrainList trainList; // 车次顺序表
|
||||
OrderInfo orderArray[MAX_ORDERS]; // 订单数组
|
||||
int orderCount = 0; // 订单总数
|
||||
StationGraph stationGraph; // 站点图
|
||||
WaitQueue* waitQueues[MAX_TRAINS] = {nullptr}; // 候补队列指针数组
|
||||
OpStack undoStack; // 撤销栈
|
||||
|
||||
/* ==================== 文件路径 ==================== */
|
||||
|
||||
const string TRAINS_CSV = "../data/trains.csv";
|
||||
const string ORDERS_CSV = "../data/orders.csv";
|
||||
const string STATIONS_CSV = "../data/stations.csv";
|
||||
|
||||
/* ==================== 菜单函数声明 ==================== */
|
||||
|
||||
void showMainMenu();
|
||||
void showAdminMenu();
|
||||
void showPassengerMenu();
|
||||
|
||||
/* ==================== 主函数 ==================== */
|
||||
|
||||
int main() {
|
||||
cout << "========================================" << endl;
|
||||
cout << " 火车票务管理系统 v1.0 (C++)" << endl;
|
||||
cout << "========================================" << endl << endl;
|
||||
|
||||
// 加载数据
|
||||
cout << "正在加载数据..." << endl;
|
||||
loadTrainsFromFile(TRAINS_CSV);
|
||||
loadOrdersFromFile(ORDERS_CSV);
|
||||
loadStationsFromFile(STATIONS_CSV);
|
||||
cout << "数据加载完成!" << endl << endl;
|
||||
|
||||
// 登录选择
|
||||
int role;
|
||||
while (true) {
|
||||
cout << "请选择登录角色:" << endl;
|
||||
cout << " 1. 管理员" << endl;
|
||||
cout << " 2. 普通乘客" << endl;
|
||||
cout << " 0. 退出系统" << endl;
|
||||
cout << "请输入选项:";
|
||||
cin >> role;
|
||||
cin.ignore(); // 吃掉换行符
|
||||
|
||||
if (role == 0) {
|
||||
cout << endl << "正在保存数据..." << endl;
|
||||
saveTrainsToFile(TRAINS_CSV);
|
||||
saveOrdersToFile(ORDERS_CSV);
|
||||
cout << "数据已保存,感谢使用!" << endl;
|
||||
break;
|
||||
} else if (role == 1) {
|
||||
showAdminMenu();
|
||||
} else if (role == 2) {
|
||||
showPassengerMenu();
|
||||
} else {
|
||||
cout << "输入无效,请重新选择!" << endl << endl;
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* ==================== 管理员菜单 ==================== */
|
||||
|
||||
void showAdminMenu() {
|
||||
int choice;
|
||||
|
||||
while (true) {
|
||||
cout << endl;
|
||||
cout << "========== 管理员菜单 ==========" << endl;
|
||||
cout << " 1. 新增车次" << endl;
|
||||
cout << " 2. 删除/停运车次" << endl;
|
||||
cout << " 3. 修改车次信息" << endl;
|
||||
cout << " 4. 查看车次列表" << endl;
|
||||
cout << " 5. 查询车次(按车次号)" << endl;
|
||||
cout << " 6. 排序车次(按票价/余票/时间)" << endl;
|
||||
cout << " 7. 查看销售统计" << endl;
|
||||
cout << " 0. 返回上级菜单" << endl;
|
||||
cout << "请输入选项:";
|
||||
cin >> choice;
|
||||
cin.ignore();
|
||||
|
||||
switch (choice) {
|
||||
case 0: return;
|
||||
case 1: adminAddTrain(); break;
|
||||
case 2: adminDeleteTrain(); break;
|
||||
case 3: adminModifyTrain(); break;
|
||||
case 4: adminListTrains(); break;
|
||||
case 5: adminSearchTrain(); break;
|
||||
case 6: adminSortTrains(); break;
|
||||
case 7: adminShowStatistics(); break;
|
||||
default:
|
||||
cout << "输入无效,请重新选择!" << endl;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* ==================== 乘客菜单 ==================== */
|
||||
|
||||
void showPassengerMenu() {
|
||||
int choice;
|
||||
|
||||
while (true) {
|
||||
cout << endl;
|
||||
cout << "========== 乘客菜单 ==========" << endl;
|
||||
cout << " 1. 查询车次" << endl;
|
||||
cout << " 2. 购票" << endl;
|
||||
cout << " 3. 退票" << endl;
|
||||
cout << " 4. 改签" << endl;
|
||||
cout << " 5. 查看我的订单" << endl;
|
||||
cout << " 6. 查询换乘方案" << endl;
|
||||
cout << " 7. 撤销上一步操作" << endl;
|
||||
cout << " 0. 返回上级菜单" << endl;
|
||||
cout << "请输入选项:";
|
||||
cin >> choice;
|
||||
cin.ignore();
|
||||
|
||||
switch (choice) {
|
||||
case 0: return;
|
||||
case 1: passengerSearchTrain(); break;
|
||||
case 2: passengerBuyTicket(); break;
|
||||
case 3: passengerRefundTicket(); break;
|
||||
case 4: passengerChangeTicket(); break;
|
||||
case 5: passengerViewOrders(); break;
|
||||
case 6: passengerFindTransfer(); break;
|
||||
case 7: passengerUndo(); break;
|
||||
default:
|
||||
cout << "输入无效,请重新选择!" << endl;
|
||||
}
|
||||
}
|
||||
}
|
||||
+125
@@ -0,0 +1,125 @@
|
||||
/**
|
||||
* order.cpp - 购票/退票/改签模块实现
|
||||
* 负责人:组员B
|
||||
*
|
||||
* TODO: 组员B 请在此文件中实现所有声明的函数
|
||||
* C++ 版本
|
||||
*/
|
||||
|
||||
#include "order.h"
|
||||
#include "train.h" // 需要操作车次余票
|
||||
#include "stack.h" // 需要记录操作日志到撤销栈
|
||||
|
||||
/* ==================== 全局变量 ==================== */
|
||||
|
||||
OrderInfo orderArray[MAX_ORDERS];
|
||||
int orderCount = 0;
|
||||
WaitQueue* waitQueues[MAX_TRAINS] = {nullptr};
|
||||
|
||||
/* ==================== 队列操作 ==================== */
|
||||
|
||||
void InitQueue(WaitQueue& Q) {
|
||||
// TODO: 初始化 front = rear = count = 0
|
||||
}
|
||||
|
||||
bool EnQueue(WaitQueue& Q, const OrderInfo& e) {
|
||||
// TODO: 候补入队(循环队列)
|
||||
// 检查队满 → 返回 false
|
||||
// 将 e 存入 data[rear],rear = (rear+1) % MAX_QUEUE_SIZE,count++
|
||||
return false;
|
||||
}
|
||||
|
||||
bool DeQueue(WaitQueue& Q, OrderInfo& e) {
|
||||
// TODO: 候补转正出票(循环队列)
|
||||
// 检查队空 → 返回 false
|
||||
// 取出 data[front],front = (front+1) % MAX_QUEUE_SIZE,count--
|
||||
return false;
|
||||
}
|
||||
|
||||
bool QueueEmpty(const WaitQueue& Q) {
|
||||
// TODO: count == 0
|
||||
return true;
|
||||
}
|
||||
|
||||
bool QueueFull(const WaitQueue& Q) {
|
||||
// TODO: count == MAX_QUEUE_SIZE
|
||||
return false;
|
||||
}
|
||||
|
||||
/* ==================== 订单操作 ==================== */
|
||||
|
||||
string GenerateOrderId() {
|
||||
// TODO: 生成 O00001 格式的自增订单号
|
||||
// 用静态变量记录已生成的序号
|
||||
return "O00000";
|
||||
}
|
||||
|
||||
int BuyTicket(const OrderInfo& order) {
|
||||
// TODO: 购票逻辑
|
||||
// 1. 查出对应车次(trainList 中查找)
|
||||
// 2. 判断 remainSeats > 0:
|
||||
// a. 有余票 → remainSeats--,生成订单,存入 orderArray,
|
||||
// 将操作 Push 到 undoStack
|
||||
// b. 无余票 → 询问是否进入候补队列 → EnQueue
|
||||
return -1;
|
||||
}
|
||||
|
||||
int RefundTicket(const string& orderId) {
|
||||
// TODO: 退票逻辑
|
||||
// 1. 找到订单,status 改为 REFUNDED
|
||||
// 2. 对应车次 remainSeats++
|
||||
// 3. 检查该车次候补队列是否非空:
|
||||
// a. DeQueue → 自动为候补乘客出票,remainSeats--
|
||||
// 4. 将操作 Push 到 undoStack
|
||||
return -1;
|
||||
}
|
||||
|
||||
int ChangeTicket(const string& orderId, const string& newTrainNo) {
|
||||
// TODO: 改签逻辑
|
||||
// 1. 原订单退票(释放原车次余票)
|
||||
// 2. 在新车次购票(扣减新车次余票)
|
||||
// 3. 更新订单的 trainNo 和 seatNo
|
||||
// 4. Push 到 undoStack
|
||||
return -1;
|
||||
}
|
||||
|
||||
int SearchOrdersByIdCard(const string& idCard,
|
||||
OrderInfo results[], int maxResults) {
|
||||
// TODO: 遍历 orderArray,按 idCard 匹配
|
||||
return 0;
|
||||
}
|
||||
|
||||
const OrderInfo* SearchOrderById(const string& orderId) {
|
||||
// TODO: 遍历 orderArray,按 orderId 匹配,返回指针
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
/* ==================== 文件读写 ==================== */
|
||||
|
||||
int loadOrdersFromFile(const string& filename) {
|
||||
// TODO: 用 ifstream 读取 CSV,填充 orderArray
|
||||
return 0;
|
||||
}
|
||||
|
||||
int saveOrdersToFile(const string& filename) {
|
||||
// TODO: 用 ofstream 写回 CSV
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* ==================== 乘客接口 ==================== */
|
||||
|
||||
void passengerBuyTicket() {
|
||||
// TODO: 交互:选择车次 → 输入姓名/身份证 → 生成订单
|
||||
}
|
||||
|
||||
void passengerRefundTicket() {
|
||||
// TODO: 交互:输入订单号 → 执行退票
|
||||
}
|
||||
|
||||
void passengerChangeTicket() {
|
||||
// TODO: 交互:输入订单号 + 新车次号 → 执行改签
|
||||
}
|
||||
|
||||
void passengerViewOrders() {
|
||||
// TODO: 交互:输入身份证号 → 显示该乘客所有订单
|
||||
}
|
||||
+64
@@ -0,0 +1,64 @@
|
||||
/**
|
||||
* order.h - 购票/退票/改签模块(订单管理)
|
||||
* 负责人:组员B
|
||||
*
|
||||
* 核心数据结构:候补队列 WaitQueue(队列)
|
||||
* C++ 版本
|
||||
*/
|
||||
|
||||
#ifndef ORDER_H
|
||||
#define ORDER_H
|
||||
|
||||
#include "common.h"
|
||||
|
||||
/* ==================== 候补队列结构 ==================== */
|
||||
|
||||
struct WaitQueue {
|
||||
OrderInfo data[MAX_QUEUE_SIZE];
|
||||
int front = 0; // 队首下标
|
||||
int rear = 0; // 队尾下标
|
||||
int count = 0; // 当前队列长度
|
||||
};
|
||||
|
||||
/* ==================== 队列操作 ==================== */
|
||||
|
||||
void InitQueue(WaitQueue& Q);
|
||||
bool EnQueue(WaitQueue& Q, const OrderInfo& e);
|
||||
bool DeQueue(WaitQueue& Q, OrderInfo& e);
|
||||
bool QueueEmpty(const WaitQueue& Q);
|
||||
bool QueueFull(const WaitQueue& Q);
|
||||
|
||||
/* ==================== 订单操作 ==================== */
|
||||
|
||||
// 生成订单号(自增格式化)
|
||||
string GenerateOrderId();
|
||||
|
||||
// 购票
|
||||
int BuyTicket(const OrderInfo& order);
|
||||
|
||||
// 退票(若有候补自动转正)
|
||||
int RefundTicket(const string& orderId);
|
||||
|
||||
// 改签
|
||||
int ChangeTicket(const string& orderId, const string& newTrainNo);
|
||||
|
||||
// 按身份证号查询订单,返回匹配数量
|
||||
int SearchOrdersByIdCard(const string& idCard,
|
||||
OrderInfo results[], int maxResults);
|
||||
|
||||
// 按订单号查询
|
||||
const OrderInfo* SearchOrderById(const string& orderId);
|
||||
|
||||
/* ==================== 文件读写 ==================== */
|
||||
|
||||
int loadOrdersFromFile(const string& filename);
|
||||
int saveOrdersToFile(const string& filename);
|
||||
|
||||
/* ==================== 乘客接口 ==================== */
|
||||
|
||||
void passengerBuyTicket();
|
||||
void passengerRefundTicket();
|
||||
void passengerChangeTicket();
|
||||
void passengerViewOrders();
|
||||
|
||||
#endif /* ORDER_H */
|
||||
@@ -0,0 +1,64 @@
|
||||
/**
|
||||
* stack.cpp - 操作撤销栈模块实现
|
||||
* 负责人:组员B
|
||||
*
|
||||
* TODO: 组员B 请在此文件中实现所有声明的函数
|
||||
* C++ 版本
|
||||
*/
|
||||
|
||||
#include "stack.h"
|
||||
#include "order.h" // 需要调用 RefundTicket / BuyTicket 执行逆操作
|
||||
|
||||
/* ==================== 全局变量 ==================== */
|
||||
|
||||
OpStack undoStack;
|
||||
|
||||
/* ==================== 栈操作 ==================== */
|
||||
|
||||
void InitStack(OpStack& S) {
|
||||
// TODO: top = -1
|
||||
}
|
||||
|
||||
bool Push(OpStack& S, const OperationLog& op) {
|
||||
// TODO: 检查栈满 → false
|
||||
// top++,data[top] = op
|
||||
return false;
|
||||
}
|
||||
|
||||
bool Pop(OpStack& S, OperationLog& op) {
|
||||
// TODO: 检查栈空 → false
|
||||
// op = data[top],top--
|
||||
return false;
|
||||
}
|
||||
|
||||
bool StackEmpty(const OpStack& S) {
|
||||
// TODO: top == -1
|
||||
return true;
|
||||
}
|
||||
|
||||
bool StackFull(const OpStack& S) {
|
||||
// TODO: top == MAX_STACK_SIZE - 1
|
||||
return false;
|
||||
}
|
||||
|
||||
/* ==================== 撤销功能 ==================== */
|
||||
|
||||
int ExecuteUndo(OpStack& S) {
|
||||
// TODO:
|
||||
// 1. Pop 出一个 OperationLog
|
||||
// 2. 根据其 type 执行逆操作:
|
||||
// BUY → 调用 RefundTicket
|
||||
// REFUND → 调用 BuyTicket(恢复原订单)
|
||||
// CHANGE → 改回原车次
|
||||
// 3. 注意:撤销操作本身不再次入栈
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* ==================== 乘客接口 ==================== */
|
||||
|
||||
void passengerUndo() {
|
||||
// TODO:
|
||||
// 1. 判断 undoStack 是否为空
|
||||
// 2. 显示最近操作信息,询问是否确认撤销
|
||||
// 3. 执行 ExecuteUndo
|
||||
}
|
||||
+40
@@ -0,0 +1,40 @@
|
||||
/**
|
||||
* stack.h - 操作撤销栈模块
|
||||
* 负责人:组员B
|
||||
*
|
||||
* 核心数据结构:顺序栈 OpStack
|
||||
* 功能:记录最近操作,支持撤销购票/退票/改签
|
||||
* C++ 版本
|
||||
*/
|
||||
|
||||
#ifndef STACK_H
|
||||
#define STACK_H
|
||||
|
||||
#include "common.h"
|
||||
|
||||
/* ==================== 栈结构 ==================== */
|
||||
|
||||
struct OpStack {
|
||||
OperationLog data[MAX_STACK_SIZE];
|
||||
int top = -1; // 栈顶下标,-1 表示栈空
|
||||
};
|
||||
|
||||
/* ==================== 栈操作 ==================== */
|
||||
|
||||
void InitStack(OpStack& S);
|
||||
bool Push(OpStack& S, const OperationLog& op);
|
||||
bool Pop(OpStack& S, OperationLog& op);
|
||||
bool StackEmpty(const OpStack& S);
|
||||
bool StackFull(const OpStack& S);
|
||||
|
||||
/* ==================== 撤销功能 ==================== */
|
||||
|
||||
// 执行撤销(调用对应的逆操作)
|
||||
// 购票→退票,退票→购票,改签→改回原车次
|
||||
int ExecuteUndo(OpStack& S);
|
||||
|
||||
/* ==================== 乘客接口 ==================== */
|
||||
|
||||
void passengerUndo();
|
||||
|
||||
#endif /* STACK_H */
|
||||
+129
@@ -0,0 +1,129 @@
|
||||
/**
|
||||
* train.cpp - 车次信息管理模块实现(顺序表)
|
||||
* 负责人:组员A
|
||||
*
|
||||
* TODO: 组员A 请在此文件中实现所有声明的函数
|
||||
* C++ 版本
|
||||
*/
|
||||
|
||||
#include "train.h"
|
||||
|
||||
/* ==================== 全局变量 ==================== */
|
||||
|
||||
TrainList trainList;
|
||||
|
||||
/* ==================== 基础操作 ==================== */
|
||||
|
||||
bool ListInsert(TrainList& L, int i, const TrainInfo& e) {
|
||||
// TODO: 在位置 i 插入车次
|
||||
// 检查合法性(i 范围、表是否满、车次号是否重复)
|
||||
// 将位置 i 及之后元素后移一位
|
||||
// 插入新元素,length++
|
||||
return false;
|
||||
}
|
||||
|
||||
bool ListDelete(TrainList& L, int i, TrainInfo& e) {
|
||||
// TODO: 删除位置 i 的车次,结果存入 e
|
||||
// 将位置 i+1 及之后元素前移一位
|
||||
// length--
|
||||
return false;
|
||||
}
|
||||
|
||||
bool ListUpdate(TrainList& L, int i, const TrainInfo& e) {
|
||||
// TODO: 更新位置 i 的车次信息
|
||||
return false;
|
||||
}
|
||||
|
||||
/* ==================== 查找算法 ==================== */
|
||||
|
||||
int SeqSearch(const TrainList& L, const string& trainNo) {
|
||||
// TODO: 顺序查找,逐个比较 trainNo
|
||||
// 找到返回下标,未找到返回 -1
|
||||
return -1;
|
||||
}
|
||||
|
||||
int BinSearch(const TrainList& L, const string& trainNo) {
|
||||
// TODO: 二分查找(前提:顺序表按 trainNo 有序)
|
||||
// 使用 InsertSort 排序后再查找
|
||||
return -1;
|
||||
}
|
||||
|
||||
int SearchByStation(const TrainList& L, const string& keyword,
|
||||
TrainInfo results[], int maxResults) {
|
||||
// TODO: 按站名模糊查找(在 startStation / endStation 中匹配)
|
||||
return 0;
|
||||
}
|
||||
|
||||
int AdvancedSearch(const TrainList& L, const string& startStation,
|
||||
const string& endStation, float minPrice,
|
||||
float maxPrice, TrainInfo results[], int maxResults) {
|
||||
// TODO: 多条件组合查询
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* ==================== 排序算法 ==================== */
|
||||
|
||||
void InsertSort(TrainList& L) {
|
||||
// TODO: 直接插入排序(按车次号升序)
|
||||
// 将 trainNo 字符串比较,从小到大排列
|
||||
}
|
||||
|
||||
void QuickSort(TrainList& L, int low, int high) {
|
||||
// TODO: 快速排序(按票价排序)
|
||||
}
|
||||
|
||||
void HeapSort(TrainList& L) {
|
||||
// TODO: 堆排序(按余票数排序)
|
||||
// 构建大顶堆 / 小顶堆
|
||||
}
|
||||
|
||||
/* ==================== 文件读写 ==================== */
|
||||
|
||||
int loadTrainsFromFile(const string& filename) {
|
||||
// TODO: 用 ifstream 读取 CSV 文件
|
||||
// 跳过标题行,逐行解析字段填充 TrainInfo
|
||||
// 存入 trainList
|
||||
return 0;
|
||||
}
|
||||
|
||||
int saveTrainsToFile(const string& filename) {
|
||||
// TODO: 用 ofstream 写回 CSV 文件
|
||||
// 先写标题行,再逐行输出 trainList 数据
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* ==================== 管理员接口 ==================== */
|
||||
|
||||
void adminAddTrain() {
|
||||
// TODO: 交互式录入新 TrainInfo,调用 ListInsert
|
||||
}
|
||||
|
||||
void adminDeleteTrain() {
|
||||
// TODO: 输入车次号,SeqSearch 找到后调用 ListDelete
|
||||
}
|
||||
|
||||
void adminModifyTrain() {
|
||||
// TODO: 查找后修改字段,调用 ListUpdate
|
||||
}
|
||||
|
||||
void adminListTrains() {
|
||||
// TODO: 遍历 trainList 输出所有车次
|
||||
}
|
||||
|
||||
void adminSearchTrain() {
|
||||
// TODO: 提示选择查找方式(顺序/二分/站名模糊)
|
||||
}
|
||||
|
||||
void adminSortTrains() {
|
||||
// TODO: 提示选择排序方式(票价快排 / 余票堆排)
|
||||
}
|
||||
|
||||
void adminShowStatistics() {
|
||||
// TODO: 调用 hash 模块的统计函数展示
|
||||
}
|
||||
|
||||
/* ==================== 乘客接口 ==================== */
|
||||
|
||||
void passengerSearchTrain() {
|
||||
// TODO: 乘客查车次(支持按站名、时间、票价区间筛选)
|
||||
}
|
||||
+80
@@ -0,0 +1,80 @@
|
||||
/**
|
||||
* train.h - 车次信息管理模块(顺序表)
|
||||
* 负责人:组员A
|
||||
*
|
||||
* 核心数据结构:顺序表 TrainList
|
||||
* 算法:顺序查找、二分查找、直接插入排序、快速排序、堆排序
|
||||
* C++ 版本
|
||||
*/
|
||||
|
||||
#ifndef TRAIN_H
|
||||
#define TRAIN_H
|
||||
|
||||
#include "common.h"
|
||||
|
||||
/* ==================== 顺序表结构 ==================== */
|
||||
|
||||
struct TrainList {
|
||||
TrainInfo data[MAX_TRAINS];
|
||||
int length = 0;
|
||||
};
|
||||
|
||||
/* ==================== 基础操作 ==================== */
|
||||
|
||||
// 增:在位置 i 插入车次
|
||||
bool ListInsert(TrainList& L, int i, const TrainInfo& e);
|
||||
|
||||
// 删:删除位置 i 的车次,将删除的元素存入 e
|
||||
bool ListDelete(TrainList& L, int i, TrainInfo& e);
|
||||
|
||||
// 改:更新车次信息
|
||||
bool ListUpdate(TrainList& L, int i, const TrainInfo& e);
|
||||
|
||||
/* ==================== 查找算法 ==================== */
|
||||
|
||||
// 顺序查找(按车次号),返回下标,未找到返回 -1
|
||||
int SeqSearch(const TrainList& L, const string& trainNo);
|
||||
|
||||
// 二分查找(要求顺序表按 trainNo 有序),返回下标,未找到返回 -1
|
||||
int BinSearch(const TrainList& L, const string& trainNo);
|
||||
|
||||
// 按始发站/终点站模糊查找,返回匹配数量
|
||||
int SearchByStation(const TrainList& L, const string& keyword,
|
||||
TrainInfo results[], int maxResults);
|
||||
|
||||
// 多条件组合查询
|
||||
int AdvancedSearch(const TrainList& L, const string& startStation,
|
||||
const string& endStation, float minPrice,
|
||||
float maxPrice, TrainInfo results[], int maxResults);
|
||||
|
||||
/* ==================== 排序算法 ==================== */
|
||||
|
||||
// 直接插入排序(按车次号排序)
|
||||
void InsertSort(TrainList& L);
|
||||
|
||||
// 快速排序(按票价排序)
|
||||
void QuickSort(TrainList& L, int low, int high);
|
||||
|
||||
// 堆排序(按余票数排序)
|
||||
void HeapSort(TrainList& L);
|
||||
|
||||
/* ==================== 文件读写 ==================== */
|
||||
|
||||
int loadTrainsFromFile(const string& filename);
|
||||
int saveTrainsToFile(const string& filename);
|
||||
|
||||
/* ==================== 管理员接口 ==================== */
|
||||
|
||||
void adminAddTrain();
|
||||
void adminDeleteTrain();
|
||||
void adminModifyTrain();
|
||||
void adminListTrains();
|
||||
void adminSearchTrain();
|
||||
void adminSortTrains();
|
||||
void adminShowStatistics();
|
||||
|
||||
/* ==================== 乘客接口 ==================== */
|
||||
|
||||
void passengerSearchTrain();
|
||||
|
||||
#endif /* TRAIN_H */
|
||||
Reference in New Issue
Block a user