设停车场是一个可停放n辆汽车的狭长通道,且只有一个大门可供汽车进出。汽车在停车场内按车辆到达时间的先后顺序,依次由北向南排列(大门在最南端,最先到达的第一辆车停放在车场的最北端),若车场内已停满n辆汽车,则后来的汽车只能在门外的便道上等候,一旦有车开走,则排在便道上的第一辆车即可开入;当停车场内某辆车要离开时,在它之后进入的车辆必须先退出车场为它让路,待该车辆开出大门外,其它车辆再按照原次序进入车场,每辆停放在车场的车在它离开停车场时必须按它停留的时间长短交纳费用。试为停车场编制按上述要求进行管理的模拟程序。
(1)以栈模拟停车场,以队列模拟车场外的便道,栈以顺序存储结构实现,队列以链表存储结构实现。
(2)按照从终端读入的输入数据序列进行模拟管理。每一组输入数据包括三个数据项:汽车“到达”或“离去”信息、汽车牌照号码以及到达或离去的时刻。对每一组输入数据进行操作后的输出信息为:若是车辆到达,则输出汽车在停车场内或便道上的停车位置;若是车辆离去,则输出汽车在停车场内停留的时间和应交纳的费用(在便道上停留的时间不收费,便道上的车辆也可直接开走)。
【结构体定义】:
需要定义栈和队列。栈是顺序栈,队列是链式队列。
【逻辑分析】:
一:对于输入的数据的合法性判断包括以下两个方面
(其实合法性可能要判断很多但是本代码只考虑了以下这些暂时足够了)
1.输入的车的时间需要保证后一辆大于前一辆
添加一个preTime变量记录前一辆车的时间,每次进车都更新时间。
2.状态码只能是0或1
如果不合法提示输入错误
二:对于通过以上判断的数据,需根据状态码来进行不同的处理。
若状态码是0,代表进车,需要停车。
若状态码是1,代表出车,需要计费。
同时!需要将队列中的车添加到栈中并更新进去时候的时间的值!
在此可添加一个对于id的判断。
若进车必须保证里边没有同id的车,若出车必须保证里边有同id的车。
( 虽说对于id重复的车那是假号牌,那是交警队的事情。)
输入的数据为一组三个数
第一个数是车的状态码(结构体中的state):0/1代表进车/出车
第二个数是车的车牌号 (结构体中的id)
第三个数是车的时间 (结构体中的id)
车辆到达则输出位置,离去则输出停留时间和费用。
#include
#include
#define MAXSIZE 100//用来定义栈的最大值
#define portMaxCarNum 3//可以用来修改停车场可容纳最大车数量
typedef struct Car {
int state;
int id;
int time;
Car * next;//在链式结构时用来指向下一个 在栈中就当做不存在这个属性
} Car; //结构体 车
//栈定义
typedef struct {
Car *base;
int top;
} Stack;//结构体 顺序栈
//顺序栈的定义是一个基底指针和一个top值,取值的时候是以数组的形式,本来应该加个maxsize
//队列定义
typedef struct Queue {
struct Car* front;//队头指针和队尾指针
struct Car* rear;
} Queue;
void InitStack(Stack &S);//初始化栈,包括分配空间和初始赋值
void PushStack(Stack &S, Car C);//压栈
void PopStack(Stack &S, Car &C);//出栈
int OverStack(Stack S);//栈满判定
int findStack(Stack S, int &bef, int id);
//寻找栈中有无这个id,传入的bef用来顺便修改外部变量的值,值为该id的车前有几辆车
void addPortPos(Stack &S, Queue &Q, int time);//将车添加到队列中并更新时间
void backStackCar(Stack &Q, Stack &help, int num);//将停车场中需要出去的车之后的车都退到一个辅助栈中
void frontStackCar(Stack &Q, Stack &help, int num);//将辅助栈中的车再重新停回到停车场中
void InitQueue(Queue &Q);
void EnQueue(Queue &Q, Car C);
void DeQueue(Queue &Q, Car &C);
int EmptyQueue(Queue Q);
int findQueue(Queue Q, Car **p, int id);
//寻找队列中有无这个id的车
//Car**p是为了顺便修改外部的变量,值为需要删除的节点的前一个节点的指针
void money(int time);//计算钱
void bookCarInStackOrQueue(Stack &S, Queue &Q, Car cc);//将后续的车补位
int main() {
//初始化
int preTime = 0;
Stack port;
InitStack(port);
Stack help;
InitStack(help);
Queue que;
InitQueue(que);
Car temp;
temp.next = NULL;
//打印提示
printf("模拟停车场管理系统\n");
printf("输入数据格式如下\n");
printf("第一个数代表状态,第二个数代表车牌号,第三个数代表时间 例如\n");
printf("0 1 2\n1 5 8\n");
printf("请输入你的数据\n");
//数据处理
while (scanf("%d%d%d", &temp.state, &temp.id, &temp.time) != EOF) {
//若时间错误
if (temp.time < preTime)
printf("车辆的时间小于前一辆车的时间,输入错误请重新输入\n");
//若状态码错误
else if (temp.state != 1 && temp.state != 0)
printf("状态码输入错误(只能输入0或1),请重新输入\n");
else {
//状态码是1但是没该车 错误
//状态码是0但是已有车 错误
if (temp.state == 0) {
Car *preCarPoint = NULL;//设置findStack和findQueue函数的时候传入了参数方便下边的停车操作
int preCarNum;
if (findStack(port, preCarNum, temp.id) || findQueue(que, &preCarPoint, temp.id))
printf("车已存在,id重复\n");//返回值是1代表已存在
else {
preTime = temp.time; //更新最后一辆车的时间
bookCarInStackOrQueue(port, que, temp);
}
} else if (temp.state == 1) {
Car *preCarPoint = NULL;
int preCarNum;
int flag1 = findStack(port, preCarNum, temp.id);
int flag2 = findQueue(que, &preCarPoint, temp.id);
if (!flag1 && !flag2)//如果停车场中和通道中都找不到
printf("车不存在,id输入错误\n");
else {
preTime = temp.time; //更新最后一辆车的时间
if (flag1) {
int carNum = port.top - preCarNum - 1;//需要移走carNum个车
backStackCar(port, help, carNum);
Car cc;
PopStack(port, cc);
printf("你停留的时间是%d\n", temp.time - cc.time);
money(temp.time - cc.time);
//重新压入停车场栈
frontStackCar(port, help, carNum);
addPortPos(port, que, temp.time);//将队列中的车压入栈
} else if (flag2) {
printf("id为%d的车在队列中找到\n", temp.id);
printf("你停留的时间是%d 但是在通道不收费\n ", temp.time - preCarPoint->next->time);
preCarPoint->next = preCarPoint->next->next;//将该车节点扔掉
//读者可自行添加free这个节点的代码,没有释放空间有点不规范
}
}
}
}
}
return 0;
}
//顺序栈
void InitStack(Stack &S) {
S.base = (Car*)malloc(sizeof(Car) * MAXSIZE);
S.top = 0;
}
void PushStack(Stack &S, Car C) {
S.base[S.top++] = C;
}
void PopStack(Stack &S, Car &C) {
C = S.base[--S.top];
}
int OverStack(Stack S) {
if (S.top == portMaxCarNum) {
return 1;
} else
return 0;
}
//链式队列
void InitQueue(Queue &Q) {
Q.front = Q.rear = (Car*)malloc(sizeof(Car));
//以队头指针的人下一个元素才是真正的第一个数据
Q.rear->next = NULL;
}
void EnQueue(Queue &Q, Car C) {
Car *p = (Car*)malloc(sizeof(Car));
*p = C;
Q.rear->next = p;
Q.rear = p;
}
void DeQueue(Queue &Q, Car &C) {
Car*p = Q.front->next;
C = *p;
Q.front->next = p->next;
//关于出队列要注意这个if判断 否则rear就被丢掉了
if (p == Q.rear) {
Q.rear = Q.front;
}
free(p);
}
int EmptyQueue(Queue Q) {
if (Q.front == Q.rear) {
return 1;
} else return 0;
}
void addPortPos(Stack &S, Queue &Q, int newTime) {
//要判断通道有没有车 有的话添加 没有的话 不加
if (EmptyQueue(Q)) {
printf("通道中无车无需补位\n");
return;
//时间改变
} else {
Car cc;
DeQueue(Q, cc);
PushStack(S, cc);
S.base[S.top - 1].time = newTime;
printf("后边车辆补位成功并已更新停车时间\n");
}
}
int findStack(Stack S, int &bef, int id) {
int idx = 0;
while (idx < S.top) {
if (S.base[idx].id == id) {
bef = idx;
printf("id为%d的车在栈中找到\n", id);
return 1;
}
idx++;
}
return 0;
}
void money(int time) {
if (time < 10) {
printf("未满十分钟不计费\n");
} else
printf("超过十分钟每分钟计费一元\n你需要付费%d元\n", time - 10);
}
//停车操作
void bookCarInStackOrQueue(Stack &port, Queue &que, Car temp) {
if (!OverStack(port)) {
PushStack(port, temp);
printf("id为%d的车已停车至停车场\n", temp.id);
} else {
EnQueue(que, temp);
printf("id为%d的车已停车至通道\n", temp.id);
}
}
//修改car**p 修改传入的指针的值
int findQueue(Queue Q, Car **p,int id) {
Car *p1,*p2;
p1 = Q.front;
p2 = Q.front->next;
while (p2!= NULL) {
if (p2->id == id) {
*p=p1;
return 1;
}
p1 = p2;
p2 = p2->next;
}
return 0;
}
void backStackCar(Stack &Q, Stack &help, int num) {
Car cc;
while (num--) {
PopStack(Q, cc);
PushStack(help, cc);
}
}
void frontStackCar(Stack &Q, Stack &help, int num) {
Car cc;
while (num--) {
PopStack(help, cc);
PushStack(Q, cc);
}
}