数据结构设计
停车场管理系统的设计与实现
·一、设计内容
停车场有M个入口,P个出口,停车场共有N个车位,其中每5个车位为一个小型立体车库,先来后到原则进行入场,入场后开始进行计费。若停车场满了之后,门口的车一次排队,出来一辆车之后,放行一辆车再入场。要求:
1)每个入口使用队列结构模拟排队场景,排序车辆需要记录排队时间,根据时间先后进场放行。
2)每个小型立体车库只用散列表进行模拟入库及出库。
3)计费原则:15分钟以下免费,超过15分钟按0.5元/15分钟。小型车夜间停车1元/小时。
2
使用编程语言实现停车场管理系统。至少实现:
·数据结构选择合理,能够实现动态输人·能够模拟排队场景
·能够模拟入库及出库、计费等功能。
二、要求 ·界面美观。
c++ 实现停车场管理系统
#include<string.h>
#include<malloc.h>
#include<stdio.h>
#include<stdlib.h>
#define TRUE 1
#define FALSE 0
#define OK 1
#define ERROR 0
#define STACK_INIT_SIZE 5
#define STACK_INCREMENT 2
typedef int SElemType;
typedef int Status;
//定义车的基本信息
typedef struct
{
int arrive[2]; //arrive[0]、arrive[1]分别记录车辆进入的时、分
int leave[2]; //leave[0]、leave[1]分别记录车车辆离开的时、分
char num[10]; //车牌信息
}car;
//定义队列(队列的链式存储结构)
typedef struct QNode
{
car data;
QNode *next;
}QNode, *QueuePtr; //给队列添加数据域和指针域
typedef struct
{
QueuePtr front; //队头指针
QueuePtr rear; //队尾指针
}LinkQueue;
//定义栈 (栈的链式存储结构)
typedef struct StackNode
{
SElemType data;
struct StackNode *next;
}StackNode, *StackPtr;
typedef struct SqStack
{
int base; //栈底指针
int top; //栈顶指针
car parkcar[STACK_INIT_SIZE];
int stacksize; //栈可用的最大容量
}SqStack;
//构造一个空栈一个空队列即创建一个停车场
void CreatePark(SqStack &S, LinkQueue &Q)
{
S.base = S.top = 0; //base初始为top,空栈
Q.front = Q.rear = (QueuePtr)malloc(sizeof(QNode));
if (!Q.front)exit(0);
Q.front->next = NULL; //头结点的指针域置空
printf("恭喜停车场创建成功!\n");
}
//遍历栈和队列即显示停车情况
//停车场的情况
void ShowStack(SqStack &S)
{
int j = S.base; //S.base栈底位置记为j
while (j < S.top) //当S.top位置大于栈底位置(栈中有存储内容)
{
printf("%s %d:%d %d",S.parkcar[j].num,S.parkcar[j].arrive[0],S.parkcar[j].arrive[1],j+1);
printf("\n");
j++;
}
}
//临时停车点的情况(利用队列先进先出特点)
void ShowQueue(LinkQueue &Q)
{
QueuePtr p = Q.front->next; //链队指针p指向头结点的指针域
while (p) //当p非空,进行循环
{
car c = p->data; //队列的数据域赋给car型变量c
printf("%s %d:%d",c.num,c.arrive[0],c.arrive[1]); //输出车辆信息
if (p != Q.rear) //若p与队尾所指位置不同
{
p = p->next; //指针后移
}
else
{
Q.rear = Q.front;
p = NULL;
}
}
}
//总体情况的显示
void ShowInformation(SqStack &S,LinkQueue &Q)
{
if (S.base != S.top) //栈顶与栈底不在同一位置(栈非空)
{
printf("车牌号 停车时间 停车位置\n");
ShowStack(S);
}
else //输出队列中的信息
{
ShowQueue(Q);
}
}
//一些基本操作:入栈,入队
//入栈即汽车进入停车场
void PushSqStack(SqStack &S, car ch) //入栈
{
printf("请输入当前小时:");
scanf("%d",&ch.arrive[0]);
printf("请输入当前分钟:");
scanf("%d",&ch.arrive[1]);
S.parkcar[S.top++] = ch; //记录车辆信息,栈顶上移
printf("已将您的车停好,车的位置是:%d\n", S.top);
}
//入队列即进入临时停车点
void PushQueue(LinkQueue &Q, car ch)
{
QueuePtr p = (QueuePtr)malloc(sizeof(QNode)); //链队指针p
if (!p){exit(0);}
p->data = ch; //将车辆信息赋给队列数据域
p->next = NULL; //p的指针域置为空
Q.rear->next = p;
Q.rear = p;
printf("对不起,停车场已满,请您在临时停车区等待!");
ShowQueue(Q);
}
//出栈,出队列
//出队列即进入停车场
car PopQueue(LinkQueue &Q)
{
car ch;
QueuePtr p;
p = Q.front->next; //链队指针p指向头结点的指针域
ch = p->data; //车辆信息ch赋给头结点的数据域
Q.front->next = p->next; //指针后移
if (Q.rear == p)
{
Q.rear = Q.front;
}
free(p);
return ch;
}
//判断队列是否为空
int QueueEmpty(LinkQueue &Q)
{
if (Q.front == Q.rear)return 1; // 队头、队尾指针的值相同,队空
else return 0;
}
//出栈即离开停车场
void PopSqStack(SqStack &S, LinkQueue &Q)//(双栈共享一个栈空间)
{
int i;
if (S.base == S.top) //栈头、栈尾指针的值相同,栈空
{
printf("停车场没有车!\n");
exit(0);
}
SqStack sq; //定义另一个栈,栈2
printf("请输入您的停车位置:\n");
scanf("%d",&i);
sq.base = sq.top = 0; //base初始为top,空栈
while (S.top > i) //找到车辆位置,结束循环
sq.parkcar[sq.top++] = S.parkcar[--S.top];//栈2的顶指针与栈顶指针移动
int n = --S.top; //n记录车辆
printf("请输入当前小时:\n");
scanf("%d",&S.parkcar[n].leave[0]);
printf("请输入当前分钟:\n");
scanf("%d",&S.parkcar[n].leave[1]);
int time = (S.parkcar[n].leave[0] - S.parkcar[n].arrive[0]) * 60 + (S.parkcar[n].leave[1] - S.parkcar[n].arrive[1] );//按分钟计算车辆停车时间
double money = time*0.05; //计算所需费用
printf("您的停车时长为:%d分钟\n", time);
printf("你本次停车的费用为%lf:",money);
printf("\n");
printf("谢谢您使用本系统,欢迎下次光临!\n");
while (sq.top > sq.base) //当栈2的头、尾指针位置相同,结束循环
S.parkcar[S.top++] = sq.parkcar[--sq.top];
if (QueueEmpty(Q)) //队列非空
{
S.parkcar[S.top] = PopQueue(Q); //便道中的第一辆车进入停车场
printf("车牌号为%s的车从临时停车点进入停车场,停车位置为%d\n", S.parkcar[S.top].num, S.top + 1);
printf("请输入当前小时:%d\n");
scanf("%d",&S.parkcar[S.top].arrive[0]);
printf("请输入当前分钟:%d\n");
scanf("%d",&S.parkcar[S.top].arrive[1]);
S.top++;
}
}
//构建整个停车场
//登记车辆信息
car Register()
{
car c;
printf("请输入您的车牌号:");
scanf("%s",&c.num);
c.arrive[0] = 0;
c.arrive[1] = 0;
c.leave[0] = 0;
c.leave[1] = 0;
return c;
}
//判断一辆车到达后是否需要构造队列
void Judge(SqStack &S, LinkQueue &Q)
{
car ch = Register();
if (S.top == STACK_INIT_SIZE) //如果栈满,推入队列,否则推入栈
{
PushQueue(Q, ch);
}
else
{
PushSqStack(S, ch);
}
}
//功能目录函数
void menu()
{
printf("-------------------------------------------\n");
printf("| |\n");
printf("| 欢迎使用停车场管理系统 |\n");
printf("| |\n");
printf("| |\n");
printf("| 请选择您需要的功能 |\n");
printf("| 1.创建停车场 |\n");
printf("| 2.车进停车场 |\n");
printf("| 3.车出停车场 |\n");
printf("| 4.查看停车情况 |\n");
printf("| 0.退出系统 |\n");
printf("| |\n");
printf("-------------------------------------------\n");
}
//主函数
int main()
{
SqStack S;
LinkQueue Q;
int i;
menu(); //功能目录
while(1)
{
printf("请继续输入你的选择:");
scanf("%d",&i);
switch (i)
{
case 1:CreatePark(S,Q);//构造一个空栈一个空队列即创建一个停车场
system("pause");
break;
case 2:Judge(S, Q); //判断一辆车到达后是否需要构造队列
system("pause");
break;
case 3:PopSqStack(S,Q);//出栈即离开停车场
system("pause");
break;
case 4:ShowInformation(S,Q);//总体情况的显示
system("pause");
break;
case 0:printf("已退出,谢谢使用!");
return 0;
default:printf("对不起,您的输入有误,已强制退出,请重新登录!");
system("pause");
}
}
return 0;
}
不知道你这个问题是否已经解决, 如果还没有解决的话:需要为一个停车场设计一个管理系统,它有M个入口和P个出口,共有N个车位,其中每5个车位为一个小型立体车库。希望使用队列来模拟每个入口的车辆排队场景,并按照先来先服务的原则放行车辆。每个小型车库将使用散列表来模拟车辆的入库和出库过程。对于计费,停车场将使用以下规则: 停车时间不足15分钟免费,超过15分钟按0.5元/15分钟计费,夜间停车1元/小时。并且需要优化界面,使其美观易用。
停车场使用一个长度为N的数组来存储停车位,其中每5个车位为一个小型立体车库,可以使用一个二维数组来表示。
int parking_lot[N]; // 停车场
int parking_garage[N/5][5]; // 小型立体车库
为了存储车辆的信息,可以定义一个结构体vehicle
,包含车牌号、进入时间和类型(小型车位 or 立体车库)等信息。
typedef struct vehicle {
char plate_number[10]; // 车牌号
time_t entry_time; // 进入时间
int type; // 车辆类型:0表示小型车位,1表示立体车库
} vehicle;
使用队列来模拟每个入口的车辆排队场景。可以使用链式队列或顺序队列实现。为了便于管理和操作,定义一个结构体queue
存储队列信息,包括车辆数目、队首和队尾指针等信息。
typedef struct node {
vehicle data; // 数据域
struct node *next; // 下一结点指针
}node;
typedef struct queue {
node *front; // 队首指针
node *rear; // 队尾指针
int count; // 车辆数目
} queue;
每个小型车库将使用散列表来模拟车辆的入库和出库过程。为了方便使用,可以使用开放地址法实现散列表,即使用一个数组存储车辆信息,并使用一个哈希函数将车辆关键字(车牌号)映射到对应的数组下标,发生冲突时,使用线性探测法来解决。
typedef struct HNode {
char key[10]; // 关键字:车牌号,长度不超过10
vehicle value; // 值:车辆信息
} HNode;
HNode hashtable[N/5*3]; // 一个小型车库最多存放3*N/5辆车
停车场管理系统的界面需要美观易用,可以使用QT框架来设计操作界面。QT有很多控件可以使用,如QPushButton、QLineEdit、QLabel等,可以根据需要灵活使用。
计费规则如下:
对于停车时间的计算,可以使用C++标准库中的time_t类型来获取时间戳,然后计算时间差来判断停车时间。
计费时可以根据停车时间来计算费用,然后在界面上输出。
参考GPT:
#include <iostream>
#include <queue>
#include <unordered_map>
#include <ctime>
using namespace std;
struct Car {
string licensePlate;
time_t arrivalTime;
};
class ParkingLot {
private:
int numEntrances; // 入口数量
int numExits; // 出口数量
int totalCapacity; // 停车场总容量
int numGarages; // 小型立体车库数量
int garageCapacity; // 每个小型立体车库的容量
queue<Car> entranceQueues; // 入口排队队列
unordered_map<int, queue<Car>> garages; // 小型立体车库
unordered_map<string, time_t> parkedCars; // 停车记录
public:
ParkingLot(int entrances, int exits, int capacity, int garages, int garageCapacity) {
numEntrances = entrances;
numExits = exits;
totalCapacity = capacity;
numGarages = garages;
this->garageCapacity = garageCapacity;
}
void enterParkingLot(const string& licensePlate) {
time_t currentTime = time(0);
Car newCar;
newCar.licensePlate = licensePlate;
newCar.arrivalTime = currentTime;
// 如果停车场已满,将车辆加入入口排队队列
if (parkedCars.size() == totalCapacity) {
entranceQueues.push(newCar);
cout << "停车场已满,车辆 " << licensePlate << " 进入排队队列" << endl;
return;
}
// 如果有可用的小型立体车库,将车辆存入小型立体车库
for (int i = 1; i <= numGarages; i++) {
if (garages[i].size() < garageCapacity) {
garages[i].push(newCar);
parkedCars[licensePlate] = currentTime;
cout << "车辆 " << licensePlate << " 进入小型立体车库 " << i << endl;
return;
}
}
// 如果没有可用的小型立体车库,将车辆存入普通停车位
parkedCars[licensePlate] = currentTime;
cout << "车辆 " << licensePlate << " 进入普通停车位" << endl;
}
void exitParkingLot(const string& licensePlate) {
time_t currentTime = time(0);
// 检查是否在小型立体车库中
for (int i = 1; i <= numGarages; i++) {
if (!garages[i].empty() && garages[i].front().licensePlate == licensePlate) {
Car car = garages[i].front();
garages[i].pop();
calculateAndPrintBill(car, currentTime);
return;
}
}
// 检查是否在普通停车位中
if (parkedCars.count(licensePlate)) {
calculateAndPrintBill(licensePlate, currentTime);
parkedCars.erase(licensePlate);
return;
}
cout << "车辆 " << licensePlate << " 未找到" << endl;
}
void calculateAndPrintBill(const Car& car, time_t exitTime) {
double duration = difftime(exitTime, car.arrivalTime) / 60.0; // 转换为分钟
cout << "车辆 " << car.licensePlate << " 停车时间: " << duration << " 分钟" << endl;
if (duration <= 15) {
cout << "停车费用: 免费" << endl;
} else {
double cost = 0.5 * ((int)duration / 15);
if (isNightTime(exitTime)) {
cost += 1.0; // 夜间停车费用
}
cout << "停车费用: " << cost << " 元" << endl;
}
}
void calculateAndPrintBill(const string& licensePlate, time_t exitTime) {
time_t arrivalTime = parkedCars[licensePlate];
Car car;
car.licensePlate = licensePlate;
car.arrivalTime = arrivalTime;
calculateAndPrintBill(car, exitTime);
}
bool isNightTime(time_t time) {
struct tm* timeinfo;
timeinfo = localtime(&time);
int hour = timeinfo->tm_hour;
return hour >= 20 || hour <= 6; // 假设晚上8点到早上6点为夜间
}
};
int main() {
ParkingLot parkingLot(2, 2, 10, 2, 5);
parkingLot.enterParkingLot("ABC123"); // 车辆 ABC123 进入小型立体车库 1
parkingLot.enterParkingLot("XYZ789"); // 车辆 XYZ789 进入小型立体车库 2
parkingLot.enterParkingLot("DEF456"); // 车辆 DEF456 进入普通停车位
parkingLot.enterParkingLot("GHI789"); // 车辆 GHI789 进入普通停车位
parkingLot.enterParkingLot("JKL012"); // 车辆 JKL012 进入排队队列
parkingLot.exitParkingLot("ABC123"); // 车辆 ABC123 停车时间: 0.5 分钟,停车费用: 免费
parkingLot.exitParkingLot("DEF456"); // 车辆 DEF456 停车时间: 0.5 分钟,停车费用: 免费
parkingLot.exitParkingLot("XYZ789"); // 车辆 XYZ789 停车时间: 0.5 分钟,停车费用: 免费
parkingLot.exitParkingLot("GHI789"); // 车辆 GHI789 停车时间: 0.5 分钟,停车费用: 免费
parkingLot.exitParkingLot("JKL012"); // 车辆 JKL012 未找到
return 0;
}