数据结构与算法程序设计
游轮乘票预定
1 项目要求
项目名称 游轮乘票预定 项目类型 系统类
项目难度 中等 素材资源 无(…/res)
使用工具 不限 编译系统 Windows、Linux
硬件需求 无 程序语言 不限
知识点 结构体/类、树、队列、线性表、排序、递归、函数、键盘操作等
项目描述 设计一个船班信息系统,该系统主要是利用船班的这些信息,通过其中的任意一个信息,找出我们所需要的查找的船班的所有信息,
采用基数排序法对一组具有结构特点的游轮船班号进行排序,利用二分查找法对排序好的船班记录按船班号实现快速查找,并按其
他关键字的查找可以采用最简单的顺序查找方法进行。
功能实现 主菜单主界面与功能一览
按船班号查询功能
按出发时间查询功能
按照到达时间查询功能
按起点站查询功能
按终点站查询功能
退出界面
提交材料 实训报告、可运行的程序
2 技术方案建议
2.1数据结构选择
按具体需求自选数据结构
2.2算法参考
采用基数排序法对一组具有结构特点的游轮船班号进行排序,利用二分查找法对排好序的船班记录按船班号实现快速查找,按其他次关键字的查找可采用最简单的顺序查找方法进行。
#include<iostream>
#include<cstdio>
#include<cstring>
#include<cstdlib>
#include<windows.h>
#include<conio.h>
using namespace std;
#define MaxNum 30
#define MaxLen 20
#define inf 99999999
/**
* 用户信息类型
*/
typedef struct User
{
char user_name[MaxLen];
char password[MaxLen];
} User;
/**
* 船班信息类型
*/
typedef struct Ferry
{
int id; //船班号
char start_place[MaxLen]; //起点站
char start_time[MaxLen]; //出发时间
char arrive_place[MaxLen]; //终点站
char arrive_time[MaxLen]; //到达时间
Ferry *next;
} Ferry,*Ferry_data;
/**
* 站点信息类型
*/
typedef struct Point
{
int id; //站点id
char name[20];//站点名字
} Point;
/**
* 存储站点信息的图
*/
typedef struct Map
{
int mapper[MaxNum][MaxNum];
char names[MaxNum][MaxLen];
} Map;
/**
* 欢迎页
* @param now:表示当前页面的编号
*/
void welcome(int &now);
/**
* 注册,判断输入的两个密码是否合法并且用户名是否不存在
* @param password1 password2:两次输入的密码 user_name:用户输入的用户名
* @return 注册成功与否
*/
bool registerCheck(char *password1,char *password2,char *user_name);
/**
* 登录,判断用户名和密码是否正确
* @param user:User类型的数据,其中包括user_name(用户名)和password(密码)
* @return 登录成功与否
*/
bool loginCheck(User user);
/**
* 判断某个字符串是是否包含空格
* @param str:待判断的字符串
* @return 包含空格返回true,否则返回false
*/
bool hasBlank(char *str);
/**
* 注册页
* @param now:表示当前页面的编号
*/
void registerPage(int &now);
/**
* 登录页面
* @param now:表示当前页面的编号 login_id:当前登录的用户名
*/
void loginPage(int &now,char *login_id);
/**
* 查询所有的船班
* @param ferrys:节点为存储船班信息的单链表,保存查询后得到的信息
*/
void findAllFerrys(Ferry_data &ferrys);
/**
* 主页
* @param now:表示当前页面的编号 login_id:当前登录的用户名
*/
void homePage(int &now,char *login_id);
/**
* 输出所有的船班信息
* @param ferrys:保存有所有船班信息的单链表
*/
void printAllFerrys(Ferry_data ferrys);
/**
* 二分查找
* 根据船班编号查询船班信息
* @param ferrys:所有的船班 id:待查询的船班的编号
*/
void findFerryById(Ferry_data ferrys,int id);
/**
* 归并排序
* @param ferrys:待排序的数组 start:排序的起始位置 ennd:排序的结束位置
*/
void Mergesort(Ferry *ferrys,int start,int ennd);
/**
* 归并排序的“并”过程
* @param ferry:待“并”的数组,start mid ennd:待“并”的两个区间[start,mid]和[mid+1,ennd]
*/
void Merge(Ferry *ferrys,int start,int mid,int ennd);
/**
* 根据站点查询船班信息
* @param ferrys:保存船班信息的单链表 tmp:待查询的站点
*/
void searchByPlace(Ferry_data ferrys,char *tmp);
/**
* 预订船票
* @param ferrys:所有船班信息 ferry:待预订的船班编号 login_id:当前登录的用户名
*/
bool orderTicket(Ferry_data ferrys,int ferry_id,char *login_id);
/**
* 查找用户的所有订单
* @param login_id:当前登录的用户名
*/
bool searchOrders(char *login_id);
/**
* 从文件系统创建站点之间的信息
* @param 创建的站点信息的图
*/
void CreateMap(Map &mapp);
/**
* 求点v到其余各点之间的最短路径
* @param mapp:存储站点信息的图 v:起点 w:终点
* @return v到w之间的最短距离
*/
int ShortestPath(Map mapp,int v,int w);
/**
* 递归
* 输出最短路径的路径
* @param start:起点,ennd:终点,path:路径,mapp:图信息
*/
void showMinDisPath(int start,int ennd,int *path,Map mapp);
int main()
{
int now = 1;
char login_id[MaxLen];
while(true)
{
system("cls");
if(now==0) //退出
break;
else if(now==1) //欢迎页
welcome(now);
else if(now==2) //注册页
registerPage(now);
else if(now==3) //登录页
loginPage(now,login_id);
else if(now==4) //主页
homePage(now,login_id);
}
return 0;
}
/**
* 欢迎页
* @param now:表示当前页面的编号
*/
void welcome(int &now)
{
cout<<"===============RuL游轮乘票预订==============="<<endl;
cout<<"| |"<<endl;
cout<<"| 欢迎来到RuL游轮乘票预订系统 |"<<endl;
cout<<"| 在使用前,请先: |"<<endl;
cout<<"| |"<<endl;
cout<<"| L:登录 R:注册 |"<<endl;
cout<<"| E:退出 |"<<endl;
cout<<"| |"<<endl;
cout<<"| |"<<endl;
cout<<"============================================="<<endl;
char operation;
while(true)
{
cout<<"请输入相关操作:"<<endl;
cin>>operation;
if(operation=='L')
{
now = 3;
break;
}
else if(operation=='R')
{
now = 2;
break;
}
else if(operation=='E')
{
char ok;
cout<<"确认退出? Y/N"<<endl;
cin>>ok;
if(ok=='Y')
{
now = 0;
cout<<"Bye!"<<endl;
Sleep(2000);
break;
}
}
}
}
/**
* 注册页
* @param now:表示当前页面的编号
*/
void registerPage(int &now)
{
cout<<"===============RuL游轮乘票预订==============="<<endl;
cout<<"| ------------------注册------------------- |"<<endl;
cout<<"| |"<<endl;
cout<<"| 请选择相关操作: |"<<endl;
cout<<"| 任意键:下一步 R:返回 |"<<endl;
cout<<"============================================="<<endl;
char operation = getch();
if(operation=='R')
now = 1;
else
{
char password1[MaxLen],password2[MaxLen],user_name[MaxLen];
cout<<"请输入您的用户名(不要包含空格):"<<endl;
cin>>user_name;
cout<<"请输入您的密码(只包含数字和字母):"<<endl;
cin>>password1;
cout<<"请确认密码:"<<endl;
cin>>password2;
//判断注册是否成功
bool success = registerCheck(password1,password2,user_name);
if(success)
{
//注册成功,修改页面编码,跳转都登录页面
now = 3;
cout<<"即将进入登录......"<<endl;
Sleep(2000);
}
else
{
//重新注册
cout<<"正在为您安排重新注册......"<<endl;
Sleep(2000);
}
}
}
/**
* 登录页面
* @param now:表示当前页面的编号 login_id:当前登录的用户名
*/
void loginPage(int &now,char *login_id)
{
cout<<"===============RuL游轮乘票预订==============="<<endl;
cout<<"| ------------------登录------------------- |"<<endl;
cout<<"| |"<<endl;
cout<<"| 请选择相关操作: |"<<endl;
cout<<"| 任意键:下一步 R:返回 |"<<endl;
cout<<"============================================="<<endl;
char operation = getch();
if(operation=='R')
now = 1;
else
{
User user;
cout<<"请输入您的用户名:"<<endl;
cin>>user.user_name;
cout<<"请输入您的密码:"<<endl;
cin>>user.password;
//判断登录是否成功
bool success = loginCheck(user);
if(success)
{
//登录成功,进入主页
cout<<"正在进入系统......"<<endl;
now = 4;
//保存登录的用户名
strcpy(login_id,user.user_name);
Sleep(2000);
}
else
{
//登录失败,重新登录
cout<<"正在为您安排重新登录......"<<endl;
Sleep(2000);
}
}
}
/**
* 主页
* @param now:表示当前页面的编号 login_id:当前登录的用户名
*/
void homePage(int &now,char *login_id)
{
cout<<"===============RuL游轮乘票预订==============="<<endl;
cout<<"| |"<<endl;
cout<<"| A:船班号快速查询 |"<<endl;
cout<<"| B:查询全部船班 |"<<endl;
cout<<"| C:普通查询 |"<<endl;
cout<<"| |"<<endl;
cout<<"| D:预订船班 |"<<endl;
cout<<"| E:我的订单 |"<<endl;
cout<<"| F:最短路径查询 |"<<endl;
cout<<"| G:退出登录 |"<<endl;
cout<<"| |"<<endl;
cout<<"| 请输入相关操作: |"<<endl;
cout<<"============================================="<<endl;
Ferry_data ferrys = NULL;
//查询所有船班信息
findAllFerrys(ferrys);
char operation;
cin>>operation;
if(operation=='A')
{
int ferry_id;
cout<<"请输入船班号:"<<endl;
cin>>ferry_id;
//根据船班号查询船班信息
findFerryById(ferrys,ferry_id);
cout<<"按任意键返回主菜单"<<endl;
getchar();
getch();
}
else if(operation=='B')
{
//输出所有船班信息
printAllFerrys(ferrys);
cout<<"按任意键返回主菜单"<<endl;
getchar();
getch();
}
else if(operation=='C')
{
char tmp[30];
cout<<"请输入起点站或终点站:"<<endl;
cin>>tmp;
//根据站点查询船班信息
searchByPlace(ferrys,tmp);
cout<<"按任意键返回主菜单"<<endl;
getchar();
getch();
}
else if(operation=='D')
{
cout<<"请输入您想要预订的船班号:"<<endl;
int ferry_id;
cin>>ferry_id;
//预订船班
orderTicket(ferrys,ferry_id,login_id);
cout<<"按任意键返回主菜单"<<endl;
getchar();
getch();
}
else if(operation=='E')
{
cout<<"您的所有订单如下:"<<endl;
//查找订单
searchOrders(login_id);
cout<<"按任意键返回主菜单"<<endl;
getchar();
getch();
}
else if(operation=='F')
{
Map mapp;
CreateMap(mapp);
for(int i=0; i<MaxNum; i++)
{
for(int j=0; j<MaxNum; j++)
{
if(mapp.mapper[i][j]!=0&&mapp.mapper[i][j]!=inf)
cout<<i<<":"<<mapp.names[i]<<"->"<<j<<":"<<mapp.names[j]<<endl;
}
}
cout<<endl<<endl<<"请输入您想查询最短路径的两个站点:"<<endl;
cout<<"请输入起点的编号:"<<endl;
int start,ennd;
cin>>start;
cout<<"请输入终点的编号:"<<endl;
cin>>ennd;
cout<<"最短路径为:"<<endl;
int ans = ShortestPath(mapp,start,ennd);
cout<<endl<<"最短距离为:"<<ans<<endl;
cout<<"按任意键返回主菜单"<<endl;
getchar();
getch();
}
else if(operation=='G')
{
cout<<"您确定退出登录吗? Y/N"<<endl;
char ok;
cin>>ok;
if(ok=='Y')
now = 1;
}
}
/**
* 注册,判断输入的两个密码是否合法并且用户名是否不存在
* @param password1 password2:两次输入的密码 user_name:用户输入的用户名
* @return 注册成功与否
*/
bool registerCheck(char *password1,char *password2,char *user_name)
{
int len1 = strlen(password1);
int len2 = strlen(password2);
//判断两次输入的密码是否一致
if(strcmp(password1,password2)!=0)
{
cout<<"两次输入的密码不一致,请重新注册!"<<endl;
return false;
}
//判断输入的密码是否合法
if(len1<6||len1>10||hasBlank(password1)||hasBlank(password2))
{
cout<<"输入的密码不符合规范,请重新注册!"<<endl;
return false;
}
//以只读方式打开存储用户信息的文件
FILE *user_file = fopen("users.txt","r");
if(user_file==NULL)
{
cout<<"系统异常,请稍后重试!"<<endl;
return false;
}
char user_name_tmp[MaxLen],password_tmp[MaxLen];
while(fscanf(user_file,"%s %s",user_name_tmp,password_tmp)!=EOF)
{
//判断用户名是否已经存在
if(strcmp(user_name_tmp,user_name)==0)
{
cout<<"该用户名已存在,请重新注册!"<<endl;
fclose(user_file);
return false;
}
}
//关闭文件
fclose(user_file);
//以追加方式打开文件
user_file = fopen("users.txt","a+");
if(user_file==NULL)
{
cout<<"系统异常,请稍后重试"<<endl;
return false;
}
//保存注册的信息到文件
fprintf(user_file,"%s %s\n",user_name,password1);
fclose(user_file);
cout<<"注册成功"<<endl;
return true;
}
/**
* 登录,判断用户名和密码是否正确
* @param user:User类型的数据,其中包括user_name(用户名)和password(密码)
* @return 登录成功与否
*/
bool loginCheck(User user)
{
//打开用户信息文件
FILE *user_file = fopen("users.txt","r");
if(user_file==NULL)
{
cout<<"系统异常,请稍后重试"<<endl;
return false;
}
char user_name[MaxLen],password[MaxLen];
while(fscanf(user_file,"%s %s",user_name,password)!=EOF)
{
if(strcmp(user_name,user.user_name)==0&&strcmp(password,user.password)==0)
{
//用户名和密码都正确
fclose(user_file);
cout<<"登录成功"<<endl;
return true;
}
}
//关闭文件
fclose(user_file);
cout<<"账号或密码错误,请重新操作!"<<endl;
return false;
}
/**
* 判断某个字符串是是否包含空格
* @param str:待判断的字符串
* @return 包含空格返回true,否则返回false
*/
bool hasBlank(char *str)
{
int len = strlen(str);
for(int i=0; i<len; i++)
{
if(str[i]==' ')
return true;
}
return false;
}
/**
* 查询所有的船班
* @param ferrys:节点为存储船班信息的单链表,保存查询后得到的信息
*/
void findAllFerrys(Ferry_data &ferrys)
{
//打开保存船班信息的文件
FILE *ferry_file = fopen("ferrys.txt","r");
if(ferry_file==NULL)
{
cout<<"系统异常,请稍后重试!"<<endl;
return;
}
int id;
char start_place[30],start_time[20];
char arrive_place[30],arrive_time[20];
//利用头插法建立链表
while(fscanf(ferry_file,"%d %s %s %s %s",&id,start_place,start_time,arrive_place,arrive_time)!=EOF)
{
Ferry *ferry = new Ferry;
ferry->id = id;
strcpy(ferry->start_place,start_place);
strcpy(ferry->start_time,start_time);
strcpy(ferry->arrive_place,arrive_place);
strcpy(ferry->arrive_time,arrive_time);
ferry->next = ferrys;
ferrys = ferry;
}
fclose(ferry_file);
}
/**
* 输出所有的船班信息
* @param ferrys:保存有所有船班信息的单链表
*/
void printAllFerrys(Ferry_data ferrys)
{
Ferry *p = ferrys;
while(p!=NULL)
{
cout<<p->id<<"||"<<p->start_place<<"|"<<p->start_time<<"||"<<p->arrive_place<<"|"<<p->arrive_time<<"|"<<endl;
p=p->next;
}
}
/**
* 二分查找
* 根据船班编号查询船班信息
* @param ferrys:所有的船班 id:待查询的船班的编号
*/
void findFerryById(Ferry_data ferrys,int id)
{
Ferry *p = ferrys;
Ferry ferryArray[MaxNum];
int index = 0;
//将链表中的信息转存到数组中
while(p!=NULL)
{
ferryArray[index++] = *p;
p = p->next;
}
//二分查找之前先进行排序
Mergesort(ferryArray,0,index-1);
int left = 0,right = index-1,mid;
bool hasFound = false;
//二分查找
while(left<=right)
{
mid = (left+right)/2;
if(ferryArray[mid].id==id)
{
cout<<ferryArray[mid].id<<"||"<<ferryArray[mid].start_place<<"|"<<ferryArray[mid].start_time<<"||";
cout<<ferryArray[mid].arrive_place<<"|"<<ferryArray[mid].arrive_time<<"||"<<endl;
hasFound = true;
break;
}
else if(ferryArray[mid].id<id)
left = mid+1;
else if(ferryArray[mid].id>id)
right = mid-1;
}
if(!hasFound)
cout<<"没有找到相关信息,请检查船班号是否有误!"<<endl;
}
/**
* 归并排序的“并”过程
* @param ferry:待“并”的数组,start mid ennd:待“并”的两个区间[start,mid]和[mid+1,ennd]
*/
void Merge(Ferry *ferrys,int start,int mid,int ennd)
{
Ferry tmp[ennd-start+1];
int index = 0;
int index1 = start;
int index2 = mid+1;
//将有序的两部分[start,mid][mid+1,ennd]合并为一部分
while(index1<=mid&&index2<=ennd)
{
if(ferrys[index1].id<ferrys[index2].id)
tmp[index++] = ferrys[index1++];
else
tmp[index++] = ferrys[index2++];
}
//还存在未合并完成的数
while(index1<=mid)
tmp[index++] = ferrys[index1++];
while(index2<ennd)
tmp[index++] = ferrys[index2++];
//将有序的一部分代替原本的两部分
for(int i=start; i<=ennd; i++)
ferrys[i] = tmp[i-start];
}
/**
* 归并排序
* @param ferrys:待排序的数组 start:排序的起始位置 ennd:排序的结束位置
*/
void Mergesort(Ferry *ferrys,int start,int ennd)
{
if(start<ennd)
{
//找中点,利用递归进行排序
int mid = start+(ennd-start)/2;
Mergesort(ferrys,start,mid);
Mergesort(ferrys,mid+1,ennd);
Merge(ferrys,start,mid,ennd);
}
}
/**
* 根据站点查询船班信息
* @param ferrys:保存船班信息的单链表 tmp:待查询的站点
*/
void searchByPlace(Ferry_data ferrys,char *tmp)
{
Ferry *p = ferrys;
//遍历查找
while(p!=NULL)
{
if(strcmp(p->start_place,tmp)==0||strcmp(p->arrive_place,tmp)==0)
cout<<p->id<<"||"<<p->start_place<<"|"<<p->start_time<<"||"<<p->arrive_place<<"|"<<p->arrive_time<<"|"<<endl;
p=p->next;
}
}
/**
* 预订船票
* @param ferrys:所有船班信息 ferry:待预订的船班编号 login_id:当前登录的用户名
*/
bool orderTicket(Ferry_data ferrys,int ferry_id,char *login_id)
{
Ferry *p = ferrys;
bool hasExist = false;
//遍历判断船班号是否存在
while(p!=NULL)
{
if(ferry_id==p->id)
{
hasExist = true;
break;
}
p = p->next;
}
if(hasExist)
{
//打开保存船班信息的文件
FILE *order_file = fopen("orders.txt","a+");
if(order_file==NULL)
{
cout<<"系统异常,请稍后重试!"<<endl;
return false;
}
fprintf(order_file,"%d %s %s %s %s %s\n",p->id,p->start_place,p->start_time,p->arrive_place,p->arrive_time,login_id);
fclose(order_file);
cout<<"预订成功"<<endl;
return true;
}
return false;
}
/**
* 查找用户的所有订单
* @param login_id:当前登录的用户名
*/
bool searchOrders(char *login_id)
{
FILE *order_file = fopen("orders.txt","r");
if(order_file==NULL)
{
cout<<"系统异常,请稍后重试!"<<endl;
return false;
}
Ferry ferry;
//预订订单的用户
char orderor[20];
while(fscanf(order_file,"%d %s %s %s %s %s",&ferry.id,ferry.start_place,ferry.start_time,ferry.arrive_place,ferry.arrive_time,orderor)!=EOF)
{
if(strcmp(orderor,login_id)==0)
cout<<ferry.id<<"||"<<ferry.start_place<<"|"<<ferry.start_time<<"||"<<ferry.arrive_place<<"|"<<ferry.arrive_time<<"||"<<endl;
}
fclose(order_file);
return true;
}
/**
* 从文件系统创建站点之间的信息
* @param 创建的站点信息的图
*/
void CreateMap(Map &mapp)
{
FILE *mapper_file = fopen("mapper.txt","r");
if(mapper_file==NULL)
{
cout<<"读取数据失败,请稍后重试"<<endl;
return;
}
//初始化站点之间的距离
for(int i=0; i<MaxNum; i++)
{
for(int j=0; j<MaxNum; j++)
{
if(i==j)
mapp.mapper[i][j]=0;
else
mapp.mapper[i][j]=inf;
}
}
Point start;
Point ennd;
int dis;
while(fscanf(mapper_file,"%d %s %d %s %d",&start.id,start.name,&ennd.id,&ennd.name,&dis)!=EOF)
{
//两站点之间的距离
mapp.mapper[start.id][ennd.id] = dis;
mapp.mapper[ennd.id][start.id] = dis;
//站点名字
strcpy(mapp.names[start.id],start.name);
strcpy(mapp.names[ennd.id],ennd.name);
}
fclose(mapper_file);
}
/**
* 求点v到其余各点之间的最短路径
* @param mapp:存储站点信息的图 v:起点 path:记录路径
* @return v到w之间的最短距离
*/
int ShortestPath(Map mapp,int v,int w)
{
//记录点是否已经被访问
bool vis[MaxNum];
//记录v到各点之间的最短距离
int distance[MaxNum];
//记录路径
int path[MaxNum];
//初始化各点到v之间的距离
for(int i=0; i<MaxNum; i++)
{
vis[i] = false;
distance[i] = mapp.mapper[v][i];
path[i] = v;
}
vis[v] = true;
//比较MaxNum-1趟
for(int i=1; i<MaxNum; i++)
{
int minIndex = 0;
int minDis = inf;
for(int j=0;j<MaxNum;j++)
{
if(vis[j]==false&&minDis>distance[j])
{
minIndex = j;
minDis = distance[j];
}
}
vis[minIndex] = true; //标记该点已经被访问
//更新每个顶点的最短路径
for(int j=1; j<MaxNum; j++)
{
if(vis[j]==false&&distance[minIndex]+mapp.mapper[minIndex][j]<distance[j])
{
distance[j] = distance[minIndex]+mapp.mapper[minIndex][j];
//更新路径
path[j] = minIndex;
}
}
}
showMinDisPath(v,w,path,mapp);
return distance[w];
}
/**
* 输出最短路径的路径
*/
void showMinDisPath(int start,int ennd,int *path,Map mapp)
{
if(start==ennd)
{
cout<<start<<":"<<mapp.names[start];
return;
}
showMinDisPath(start,path[ennd],path,mapp);
cout<<"->"<<ennd<<":"<<mapp.names[ennd];
}