停车场管理系统
1 需求分析
1.1问题描述
停车场内只有一个可停放 n 辆汽车的狭长通道,且只有一个大门可供汽车进出。
汽车在停车场内按车辆到达时间的先后顺序,依次由北向南排列(大门在最南端,最先到达的第一辆车停放在停车场的最北端),若车场内已停满 n 辆汽车,则后来的汽车只能在门外的便道上等候,一旦有车开走,则排在便道上的第一辆车即可开入。
当停车场内某辆车要离开时,在它之后开入的车辆必须先退出车场为它让路,待该辆车开出大门外,其它车辆再按原次序进入车场,每辆停放在车场的车在它离开车场时必须按它停留的时间长短交纳费用。
试为停车场编制按上述要求进行管理的模拟程序。
1.2基本要求
以栈模拟停车场,以队列模拟车场外的便道,按照从终端读入的输入数据序列进行模拟管理;
每一组输入数据包括三个数据项:汽车“到达”或“离去”信息、汽车牌照号码及到达或离去的时刻,对每一组输入数据进行操作后的输出数据为:若是车辆到达,则输出汽车在停车场内或便道上的停车位置;若是车离去,则输出汽车在停车场内停留的时间和应交纳的费用(在便道上停留的时间不收费);
栈以顺序结构实现,队列以链表实现。
2 概要设计
2.1数据结构
2.1.1时间类
时间是进行收费的依据,此处假定时间在一天之内。时间类既可以表示一个时刻,也可以表示一段时间长度。
时间类数据成员:
- hour:指示时钟
- minute:指示分钟
时间类成员函数:
- Time:构造函数
- operator+=:进行时间的复合加法,即将相加后的结果赋给当前对象,并返回当前对象
- operator-=:进行时间的复合减法,即将相减后的结果赋给当前对象,并返回当前对象
Time |
---|
+ hour: int + minute: int |
+ Time() + Time(hour: int, minute: int) <> operator+(left: const Time&, right: const Time&): Time + operator+=(right: const Time&): Time <> operator-(left: const Time&, right: const Time&): Time + operator-=(right: const Time&): Time <> operator==(left: const Time&, right: const Time&): bool <> operator<(left: const Time&, right: const Time&): bool <> operator<=(left: const Time&, right: const Time&): bool <> operator>(left: const Time&, right: const Time&): bool <> operator>=(left: const Time&, right: const Time&): bool <> operator<<(os: ostream&, t: const Time&): ostream& |
时间类非成员函数:
-
operator+:时间加法
-
operator-:时间减法
-
operator==:判断时间是否相等
-
operator<:判断前一个时间是否小于后一个时间
-
operator<=:判断前一个时间是否小于等于后一个时间
-
operator>:判断前一个时间是否大于后一个时间
-
operator>=:判断前一个时间是否大于等于后一个时间
-
operator<<:将时间输出到输出流中
2.1.2汽车类
汽车是后续操作的基础元素,结合题目要求,汽车应包含牌照号码、停车时间等数据。汽车类数据成员:
- number:汽车牌照号码
- lastTime:最后一次在停车场(栈)内的时刻
- parking: 停车时间
lastTime 和 parking 并非实时更新,而是当有车辆到达或离去时才会做相应的改变。
Car |
---|
- number: string - lastTime: Time - parking: Time |
+ Car() + Car(number: string) + operation==(car: const Car&): bool + updateLastTime(time: const Time&) + setLastTime(time: const Time&) + getLastTime(): Time + addParkingTime(time: const Time&) <> operator<<(os: ostream&, t: const Car&): ostream& |
汽车类成员函数:
- Car:构造函数
- operation==:判断是否为同一辆汽车(只判断牌照号码)
- updateLastTime:设置最后一次在停车场(栈)内的时刻,并增加停车时间
- setLastTime:设置最后一次在停车场(栈)内的时刻
- getLastTime:获取最后一次在停车场(栈)内的时刻
- addParkingTime:增加停车时间
- getParingTime:获取停车时间
汽车类非成员函数:
- operator<<:将汽车信息输出到输出流中
2.1.3栈类模板
栈是一种“先进后出”的数据结构,此处用于组织停车场内汽车的停放。我们选用线性结构实现栈,并进行模板化,以便下次复用。
模板参数 T1,表示基础元素类型,在编写代码时,可设为 Car。
从模板参数 T,定义出以下几种嵌套类型:
- T −→ value_type,基础元素类型
- T∗ −→ pointer,指针
- const T∗ −→ const_pointer,常指针
- T & −→ reference,引用
- const T & −→ const_reference,常引用
Stack |
---|
- _top: pointer - _base: pointer - _cap: pointer |
+ Stack() ∼ Stack() + operator[](pos: size_type): reference + operator[](pos: size_type): const_reference + top(): reference + top(): const_reference + empty(): bool + size(): size_type + capacity(): size_type + push(data: const_reference) + pop() + index(data: const_reference): size_type + print() + reserve(newCapacity: size_type) |
栈类数据成员:
- _top 栈顶
- _base 栈底
- _cap 当前栈存储空间的尾部
特别指出,栈顶指针 _top,其初值指向栈底,即 _top == _base 可作为栈空的标记,每当插入新的栈顶元素时,指针 _top 增 1;删除栈顶元素时,指针 _top 减 1,因此,非空栈中的栈顶指针始终在栈顶元素的下一个位置上。
_cap 指针则仅指示当前栈存储空间的尾部,其真实地址则是尾部的下一个位置。这两种设计都是为了方便程序的编写。
栈类成员函数:
- Stack:构造函数
- ∼Stack:析构函数
- operator[]:访问器
- top:访问栈顶
size_type 是无符号超长整型,源于 std::size_t。
设置访问器仅用于方便本次项目的代码编写,破坏了栈的设计原则,在编写一般程序时,不应在栈中设置访问器。
- empty:判断栈是否为空
- size:获取栈长
- capacity:获取栈的存储容量
- push:入栈
- pop:出栈
- index:寻找元素的第一个位置
- print:打印栈
- reserve:重新分配存储空间容量
2.1.4队列类模板
队列,是一种“先进先出”的数据结构,此处可用于模拟停车场外的便道。我们选用链式结构实现队列,并进行模板化,以便下次复用。
模板参数 T1,表示基础元素类型,在编写代码时,可设为 Car。
首先设计一个队列节点类,与链表节点类似:
QNode |
---|
- _data: value_type - _next: node_ptr |
+ QNode() + QNode(data: const_reference, next = nullptr: const_node_ptr) + data(): reference + data(): const_reference + setData(data: const_reference) + next(): node_ptr + next(): const_node_ptr + setNext(next: const_node_ptr) |
队列节点类数据成员:
_data:数据域
从模板参数 T 定义出的嵌套类型与 Stack 类相似,但增加了 4 个嵌套定义:
- QNode < T > ∗ −→ node*_ptr,节点指针
- const QNode < T > ∗ −→ const*_node_ptr,节点常指针
- QNode < T > & −→ node_ref ,节点引用
- const QNode < T >* & −→ const_node_ref ,节点常引用
_next:指针域,指向下一节点
队列节点类成员函数:
- QNode:构造函数
- data:返回数据域
- setData:设置数据域
- next:返回下一节点
- setNext:设置下一节点
然后以队列节点为基础设计队列类模板:
Queue |
---|
- _front: node_ptr - _back: node_ptr |
+ Queue() ∼ Queue() + front(): reference + front(): const_reference + back(): reference + back(): const_reference + empty(): bool + size(): size_type + push(data: const_reference) + pop() + erase(data: const_reference) + print() |
队列类数据成员:
- _front:队头指针
- _back:队尾指针
队列类成员函数:
- Queue:构造函数
- ∼* Queue:析构函数
- front:返回队头
- back:返回队尾
- empty:返回队列是否为空
- size:返回队列的大小
- push:入队列
- pop:出队列
- erase:直接擦除第一个值为 data 的节点1
- print:打印队列
2.1.5停车场类
依据题意,整个停车场包含一个有限容量的停车场(栈)和场外的便道(队列)。将栈和队列综合,封装成一个停车场类。
ParkLot |
---|
- s: Stack - q: Queue - size: size_t |
+ ParkLot() + ParkLot(size: size_t) + add(carNumber: const string&, arriveTime: const Time&) + reduce(carNumber: const string&, leaveTime: const Time&) + print() |
停车场类数据成员:
- s:停车场 (栈)
- q:便道 (队列)
- size:停车场容量 (栈最大大小)
停车场类函数成员:
- ParkLot:构造函数
- add:到达汽车
- reduce:离开汽车
- print:打印停车场
设计此函数仅用于方便本项目代码的编写,破坏了队列的设计原则,在编写一般程序时,不应在队列中设置此函数。
4测试分析
使用 G++ 编译器编译本实例,运行测试。
图 1: 初始化及菜单
图 2: 到达停车场
图 3: 到达便道
图 4: 从停车场离去车辆
图 5: 没有找到车辆
图 6: 从便道离去车辆
图 7: 显示停车情况
5总结
通过本次项目实践,熟练地掌握了栈、队列这两种数据结构,并实现了顺序栈、链队列模板的编写,增强了编码能力。
结合栈、队列设计停车场管理系统,使得栈和队列得到实际应用。在实践过程中,需要借助栈和队列对停车场内以及便道上的车辆进行有序地调度,增强了离散事件问题的模拟算法设计与求解的能力。同时,设计入栈、出栈、入队列、出队列、计时收费等系列算法的设计,对计算机如何模拟实际问题有了较好的感性理解。
♻️ 资源
大小: 6.42MB
➡️ 资源下载:https://download.csdn.net/download/s1t16/87248068