设停车场是一个可停放n辆车的狭长通道,且只有一个大门可供汽车进出。在停车场内,汽车按到达的先后次序,由北向南依次排列(假设大门在最南端)。若车场内已停满n辆车,则后来的汽车需在门外的便道上等候,当有车开走时,便道上的第一辆车即可开入。当停车场内某辆车要离开时,在它之后进入的车辆必须先退出车场为它让路,待该辆车开出大门后,其他车辆再按原次序返回车场。每辆车离开停车场时,应按其停留时间的长短交费(在便道上停留的时间不收费)。
试编写程序,模拟上述管理过程。要求以顺序栈模拟停车场,以链队列模拟便道。从终端读入汽车到达或离去的数据,每组数据包括三项:①是“到达”还是“离去”;②汽车牌照号码;③“到达”或“离去”的时刻(获取系统时间,以秒为单位)。与每组输入信息相应的输出信息为:如果是到达的车辆,则输出其在停车场中或便道上的位置;如果是离去的车辆,则输出其在停车场中停留的时间和应交的费用。(提示:需另设一个栈,临时停放为让路而从车场退出的车。)
第一次发出的代码没有考虑在为要出车库的车挪地方的时候会把真实时间覆盖,现在又在代码中加入了挪动操作,时间不进行改变。
代码如下:
#include<stdio.h>
#include<time.h>
#include<stdlib.h>
#include<string.h>
#include<math.h>
#define PARK_SIZE 5
//定义车的结构体
typedef struct{
int plateNum;
time_t ariTine;//进库时间
time_t leaTime;// 出库时间
}Car;
//车库,用顺序栈表示
typedef struct{
Car park[PARK_SIZE];
int top;
}seqParkList;
//便道,用链队列表示
typedef struct LoadNode{
Car loadnode;
LoadNode *next;
}LoadNode, *LoadList;
//Park1为车库,Park2为中间车库来安放为Park1重要出栈的腾位置的车
seqParkList Park1, Park2;
//Load为便道
LoadList Load;
//初始化车库(栈)
void InitSeqStack(seqParkList *top){
top->top = -1;
}
//初始化便道(队列)
void InitQueue(LoadList *Q){
*Q = (LoadList)malloc(sizeof(LoadNode));
(*Q)->next = NULL;
}
//车出小道(出队列)
int DeletQueue(Car *car){
LoadNode *tcar;
tcar = Load->next;
if(tcar == NULL) return 0;
*car = tcar->loadnode;
Load->next = tcar->next;
free(tcar);
return 1;
}
//车进入小道,并且返回在小道的位置
int EnterQueue(Car *car){
//尾插创建队列
int order = 0;
LoadNode *p1, *p2;
p1 = p2 = Load;
LoadNode *newCar = (LoadNode *)malloc(sizeof(LoadNode));
//找到队尾,顺便返回即将被放在便上车的位置
while(p1 != NULL){
order++;
p2 = p1;
p1 = p1->next;
}
newCar->loadnode = *car;
p2->next = newCar;
newCar->next = NULL;
return order;
}
//判断车库是否停满
bool isFull(){
if(Park1.top == PARK_SIZE - 1) return true;
return false;
}
//车进车库(进栈)
int Push(seqParkList *S, Car *car){
if(S->top == PARK_SIZE - 1) return -1;
S->top++;
//进库时获取当前系统的时间
time(&car->ariTine);
S->park[S->top] = *car;
return S->top;
}
//此时仅做进车库操作,不算更新车进出库时间,因为只是为要出库得车腾地方而进行的动作
int MoveIn(seqParkList *S, Car *car){
if(S->top == PARK_SIZE - 1) return -1;
S->top++;
S->park[S->top] = *car;
return S->top;
}
//车出库(出栈)
int Pop(seqParkList *S, Car *car){
if(S->top == -1) return S->top;
*car = S->park[S->top];
//出车库时获取当前系统的时间
time(&car->leaTime);
S->top--;
return S->top + 1;
}
//此时仅做出车库操作,不算更新车进出库时间,因为只是为要出库得车腾地方而进行的动作
int MoveOut(seqParkList *S, Car *car){
if(S->top == -1) return S->top;
*car = S->park[S->top];
S->top--;
return S->top + 1;
}
//获取车库最外的车(获取栈顶元素)
int GetTop(seqParkList *S, Car *car){
if(S->top == -1) return S->top;
*car = S->park[S->top];
return S->top;
}
//返回车库(栈)是否为空
bool isParkEmpty(seqParkList *park){
if(park->top == -1) return true;
return false;
}
//比较两个车的信息
bool ComCar(Car c1, Car c2){
if(c1.plateNum == c2.plateNum) return true;
return false;
}
//车到达进行相应的操作
void CarIn(Car *car){
int order;
//只要车到来就进入便道,接下来在看要不要进车库
order = EnterQueue(car);
if(isFull()){//如果车库满了则输出一下信息
printf("车在便道 %d位置\n", order);
}
else{//反之车库没满
Car tcar;
DeletQueue(&tcar);//出便道,
order = Push(&Park1, &tcar);//进车库
printf("车在车库 %d位置\n", order + 1);
}
}
//车离开进行相应的操作
void CarOut(Car *car){
if(isParkEmpty(&Park1)){
//如果车库为空便输出相应的信息
printf("Garage is empty!\n");
}
else{
Car c1;
GetTop(&Park1, &c1);
//如果车库最外边不是将要出库的车,便从栈中挪出
//存入另一个栈,直到车库最外边为要出库的车
while(!ComCar(c1, *car)){
MoveOut(&Park1, &c1);
MoveIn(&Park2, &c1);
GetTop(&Park1, &c1);
}
int order = Pop(&Park1, &c1);
//输出出库车在停车场停留时间,并且计算费用,假设10秒2元,11-20s都算4元
printf("此车在车库停留 %lds 并且花费 %d 元(10s/2元)!\n", c1.leaTime - c1.ariTine, (c1.leaTime - c1.ariTine + 9 ) / 10 * 2);
//然后把Park2中的车重新放回Park1
while(!isParkEmpty(&Park2)){
MoveOut(&Park2, &c1);
MoveIn(&Park1, &c1);
}
}
//车库出了一个车,便道上的车便要进入车库
Car c1;
if(DeletQueue(&c1)){
Push(&Park1, &c1);
}
}
int main(){
InitQueue(&Load);
InitSeqStack(&Park1);
InitSeqStack(&Park2);
seqParkList park1, park2;
LoadList Load;
Car car1;
printf("请输入车牌号,动作\n");
char action[6];
scanf("%d %s", &car1.plateNum, action);
//直到输入车牌号为0结束程序
while(car1.plateNum){
if(strcmp(action, "到达") == 0){
CarIn(&car1);
}
else if(strcmp(action, "离去") == 0){
CarOut(&car1);
}
printf("请输入车牌号,动作\n");
scanf("%d %s", &car1.plateNum, action);
}
}
运行结果: