问题描述
设停车厂只有一个可停放5辆汽车的狭长通道,且只有一个大门可供汽车进出。汽车在停车场内按车辆到达的先后顺序依次排列,若车场内已停满几辆汽车,则后来的汽车只能在门外的便道上等候,一旦停车场内有车开走,则排在便道上的第一辆车即可进入;当停车场内某辆车要离开时,由于停车场是狭长的通道,在它之后开入的车辆必须先退出车场为它让路,待该辆车开出大门后,为它让路的车辆再按原次序进入车场。在这里假设汽车不能从便道上开走。
基本要求
以栈模拟停车场,以队列模拟车场外的便道,按照从终端输入数据序列进行模拟管理。每一组输入数据包括三个数据项:汽车“到达”或“离去”信息、汽车牌照号码以及到达或离去的时刻。对每一组输入数据进行操作后的输出信息为:若是车辆到达,则输出车辆在停车场内或便道上的停车位置;若是车辆离去,则输出车辆在停车场内停留的时间和应缴纳的费用(1小时以内不收费,1小时以上收费标准为2元/小时,在便道上停留的时间不收费)。栈以顺序结构出现,队列以链表结构实现。
问题分析
(一)算法设计思路:
使用栈模拟停车场,使用队列模拟便道,设一个辅助栈,临时停放为给要离去的汽车让路而从停车场退出来的汽车。设置一个字符串数组存储停车场上的车辆车牌号,车辆离开时,遍历此数组;若有此车,则将比它后进的车辆压入辅助栈,开走请求离开的车辆,并输出信息,再将辅助栈中车辆压入停车场;查询此时便道上是否有车辆,若有则将便道上第一辆车驶入停车场,开始收费。
(二)使用模块及变量的说明
1、typedef struct car//定义车辆信息
2、typedef struct carstop//定义停车栈和辅助栈
3、typedef struct carw//定义便道队列,链表实现
4、carlist* Init_carlist()//初始化便道链队
5、void gowait(carlist *w,string a) //进入便道队列
6、void showtime(time_t now)//显示时间
7、void gostop(carstop* s, carlist*w, string a,string *carNum) //进入停车场,入栈操作
8、void outstop(carstop* s, int i) //停车场车辆离开并输出收费信息
9、void movcar(carstop* s1, carstop* s2, int a, string* carNum) //停车栈中不离开的车辆进入辅助栈,车辆离开,辅助栈车辆进入停车场
10、void go_stop(carstop* s, carlist* w,string *carNum) //便道第一辆车进入停车栈
11、void showstop(carstop* s) //显示停车场的车辆信息
12、void showait(carlist* w) //显示便道车辆信息
13、int main()//主调函数
实验代码
C++版
#include <iostream>
#include<ctime>
#define _CRT_SECURE_NO_WARNINGS
using namespace std;
#define MAX 5 //停车栈与辅助栈最大容量
//定义车辆信息
typedef struct car {
time_t intime; //进车时间
time_t outime; //出车时间
string carNum; //车牌号
}car;
//定义停车栈和辅助栈
typedef struct carstop {
car cars[MAX];
int top;
}carstop;
//定义便道队列,链表实现
typedef struct carw {
string carNum; //存储区域
carw* next;
}carNode;
typedef struct {
carNode* front, * rear;
}carlist;
//初始化便道链队
carlist* Init_carlist() {
carlist* w=new carlist;
carNode* p=new carNode;
p->next = NULL;
w->front = p;
w->rear = p;
return w;
}
//进入便道队列
void gowait(carlist *w,string a) { //带头结点,尾插法
carNode* p;
p = new carNode;
p->carNum = a;
p->next = NULL;
w->rear ->next= p;
w->rear = p;
cout << "车辆" << a << "进入便道" << endl;
}
//显示时间
void showtime(time_t now) {
struct tm* ltm = localtime(&now);
cout << 1900 + ltm->tm_year <<"年"<< 1 + ltm->tm_mon <<"月"<< ltm->tm_mday << "日";
int hour = ltm->tm_hour % 24;
cout << hour <<":" << ltm->tm_min <<":" << ltm->tm_sec;
}
//进入停车场,入栈操作
void gostop(carstop* s, carlist*w, string a,string *carNum) {
if (s->top == MAX - 1) {
cout << "停车场已满," ; //停车场已满
gowait(w, a);
}
else {
car* c = new car;
c->carNum = a;
c->intime = time(0);
s->top++;
s->cars[s->top] = *c;
cout << "车辆" << a << "在";
showtime(c->intime);
cout<< "进入停车场" << s->top + 1 <<"号位,开始计时收费" << endl;
carNum[s->top + 1] = a;
}
}
//停车场车辆离开并输出收费信息
void outstop(carstop* s, int i) { //传入停车栈和离开车辆下标
s->cars[i].outime = time(0);
cout << "车辆" << s->cars[i].carNum << "离开停车场,离开时间为:";
showtime(s->cars[i].outime);
cout << endl;
double a = difftime(s->cars[i].outime, s->cars[i].intime);//a为double类型单位秒
int b = ((int)a) / 3600; //计算停车的费用
cout << "车辆停留时间为:" << b << "小时 应交停车费:" << 2 * b << "元" << endl;
s->top--;
}
//停车栈中不离开的车辆进入辅助栈,车辆离开,辅助栈车辆进入停车场
void movcar(carstop* s1, carstop* s2, int a, string* carNum) { //w1为停车栈,w2为辅助栈,a为车辆下标位置
int j = 0;
int i = s1->top ;
while (i > a) { //让路进入辅助栈
s2->cars[j] = s1->cars[i];
cout << s1->cars[i].carNum << "让路" << endl;
j++; s2->top++;
i--; s1->top--;
}
outstop(s1, a); //车辆离开Pop
j--;
while (s2->top !=-1 && j >= 0) { //让路车辆回到停车场
s1->cars[i] = s2->cars[j];
carNum[i+1] = s1->cars[i].carNum;
carNum[i+2] = "";
j--; s2->top--;
i++; s1->top++;
}
}
//便道第一辆车进入停车栈
void go_stop(carstop* s, carlist* w,string *carNum) { //P为停车栈,w为便道
if (w->front != w->rear ) {
carNode *q = w->front ->next ;
string p = q->carNum;
if (q->next != NULL) {
w->front->next = q->next;
delete q;
}
gostop(s, w, p, carNum);
}
else cout << "便道无等待车辆" << endl;
}
//显示停车场的车辆信息
void showstop(carstop* s) {
if (s->top == -1) cout << "停车场内无车辆" << endl;
else {
cout << "当前停车场:" << endl;
for (int i = 1; i <= s->top+1; i++) {
cout << i << "号位,停放车辆" << s->cars[i - 1].carNum <<
"进入时间为:";
showtime(s->cars[i - 1].intime);
cout<< endl;
}
}
}
//显示便道车辆信息
void showait(carlist* w) {
if (w->front == w->rear) cout << "便道无车辆" << endl;
else {
int i = 1;
carNode* p; p = w->front->next ;
cout << "当前便道:";
while (p != w->rear) {
cout << i++ << "号位停放" << p->carNum << " ";
p = p->next;
}cout << i++ << "号位停放" << w->rear ->carNum << " ";
cout << endl;
}
}
//显示菜单栏
int menu() {
int a;
cout << "**********菜单栏**********" << endl;
cout << "1.查询当前停车场状态" << endl;
cout << "2.车辆进入" << endl;
cout << "3.车辆离开" << endl;
cout << "0.退出" << endl;
cout << "**************************" << endl;
cout << "请选择功能:" ;
cin >> a;
if (a >= 0 && a <= 3) {
return a;
}
else return -1;
}
int main() {
carlist* w = Init_carlist();
carstop* s = new carstop, * s2 = new carstop;
s->top = -1; s2->top = -1;
string c;
string carNum[6], outcar; //字符串数组记录停车场的车牌;要离开的车辆车牌号
int a=menu();
while (a != 0) {
switch (a) {
case -1:
cout << "输入有误,请重新输入!" << endl;
a = menu();
break;
case 1:
showstop(s); showait(w);
a = menu();
break;
case 2:
cout << "请输入车牌号:";
cin >> c;
gostop(s, w, c,carNum);
a = menu();
break;
case 3:
cout<<"请输入车牌号:";
cin >> outcar;
int flag = 0;
for (int i = 1; i <= 6; i++) {
if (carNum[i] == outcar) {
flag = 1;
if (i-1 == s->top) {
outstop(s, i-1);
go_stop(s, w, carNum);
}
else {
movcar(s, s2, i - 1, carNum);
go_stop(s, w, carNum);
}
}
}
if(flag==0) cout << "未查询到此车" << endl;
a = menu();
break;
}
}
cout << "已退出,欢迎下次使用!" << endl;
delete s, s2;
carNode* d = w->front, * d2 = NULL;
while (d != w->rear) {
d2= d;
d = d->next;
delete d2;
}
delete w->rear;
system("pause");
return 0;
}
运行结果
实验总结
1、使用一个字符串数组,记录进入停车场的车辆车牌号,出车时遍历字符串数组,若有此车辆出车。
2、退出后,释放空间,便道链队需要遍历释放,而不是只是放第一个结点。
3、使用ctime库函数,显示时间。写了一个显示时间的函数,使时间格式化输出。
4、c4996错误,关闭SDL检查,添加宏定义,警告解决。