航空客运订票系统.doc
-/课 程 设 计 报 告课程名称 数据结构 课题名称 航空客运订票系统 专 业 通 信 工 程 班 级 学 号 姓 名 指导教师 2013 年 6 月 29 日湖南工程学院课 程 设 计 任 务 书课程名称 数据结构 课 题 航空客运订票系统 专业班级 学生姓名 学 号 指导老师 张鏖烽 田娟秀 李杰君 审 批 任务书下达日期 2013 年 6 月 23 日任 务 完成日期 2013 年 6 月 29 日 目 录1. 需求分析.12. 概要设计.1 2.1 定义“航线”类型.2 2.2 主函数.2 2.3 调用关系.33. 详细设计.3 3.1 航线与客户的存储结构.3 3.2 各个系统模块.3 3.3 算法设计.4 3.4 主函数功能.6 3.5 整个系统的流程图.7 3.6 存储结构设计.74. 调试分析.75. 用户使用说明.86. 测试结果.107. 心得体会.128. 附录.13 课题名称 航空客运订票系统1. 需求分析 航空客运订票的业务活动包括:查询航线、客票预订和办理退票等。试设计一个航空客运订票系统,以使上述业务可以借助计算机来完成。【基本要求】(1)每条航线所涉及的信息有:终点站名、航班号、飞机号、飞行周日(星期几)、乘员定额、余票量、已订票的客户名单(包括姓名、订票量、舱位等级1,2或3)以及等候替补的客户名单(包括姓名、所需票量);(2)系统能实现的操作和功能如下:录入:可以录入航班情况,全部数据可以只放在内存中,最好存储在文件中;查询航线:根据旅客提出的终点站名输出下列信息:航班号、飞机号、星期几飞行,最近一天航班的日期和余票额;承办订票业务:根据客户提出的要求(航班号、订票数额)查询该航班票额情况,若尚有余票,则为客户办理订票手续,输出座位号;若已满员或余票额少于订票额,则需重新询问客户要求。若需要,可登记排队候补;承办退票业务:根据客户提供的情况(日期、航班),为客户办理退票手续,然后查询该航班是否有人排队候补,首先询问排在第一的客户,若所退票额能满足他的要求,则为他办理订票手续,否则依次询问其他排队候补的客户。初始化航班信息如下: 通过输入05这六个数字选择相应的操作,如:查询航班,订票,退票等操作;2. 概要设计 两个客户名单可分别由线性表和队列实现。为查找方便,已订票客户的线性表应按客户姓名有序,并且,为插入和删除方便,应以链表作存储结构。由于预约人数无法预计,队列也应以链表作存储结构。整个系统需汇总各条航线的情况登录在一张线性表上,由于航线基本不变,可采用顺序存储结构,并按航班有序或按终点站名有序。每条航线是这张表上的一个记录,包含上述8个域、其中乘员名单域为指向乘员名单链表的头指针,等候替补的客户名单域为分别指向队头和队尾的指针。注:由于“航线”可只用一条单链表记录,故采用全局变量,减少参数的传递。 2.1定义“航线”类型 ADT Lairline数据对象:D=ai|ai航线链表集,i=1,2,3,n,n>=0数据关系:R1=<ai-1,ai>| ai-1,aiD,i=1,2,3,n 基本操作:Lairline search_line()/按航班号查找航班Lairline search_plane()/按飞机号查找航班Lairline search_date()/按飞行日期查找航班Lairline search_addr()/按航班终点查找航班 void boundary()/主菜单界面void insert_line()/插入新航班void print_customer(airline *p)/显示航班客户信息void book()/订票系统void waited(airline *p)/排队订票系统void Refund()/退票系统void search()/航班查询系统void InitLine()/初始化航线信息void printline()/显示所有航班信息 ADT Lairline; 2.2 主函数 void main() 初始化; do接受命令; 处理命令(调用相应函数); while(“命令”!=“退出”); 2.3 调用关系 3. 详细分析 3.1航线和客户的存储结构 客户存储结构体 typedef struct customer char name20; /姓名 int num; /订票数量int level; /舱位等级customer *next; /指向后继乘客 customer,*Lcustomer; 航线存储结构体 typedef struct airline char ter_address20; /终点站char line_num10; /航班号 char plane_num10; /飞机型号int date; /飞行日期int total; /总人数int remain; /余票数 customer *booked;/已定客户信息customer *wait; /替补客户信息 airline *next; /指向后继航线 airline,*Lairline; 3.2 各个系统模块 (1) 浏览航线模块: 定义void print_customer(airline *p),显示成员的信息;调用void printline()函数输出全部航线信息。 (2) 浏览订票客户信息模块: 定义订票客户信息的结构体customer,根据输入航班号调用search()函数寻找客户信息。 (3) 查询航线模块: 顺着单链表查找,如果与航班号(航线)一致,输出相关信息,否则,查询不成功。 (4) 订票模块: 查找乘客要订的航班号,判断此航班是否有空位,有则输入乘客有关信息,订票成功, 否则失败。 (5) 退票模块: 输入要退票的乘客姓名,查找乘客资料的链表中是否有这位乘客,有则删去此节点,并在空位上加1,无则退票失败。如果此时余票额大于等于候补客户的订票数量,那么候补客户订票成功。 3.3 算法设计 1.按照航班查找 Lairline search_line() char a10;airline *p;p=L->next; P("Please input the number of line:"); S("%s",a);for(;p;p=p->next)if(!strcmp(a,p->line_num ) break;return p;注:通过建立节点p实现链表的遍历,利用for循环挨个查找,直到找到为止,再返回找到的这个节点,实现传递。 2.订票系统 void book() int i; int flag=0;airline *p;customer *cst, *c; P("Please choose the way of viewing:n"); /查询方式选择P("Thenumberoftheflight=>1n"); P("The address of the final destination=>2n"); P("Thedateofthe flight=>3n"); for(;!flag;) /flag为0时一直在循环S("%d",&i); switch(i) /三种方式查询航班 case 1: p=search_line();flag=1;break; case 2: p=search_address();flag=1;break; case 3: p=search_date();flag=1;break; default:P("Wrong!Please input again!n");break; 注:输入1,2,3选择操作方式,先进行查询,在通过调用函数实现购票。 3.初始化航线 void InitLine()/初始化航线信息初始化航线,先建立3条航线方便测试; 4.航班查询 void search()int i;int flag=0;airline *p; P("Please input the way of viewing the flight:n"); P("The number of the flight->1n"); /航班号P("The number of the plane->2n"); /飞机号码P("The date of the flight->3n"); /航班日期P("Thefinaladdressoftheflight->4n"); /航班终点S("%d",&i); for(;!flag;) switch(i) /按照选择项进行操作 case 1: p=search_line();flag=1;break;case 2: p=search_plane();flag=1;break;case 3: p=search_date();flag=1;break;case 4: p=search_address();flag-=1;break;default:P("Wrong,input again!n");break;if(p)P("终点站 航班号 飞机号 飞行周日 余票量n");P("%-9s%9s%13s%10d%15dn",p->ter_address,p->line_num,p->plane _num,p->date,p->remain);P("Booking the tickets?(Sure,please input 1;Else input any number! )");S("%d",&i);if(i=1) book(); Else P("nnnn");boundary(); Else P("The flight is not exist!(_)nnn"); void printline()int flag; airline *p;p=L->next;P("终点站 航班号 飞机号 飞行周日 余票量n");for(;p;p=p->next)P("%s%s%s%d%dn",p->ter_address,p->line_num,p->plane_num,p-> date,p->remain);P("nnnnn");boundary(); 注:通过输入1,2,3,4进行选择查询的方式,分别为飞机型号,航班 号,目的地位置,飞行日期进行查询。 3.4主函数功能 void main() int flag=1; boundary(); InitLine(); do switch(getchar()case 1:printline();break; /显示所有航线case 2:search();break; /case 3:book();break;case 4:Refund();break;case 5:system("cls"); boundary();break; case 0:flag=0;break;while(flag); 包括显示航线,查询信息,订票,退票,清屏这五个功能。 3.5 整个系统的流程图 3.6 存储结构设计: 航班的信息:为了便于查找,航班情况的存储结构采用单链表,每个元素表示一个航班的情况,包括终点站名、航班号、飞机号、星期几、乘员定额和余票量,共六个数据项:终点站名航班号飞机号星期几余票量 4. 调试分析 1、在编程过程中,起先使用的是局部变量,每次调用函数都需要进行参数的传递,很麻烦,而且还容易出现错误;后意识到航线的链表只有一条,很多函数都需要对其数据进行修改,故航线信息采用了全局变量,方便数据的修改,减少 了参数的传递。 2、因为排队订票的客户信息列表没有设置头结点,在退票后询问排队订票客户是否订票时,出现了操作错误,在没有头结点的情况下判断等操作很麻烦,故在 wait(p) 函数里询问排队客户是否订票时,为排队订票的客户信息列表增加了头结点,方便操作。 3、在开始的时候,排队订票客户信息使用的是队列进行数据存储,但测试的时候,发现当第一名排队订票客户不满足需求时询,往后依次询问客户时,队列完全没用,而且还需进行尾节点的各项操作,故弃用队列存储结构。 4、由于本程序涉及的知识单链表的查找,插入和删除,故时间复杂度为 O(n),辅助空间为O(1)。 5、经验和体会:我用vc6.0编程的,这么长的代码,让我深刻认识到断点调试的必要性;同时让我了解到动手的重要性,开始的时候,明明有满脑子的想法和算法,就是很难把想法和算法用代码实现;通过此次课程设计,我的动手能力和算法设计能力有了明显的提高。由于忘记了一些c语言的规范使得在调试过程中一些错误没有发现。例如,调用函数时,数组只需要传递数组名即可;字符0和整形的0是不同的文明不可以直接对其画等号。程序在起初设计的时候,经常出现溢出错误,而且不只一处。为了修正这些溢出错误,耗费了大量的时间,修正解释之后再看源程序,才发现原来只是因为开始的函数定义的数据类型出现了问题,对函数的定义不清楚,字符的不正确定义造成了后期大量的纠错工作, 6、时间复杂度分析 浏览遍历整张航线线性表的时间复杂度:O(1); 线性表的插入和删除操作的时间复杂度:O(n); 查询为线性表的查找,时间复杂度:O(n); 订票为线性表的查找,时间复杂度:O(n);退票是查找两张线性表,时间复杂度为:O(n*e),其中n为航班总数,e 为对应航班已订票人数。5. 用户使用说明 按数字(0-5) 1=>即可显示所有航线信息; 显示现有的所有航线信息,包括目的地,航班号,飞机号,飞行日期,余票量。 2=> 查看某个航线订票余票情况 根据飞行日期,目的地,航班号,飞机号查询飞机的各项信息,如果想要购票 可以实现购票功能。 3=>办理订票业务 根据飞行日期,目的地,航班号,飞机号查询飞机的各项信息 进行选择购票,再输入购票张数,舱位等级,购票人姓名,进行购票。首先输入航班号,如果没有该航班号。则会输出“对不起,该航线未找到!"系统会给出你的座位号;如果你订票数量大于总数,则会输出“对不起。您输入的票的数量已经超过成员定额!”;如果你订票的数量大于剩余票数,那么系统会提示你是否需要排队。如果你需要,则输入排队的客户信息 4=>办理退票业务 如果有该航班,则按照输入顺序。输入订票数量,订票客户,舱位等级。先输入航班号,如果你输入的航班号不存在,那么系统会输出“对不起。该航线未找到!”如果你输入的航班号存在,那么系统会让你输入你退票客户的名字。如果有该客户,那么退票成功。如果没有该客户。那么系统会输出“对不起。你没有定过票”。 0=>退出系统 直接退出购票系统。 5=>清理屏幕 清理屏幕上的信息。6. 测试结果 主菜单界面 图6-1 客服系统主界面 显示所有航线的信息 图6-2 显示所有航线的信息进入订票系统后的操作界面 图6-3 按照飞行日期订票 进入查询系统后的操作界面 图6-4 订票后再查询此航线 注:由图6-3和图6-4可以看出顾客定了三十张票后剩余90张票。进入退票系统后的操作界面 图6-5 当输入错误的航班时退票失败 图6-6 正确输入航班号进行退票成功 退票后的航线查询 图6-7 退票后再次查询此航线注:结合上面的退票信息图可以观察出退票成功后票又变回了原来的张数多位顾客购票后的余票查询 图6-8 多人购票后余票查询7. 心得体会 短短一周的数据结构课程设计结束了,本次课程设计遇到了很多困难,但是在老师的帮助下都一一解决了,首先感谢老师对我的帮助。开始学习数据结构时感觉和C语言没什么不一样,而且还认为数据结构做不出什么实质性的东西出来。但是这次课程设计改变了我的看法,也让我深深体会到自己学习的不足。通过这次课程设计,我感觉数据结构的核心应该是算法,无论什么程序,只要掌握了核心算法,程序基本都能编写出来。在敲源代码时,发现航班结构体中的已定票乘客信息和等待订票乘客信息的结构不太好操作,经过一番思考最终改为源代码中所定义的结构体。从中知道了结构体的定义决定了源程序的难易。在打程序时,没有把文件操作的代码打进源程序。在调试没有文件操作的代码时,没有很多错误,但是犯了一个大错,就是在有一个字符串的复制中使用了赋值,调试过程指出错错误半天都不知道改,后来看了整个程序才反应过来。在运行调试过程中浏览信息没有输出想要的输出结果,检查程序原来是格式控制字符串中的一个字符打成了大写;查询信息只能查询链表中的第一条航线,检查程序原来是多用了break造成过早跳出循环,不能查找后面的航线;乘客订多张票后浏览信息发现余票只减了一张,检查程序发现乘客订票后只对余票做了自减,在运行调试过程中就出现了这么些大的错误,在这过程中还对输出窗口界面做了一些调整。加入文件操作代码后进行调试,没有出现什么错误。最终运行时老在文件操作时终止程序,经过调试和自己的摸索原来是文件检测函数运用错误,改正后程序正常运行。运行程序后打开所写的文件,发现航班信息的余票量没有随乘客的订票而减少,还是初始值,这时才发现每进行一次订票后都要重新对航班信息的文件重新写入,改后最终就确定了上交源代码。在敲代码和在程序的调试、运行过程中我们发现我们半天才能想出几句语句,整个代码敲了二十几个小时,调试调了二三十个小时,主要原因使我们练得还不够,C语言功底还不是很扎实,要增加敲的代码量。 此次课程设计,使我们对链表和链队列的基本操作更加熟练,让我们深深地体会到要学好数据结构需要多练,多编程,多思考。8. 附录#include <stdio.h>#include <string.h>#include <malloc.h>#include <stdlib.h>#define P printf#define S scanf /*客户信息*/typedef struct customer char name20; /姓名 int num; /订票数量int level; /舱位等级customer *next; /指向后继乘客customer,*Lcustomer;/*航线信息*/typedef struct airline char ter_address20; /终点站char line_num10; /航班号 char plane_num10; /飞机型号int date; /飞行日期int total; /总人数int remain; /余票数 customer *booked;/已定客户信息customer *wait; /替补客户信息 airline *next; /指向后继航线airline,*Lairline;airline * L; /全局变量 :航班信息/*按照航班号查找航班*/Lairline search_line()char a10;airline *p;p=L->next; P("Please input the number of line:"); S("%s",a);for(;p;p=p->next)if(!strcmp(a,p->line_num ) break;return p;/*三种方式查找航班*/Lairline search_plane()/1.按照飞机型号查找char a10;airline *p;p=L->next;P("Please input the number of plane:");S("%s",a);for(;p;p=p->next)if(!strcmp(a,p->plane_num) break;return p;Lairline search_date()/2.按照日期查询航班 int a;airline *p;p=L->next;P("Please input the date of plane:");S("%d",&a); /注意这里加取址符for(;p;p=p->next) if(a=p->date) break; /当找到找到与a相同的节点时跳出循环return p;Lairline search_address()/3.按航班终点查找航班char a20;airline *p;p=L->next;P("Please input the final address of the plane:");S("%s",a); for(;p;p=p->next)if(!strcmp(a,p->ter_address) break;return p;/*主界面*/void boundary() P(" *欢迎您进入航空订票客服系统* n "); P("n"); P(" O(_)O 请选择您要进行的业务:n"); P("tt显示所有航线 =>请输入1n"); P("tt查询航线信息 =>请输入2n"); P("tt进入订票系统 =>请输入3n"); P("tt进入退票系统 =>请输入4n"); P("tt退出客服系统 =>请输入0n"); P("n"); P("tt清除屏幕信息 =>请输入5n"); P("请按照以上的信息提示进行操作: t");/*显示乘客信息*/void print_customer(airline *p)customer *c; if(p->booked) c=p->booked;P("已经购票的乘客的信息nt票数t姓名tn"); for(;c;c=c->next)P("%5dtt %sn",c->num,c->name);P("nn"); else P("(_)暂时没有客户订票!nn"); if(p->wait) c=p->wait; P("排队购票的乘客的信息nt票数t姓名tnn"); for(;c;c=c->next) P("%5dtt %sn",c->num,c->name); P("nn");else P("暂时没有客户排队订票nn");/*插入新航班(创建链表)*/void insert_line()airline *p,*q;int flag=1;for(;flag;)q=(Lairline)malloc(sizeof(airline);P("Please input the number of the plane: ");S("%s",q->line_num);for(p=L;p->next;p=p->next) if(strcmp(p->next->line_num,q->line_num)>=0) break; if(p->next&&strcmp(p->next->line_num,q->line_num)=0)P("航班已存在,请重新输入n");continue; /一旦航班已经存在,立刻跳出本次循环 P("Please input the date of the plane:"); /飞行日期 S("%dt",&q->date);P("Please input the number of the plane:"); /飞机号S("%s",q->plane_num); P("PLease input the final address of the plane:");/终点站S("%s",q->ter_address); q->total=120; /总数为120 q->remain=120; /余票为120 q->booked=NULL;q->wait=NULL; q->next=p->next; /插入新节点p->next=q;/插入节点成功后再选择是否继续增加P("Success!Do you want to continue?n");P("Stop=>(0)ttContinue=>(1)n");scanf("%d",&flag);/*订票系统*/void book()int i; int flag=0;airline *p;customer *cst, *c; P("Please choose the way of viewing:n"); /查询方式选择P("The number of the flight=>1n"); P("The address of the final destination=>2n"); P("The date of the flight=>3n"); for(;!flag;) /flag为0时一直在循环S("%d",&i); switch(i) /三种方式查询航班 case 1: p=search_line();flag=1;break; case 2: p=search_address();flag=1;break; case 3: p=search_date();flag=1;break; default:P("Wrong!Please input again!n");break; /首先进行查票 if(p) P("终点站 航班号 飞机号 飞行周日 余票量 n"); P("%-10s%8s%18s%13d%16dn",p->ter_address,p->line_num, p->plane_num,p->date,p->remain);cst=(customer *)malloc(sizeof(customer);P("The number of tickets:t"); / 购票张数S("%d",&cst->num)