模拟停车场管理班级:物联网姓名:XXX 学号:XXXXXXX 日期:4月9日一、需求分析1、程序的功能描述按照从终端输入的数据序列进行模拟管理。
1)狭道停车用栈来实现,并且用的顺序栈,等车位的便道用队列来实现,并用链式存储。
2)每一组输入信息包含三个数据项,汽车的“到达”和“离去”的信息,汽车牌照号码,汽车“到达”或“离去”的时刻。
3)对每一组输入数据进行操作后的输出信息为:若是车辆到达,则输出车辆在停车场内或便道上的停车位置;若是车子离去,则输出车辆在停车场内停留的时间和缴纳的费用。
(假设在便道等车的时间不收费)4)选作内容:(1)便道也是要收费的,仅仅比狭道收费便宜点。
(2)狭道上的车可以直接开走。
2、输入/输出的要求首先选择操作的模块,根据提示输入车牌和到达时间,程序会告知是否停满或者停车车位。
车牌为10个字符以内的字符串,时间的输入中间有冒号把时分隔开。
3、测试数据1 苏D543 1:101 苏Q123 1:201 苏D145 1:30二、概要设计1、本程序所用的抽象数据类型的定义typedef struct NODE{CarNode *stack[MAX+1];int top;}SeqStackCar;//狭道的堆栈顺序存储typedef struct car{CarNode *data;struct car *next;}QueueNode;//队列的链式存储typedef struct Node{QueueNode *head;QueueNode *rear;}LinkQueueCar;//便道上等候的队列定义2、主模块的流程及各子模块的主要功能○1车辆到达:int Arrival(SeqStackCar *Enter,LinkQueueCar *W)首先定义一个栈和队列的结构体指针为:*p , *t 。
然后申请一个车辆信息的内存空间,并把它赋给栈指针。
车辆到达时就输入车牌号,并通过if(Enter->top<MAX)来判断该车是进车场内还是进便道上,如果是进车场内就把top 加1,显示在车场内的位置,还要输入进车场的时间,然后把该节点进栈。
如果是else 就显示该车要停在便道上,并进行进队列的操作。
○2车辆离开:void Leave(SeqStackCar *Enter,SeqStackCar *Temp,LinkQueueCar *W)定义一个整型变量room 记录要离开车辆的位置,定义两个栈指针和一个队列指针,用个if(Enter->top>0) 确保栈不空,然后用个while(1) 确保输入的车辆离开位置的合法性。
如果不和法,显示输入有误,要重新输入。
通过while(Enter->top>room) 判断离开车辆的位置,如果是中间位置,就要再用一个栈前面临时开出来的车,等要开出的车开出后,再把临时栈的车看进车场内,并要调用PRINT(p,room); 这个函数计算显示费用。
然后还要用if((W->head!=W->rear)&&Enter->top<MAX) 语句判断便道上有没有车,如果有车就要显示进车场的车的车牌号,并登记进入时间。
3、模块之间的层次关系主函数中包含着各个函数模块,各模块也在互相调用。
比如,离开函数中要计算停车费,故要调取价格函数。
价格函数计算要用到离开和进入的时间,又要调用进入和离开函数。
三、详细设计1、采用C语言定义相关的数据类型#define MAX 3 // 停车场最大容量为3辆,便于观察#define price 0.05typedef struct time{ // 定义时间结构体int hour;int min;}Time;typedef struct node{ // 定义车辆信息结构体char num[10];Time reach;Time leave;}CarNode;2、写出各模块的伪码算法void PRINT(CarNode *p,int room){ // 车辆收费int A1,A2,B1,B2;printf("\n车辆离开的时间:");scanf("%d:%d",&(p->leave.hour),&(p->leave.min));printf("\n离开车辆的车牌号为:");puts(p->num);printf("\n其到达停车位时间);printf("\n离开停车位时间为:);A1=p->reach.hour;A2=p->reach.min;B1=p->leave.hour;B2=p->leave.min;printf("\n应交费用为: %2.1f元",((B1-A1)*60+(B2-A2))*price+PRINTE(p,room));free(p);}int Arrival(SeqStackCar *Enter,LinkQueueCar *W)//进入便道或者狭道{CarNode *p;QueueNode *t;p=(CarNode *)malloc(sizeof(CarNode));flushall();printf("\n请输入车牌号(例:豫B1234):");gets(p->num);if(Enter->top<MAX){Enter->top++;printf("\n车辆在车场第%d位置.",Enter->top);printf("\n车辆到达时间:");scanf("%d:%d",&(p->reach.hour),&(p->reach.min));Enter->stack[top]=p;return(1);}else{printf("\n该车须在便道等待!有车位时进入车场");t=(QueueNode *)malloc(sizeof(QueueNode));进入队列,调整指针;printf("请输入进入便道的时间");scanf("%d:%d",&(p->reach.hour),&(p->reach.min));return(1);}}void Leave(SeqStackCar *Enter,SeqStackCar *Temp,LinkQueueCar *W) { //车辆的离开int room;CarNode *p,*t;QueueNode *q;if(Enter->top>0) // 判断车场是否为空{while(1){printf("\n请输入车在车场的位置/1--%d/:",Enter->top); scanf("%d",&room);if(room>=1&&room<=Enter->top) break;else printf("\n 输入有误,请重输: ");}while(Enter->top>room) // 把要删除的车辆的前面的车开出来,进临时栈。
{Temp->top++;Temp->stack[Temp->top]=Enter->stack[Enter->top];Enter->stack[Enter->top]=NULL;Enter->top--;}p=Enter->stack[Enter->top]; //把要删除的车辆节点赋给p。
Enter->stack[Enter->top]=NULL;Enter->top--;while(Temp->top>=1) // 再把临时栈里德车辆进停车场{Enter->top++;Enter->stack[Enter->top]=Temp->stack[Temp->top];Temp->stack[Temp->top]=NULL;Temp->top--;}PRINT(p,room); // 调用计费函数计费。
if((W->head!=W->rear)&&Enter->top<MAX) //如果便道上有车,则再开进停车场。
{q=W->head->next;t=q->data;Enter->top++;scanf("%d:%d",&(t->reach.hour),&(t->reach.min));// t->leave .hour =t->reach.hour;//t->leave .min =t->reach.min;W->head->next=q->next;if(q==W->rear) W->rear=W->head;Enter->stack[Enter->top]=t;PRINTE(t,room);free(q);}else printf("\n便道里没有车.\n");}else printf("\n车场里没有车.");}3、画出函数的调用关系图|---------------->到达函数-----||---------------->离开函数-------->停车费用主函数----------->显示车场里的情况|---------------->显示便道里的情况四、调试分析1、调试中遇到的问题及对问题的解决方法因为时间结构体里的小时,分钟都是用的是整型,所以如果出现1:01这个时间的话,会导致显示列表是1:1;这样的话会造成人的误解,同时会导致程序对停车缴纳的费用计算错误。
解决方法1:可以用数组和或者字符串来表示时间,但是问题来了,要是用字符串的话,算停车费有点问题,要废上一段时间的,会提高复杂度。
解决方案2:将输出用右对齐方式,缺位的用0补齐,这样最快捷啦!2、算法的时间复杂度和空间复杂度由于没有进行循环嵌套之类的运算,只有简单的循环语句,所以时间复杂度T(O)=O(n),在数据的存储方面,除了车牌号用的是数组以外,便道用的是顺序栈,这些是提前要申请一定的存储空间的,这样非动态分配的存储空间,在某些时候是会导致空间的浪费,增加其空间复杂度。