项目实战笔记 | C++ 实现银行排队服务模拟1 数据结构设计 |实验楼项目
2018-01-07 18:24
771 查看
2017年12月11日
使用蒙特卡洛方法,
// Random.hpp
// QueueSystem
//
#ifndefRandom_hpp
#defineRandom_hpp
//语句1#ifndef
标识1
语句2 #define
标识1
语句3 #endif
语句4 ……
语句5 ……
该段代码意思是:如果标识1没有被定义,则重定义标识1,即执行语句2、语句3;如果标识1已经被定义,则直接跳过语句2、语句3,直接执行语句4、语句5、……
#include<cstdlib>//实现了c语言的一些方法
#include<cmath>
class Random {
public:
// [0, 1) 之间的服从均匀分布的随机值
static double uniform(double max = 1) {
return ((double)std::rand() /(RAND_MAX))*max;//这一句有一些绕口,include <cstdlib>可以使用std::中的rand()函数,rand函数生成1_rand_max-1的随机数,然后除以rand_max,最后乘以max,可以生成【0,max)的随机数
}
};
#endif /*Random_hpp */
//
// main.cpp
// QueueSystem
//
#include"QueueSystem.hpp"
#include<iostream>
#include<cstdlib>
int main() {
std::srand((unsigned)std::time(0)); // 使用当前时间作为随机数种子
int total_service_time = 240; // 按分钟计算
int window_num = 4;
int simulate_num = 100000; // 模拟次数
QueueSystem system(total_service_time,window_num);
system.simulate(simulate_num);
std::cout << "The average timeof customer stay in bank: "
<< system.getAvgStayTime()<< std::endl;
std::cout << "The number ofcustomer arrive bank per minute: "
<< system.getAvgCustomers()<< std::endl;
return 0;
}
来源: 实验楼
链接: https://www.shiyanlou.com/courses/557
本课程内容,由作者授权实验楼发布,未经允许,禁止转载、下载及非法传播
//
// Node.hpp
// QueueSystem
//
#ifndef Node_hpp
#define Node_hpp
#include"Random.hpp"
#defineRANDOM_PARAMETER 100
struct Node {
int arrive_time;
int duration;
struct Node *next;//在结构体内定义结构体指针需要加上 struct前缀
// 默认到达事件为0,需要服务的事件是随机的
//类默认是私有的,结构体默认是公有的
Node(int arrive_time = 0,
int duration = Random::uniform(RANDOM_PARAMETER)):
arrive_time(arrive_time),
duration(duration),
next(NULL) {}
};
typedef structNode Node;
typedef structNode Customer;
#endif /* Node_h*/
//endif以后最好加上文件名,以区分该endif是哪个文件的
来源: 实验楼
链接: https://www.shiyanlou.com/courses/557
本课程内容,由作者授权实验楼发布,未经允许,禁止转载、下载及非法传播
接下来是ServiceWindow的设计
// ServiceWindow.hpp
// QueueSystem
//
#ifndefServiceWindow_hpp
#defineServiceWindow_hpp
#include"Node.hpp"
enumWindowStatus {
SERVICE,
IDLE,
};
classServiceWindow {
public:
inline ServiceWindow() //inline内联函数,要求函数非常的简单,里面没有例如while,switch等复杂的结构控制语句,且不能是直接递归函数,且inline是一个建议的语句,是否内联还要看编译器怎么说,在内联处编译器一定要明白函数的定义才行
{
window_status = IDLE;
};
inline bool isIdle() const {
if (window_status == IDLE) {
return true;
} else {
return false;
}
}
inline void serveCustomer(Customer&customer) {
this->customer = customer;
}
inline void setBusy() {
window_status = SERVICE;
}
inline void setIdle() {
window_status = IDLE;
}
inline int getCustomerArriveTime() const {
return customer.arrive_time;
}
inline int getCustomerDuration() const {
return customer.duration;
}
private:
Customer customer;
WindowStatus window_status;//当定义了枚举之后,这里是WindowStatus,则可以将定义的枚举名称当做类名使用,可以直接定义枚举变量,枚举变量可以等于枚举里面的值
};
#endif /*ServiceWindow_hpp */
来源: 实验楼
链接: https://www.shiyanlou.com/courses/557
本课程内容,由作者授权实验楼发布,未经允许,禁止转载、下载及非法传播
这里虽然编写好了顾客的类和窗口的类,当是现在这个程序还是静态的,并没有动起来,我们还需要考虑更多逻辑的问题
这里使用事件驱动的方法来管理整个系统的时间线
Event.hpp:
//
// Event.hpp
// QueueSystem
//
#ifndefEvent_hpp
#defineEvent_hpp
#include"Random.hpp"
#defineRANDOM_PARAMETER 100
struct Event {
int occur_time;
// 使用 -1 表示到达事件, >=0 表示离开事件, 同时数值表示所离开的服务窗口
int event_type;
Event* next;
// 默认为到达事件,发生事件随机
Event(int occur_time =Random::uniform(RANDOM_PARAMETER),//一个类的静态方法除了可以使用.来调用以外,还可以使用::方法来调用
int event_type = -1):
occur_time(occur_time),
event_type(event_type),
next(NULL) {}
};
#endif /*Event_hpp */
来源: 实验楼
链接: https://www.shiyanlou.com/courses/557
本课程内容,由作者授权实验楼发布,未经允许,禁止转载、下载及非法传播
接下来我们来设计存储顾客和窗口以及事件的队列,顾客和窗口的队列直接从后面插入就好了,而事件的队列必须按照发生的时间顺序插入
//
// Event.hpp
// QueueSystem
//
#ifndefEvent_hpp
#defineEvent_hpp
#include"Random.hpp"
#defineRANDOM_PARAMETER 100
struct Event {
int occur_time;
// 使用 -1 表示到达事件, >=0 表示离开事件, 同时数值表示所离开的服务窗口
int event_type;
Event* next;
// 默认为到达事件,发生事件随机
Event(int occur_time =Random::uniform(RANDOM_PARAMETER),
int event_type = -1):
occur_time(occur_time),
event_type(event_type),
next(NULL) {}
};
#endif /*Event_hpp */
来源: 实验楼
链接: https://www.shiyanlou.com/courses/557
本课程内容,由作者授权实验楼发布,未经允许,禁止转载、下载及非法传播
这里的顾客,窗口和事件列表使用的都是队列的形式,因此使用队列就好了
// Queue.hpp
// QueueSystem
//
#ifndefQueue_hpp
#defineQueue_hpp
#include<iostream>
#include<cstdlib>
#include"Event.hpp"
// 带头结点的队列
template<typename T>//这一句和template<class T>的意思是一样的,功能也是一样的
class Queue
{
public:
Queue();
~Queue();
void clearQueue(); // 清空队列
T* enqueue(T &node);//适合于任何类型的人队
T* dequeue();
T* orderEnqueue(Event &event); // 只适用于事件入队
int length();
private:
T *front; // 头结点
T *rear; // 队尾
};
#endif /*Queue_hpp */
来源: 实验楼
链接: https://www.shiyanlou.com/courses/557
本课程内容,由作者授权实验楼发布,未经允许,禁止转载、下载及非法传播
这样的话,基本结构的设计就完成了,接下来是对基本结构的使用以及逻辑运行,来实现银行排队系统
系统管理类
//
// QueueSystem.hpp
// QueueSystem
//
#ifndefQueueSystem_hpp
#defineQueueSystem_hpp
#include"Event.hpp"
#include"Queue.hpp"
#include "ServiceWindow.hpp"
classQueueSystem {
public:
// 初始化队列系统
QueueSystem(int total_service_time, intwindow_num);
// 销毁
~QueueSystem();
// 启动模拟
void simulate(int simulate_num);
inline double getAvgStayTime() const {
return avg_stay_time;
}
inline double getAvgCustomers() const {
return avg_customers;
}
private:
// 让队列系统运行一次
double run();
// 初始化各种参数
void init();
// 清空各种参数
void end();
// 获得空闲窗口索引
int getIdleServiceWindow();
// 处理顾客到达事件
void customerArrived();
// 处理顾客离开事件
void customerDeparture();
// 服务窗口的总数
int window_num;
// 总的营业时间
int total_service_time;
// 顾客的逗留总时间
int customer_stay_time;
// 总顾客数
inttotal_customer_num;
// 核心成员
ServiceWindow* windows;
Queue<Customer> customer_list;
Queue<Event> event_list;
Event* current_event;
// 给外部调用的结果
double avg_customers;
double avg_stay_time;
};
#endif /*QueueSystem_hpp */
来源: 实验楼
链接: https://www.shiyanlou.com/courses/557
本课程内容,由作者授权实验楼发布,未经允许,禁止转载、下载及非法传播
引用是c++的内容,c语言不存在引用,在C语言中要实现引用的功能,使用指针,传递地址
//枚举
#define MON 1
#define TUE 2
#define WED 3
#define THU 4
#define FRI 5
#define SAT 6
#define SUN 7
//等同于
enum DAY
{
MON=1, TUE, WED, THU, FRI, SAT, SUN
};
Inline必须对于函数定义,对于函数声明,不起作用
使用蒙特卡洛方法,
Random.hpp:
//// Random.hpp
// QueueSystem
//
#ifndefRandom_hpp
#defineRandom_hpp
//语句1#ifndef
标识1
语句2 #define
标识1
语句3 #endif
语句4 ……
语句5 ……
该段代码意思是:如果标识1没有被定义,则重定义标识1,即执行语句2、语句3;如果标识1已经被定义,则直接跳过语句2、语句3,直接执行语句4、语句5、……
#include<cstdlib>//实现了c语言的一些方法
#include<cmath>
class Random {
public:
// [0, 1) 之间的服从均匀分布的随机值
static double uniform(double max = 1) {
return ((double)std::rand() /(RAND_MAX))*max;//这一句有一些绕口,include <cstdlib>可以使用std::中的rand()函数,rand函数生成1_rand_max-1的随机数,然后除以rand_max,最后乘以max,可以生成【0,max)的随机数
}
};
#endif /*Random_hpp */
//
// main.cpp
// QueueSystem
//
#include"QueueSystem.hpp"
#include<iostream>
#include<cstdlib>
int main() {
std::srand((unsigned)std::time(0)); // 使用当前时间作为随机数种子
int total_service_time = 240; // 按分钟计算
int window_num = 4;
int simulate_num = 100000; // 模拟次数
QueueSystem system(total_service_time,window_num);
system.simulate(simulate_num);
std::cout << "The average timeof customer stay in bank: "
<< system.getAvgStayTime()<< std::endl;
std::cout << "The number ofcustomer arrive bank per minute: "
<< system.getAvgCustomers()<< std::endl;
return 0;
}
来源: 实验楼
链接: https://www.shiyanlou.com/courses/557
本课程内容,由作者授权实验楼发布,未经允许,禁止转载、下载及非法传播
//
// Node.hpp
// QueueSystem
//
#ifndef Node_hpp
#define Node_hpp
#include"Random.hpp"
#defineRANDOM_PARAMETER 100
struct Node {
int arrive_time;
int duration;
struct Node *next;//在结构体内定义结构体指针需要加上 struct前缀
// 默认到达事件为0,需要服务的事件是随机的
//类默认是私有的,结构体默认是公有的
Node(int arrive_time = 0,
int duration = Random::uniform(RANDOM_PARAMETER)):
arrive_time(arrive_time),
duration(duration),
next(NULL) {}
};
typedef structNode Node;
typedef structNode Customer;
#endif /* Node_h*/
//endif以后最好加上文件名,以区分该endif是哪个文件的
来源: 实验楼
链接: https://www.shiyanlou.com/courses/557
本课程内容,由作者授权实验楼发布,未经允许,禁止转载、下载及非法传播
接下来是ServiceWindow的设计
// ServiceWindow.hpp
// QueueSystem
//
#ifndefServiceWindow_hpp
#defineServiceWindow_hpp
#include"Node.hpp"
enumWindowStatus {
SERVICE,
IDLE,
};
classServiceWindow {
public:
inline ServiceWindow() //inline内联函数,要求函数非常的简单,里面没有例如while,switch等复杂的结构控制语句,且不能是直接递归函数,且inline是一个建议的语句,是否内联还要看编译器怎么说,在内联处编译器一定要明白函数的定义才行
{
window_status = IDLE;
};
inline bool isIdle() const {
if (window_status == IDLE) {
return true;
} else {
return false;
}
}
inline void serveCustomer(Customer&customer) {
this->customer = customer;
}
inline void setBusy() {
window_status = SERVICE;
}
inline void setIdle() {
window_status = IDLE;
}
inline int getCustomerArriveTime() const {
return customer.arrive_time;
}
inline int getCustomerDuration() const {
return customer.duration;
}
private:
Customer customer;
WindowStatus window_status;//当定义了枚举之后,这里是WindowStatus,则可以将定义的枚举名称当做类名使用,可以直接定义枚举变量,枚举变量可以等于枚举里面的值
};
#endif /*ServiceWindow_hpp */
来源: 实验楼
链接: https://www.shiyanlou.com/courses/557
本课程内容,由作者授权实验楼发布,未经允许,禁止转载、下载及非法传播
这里虽然编写好了顾客的类和窗口的类,当是现在这个程序还是静态的,并没有动起来,我们还需要考虑更多逻辑的问题
这里使用事件驱动的方法来管理整个系统的时间线
Event.hpp:
//
// Event.hpp
// QueueSystem
//
#ifndefEvent_hpp
#defineEvent_hpp
#include"Random.hpp"
#defineRANDOM_PARAMETER 100
struct Event {
int occur_time;
// 使用 -1 表示到达事件, >=0 表示离开事件, 同时数值表示所离开的服务窗口
int event_type;
Event* next;
// 默认为到达事件,发生事件随机
Event(int occur_time =Random::uniform(RANDOM_PARAMETER),//一个类的静态方法除了可以使用.来调用以外,还可以使用::方法来调用
int event_type = -1):
occur_time(occur_time),
event_type(event_type),
next(NULL) {}
};
#endif /*Event_hpp */
来源: 实验楼
链接: https://www.shiyanlou.com/courses/557
本课程内容,由作者授权实验楼发布,未经允许,禁止转载、下载及非法传播
接下来我们来设计存储顾客和窗口以及事件的队列,顾客和窗口的队列直接从后面插入就好了,而事件的队列必须按照发生的时间顺序插入
//
// Event.hpp
// QueueSystem
//
#ifndefEvent_hpp
#defineEvent_hpp
#include"Random.hpp"
#defineRANDOM_PARAMETER 100
struct Event {
int occur_time;
// 使用 -1 表示到达事件, >=0 表示离开事件, 同时数值表示所离开的服务窗口
int event_type;
Event* next;
// 默认为到达事件,发生事件随机
Event(int occur_time =Random::uniform(RANDOM_PARAMETER),
int event_type = -1):
occur_time(occur_time),
event_type(event_type),
next(NULL) {}
};
#endif /*Event_hpp */
来源: 实验楼
链接: https://www.shiyanlou.com/courses/557
本课程内容,由作者授权实验楼发布,未经允许,禁止转载、下载及非法传播
这里的顾客,窗口和事件列表使用的都是队列的形式,因此使用队列就好了
// Queue.hpp
// QueueSystem
//
#ifndefQueue_hpp
#defineQueue_hpp
#include<iostream>
#include<cstdlib>
#include"Event.hpp"
// 带头结点的队列
template<typename T>//这一句和template<class T>的意思是一样的,功能也是一样的
class Queue
{
public:
Queue();
~Queue();
void clearQueue(); // 清空队列
T* enqueue(T &node);//适合于任何类型的人队
T* dequeue();
T* orderEnqueue(Event &event); // 只适用于事件入队
int length();
private:
T *front; // 头结点
T *rear; // 队尾
};
#endif /*Queue_hpp */
来源: 实验楼
链接: https://www.shiyanlou.com/courses/557
本课程内容,由作者授权实验楼发布,未经允许,禁止转载、下载及非法传播
这样的话,基本结构的设计就完成了,接下来是对基本结构的使用以及逻辑运行,来实现银行排队系统
系统管理类
//
// QueueSystem.hpp
// QueueSystem
//
#ifndefQueueSystem_hpp
#defineQueueSystem_hpp
#include"Event.hpp"
#include"Queue.hpp"
#include "ServiceWindow.hpp"
classQueueSystem {
public:
// 初始化队列系统
QueueSystem(int total_service_time, intwindow_num);
// 销毁
~QueueSystem();
// 启动模拟
void simulate(int simulate_num);
inline double getAvgStayTime() const {
return avg_stay_time;
}
inline double getAvgCustomers() const {
return avg_customers;
}
private:
// 让队列系统运行一次
double run();
// 初始化各种参数
void init();
// 清空各种参数
void end();
// 获得空闲窗口索引
int getIdleServiceWindow();
// 处理顾客到达事件
void customerArrived();
// 处理顾客离开事件
void customerDeparture();
// 服务窗口的总数
int window_num;
// 总的营业时间
int total_service_time;
// 顾客的逗留总时间
int customer_stay_time;
// 总顾客数
inttotal_customer_num;
// 核心成员
ServiceWindow* windows;
Queue<Customer> customer_list;
Queue<Event> event_list;
Event* current_event;
// 给外部调用的结果
double avg_customers;
double avg_stay_time;
};
#endif /*QueueSystem_hpp */
来源: 实验楼
链接: https://www.shiyanlou.com/courses/557
本课程内容,由作者授权实验楼发布,未经允许,禁止转载、下载及非法传播
引用是c++的内容,c语言不存在引用,在C语言中要实现引用的功能,使用指针,传递地址
//枚举
#define MON 1
#define TUE 2
#define WED 3
#define THU 4
#define FRI 5
#define SAT 6
#define SUN 7
//等同于
enum DAY
{
MON=1, TUE, WED, THU, FRI, SAT, SUN
};
Inline必须对于函数定义,对于函数声明,不起作用
相关文章推荐
- 项目实战笔记 | C++ 事件驱动模型实现银行排队服务2 代码实现
- 转载:C++ 实现银行排队服务模拟
- C++ 实现银行排队服务模拟
- 项目实战笔记 | C++实现运动目标的追踪 实验楼项目
- C++ 实现银行排队服务模拟
- 小项目分析之C++ 实现模拟银行排队
- c语言版数据结构(奇迹冬瓜)-队列实战(1)离散事件模拟(银行排队)
- Quartz.NET 2.0 学习笔记(5) :实例创建Windows服务实现任务调度 Quartz.NET 项目地址 http://quartznet.sourceforge.net/ Quar
- 数据结构作业2 ------ 用队列模拟银行排队的情况
- 项目实战之中小网站数据缓存的设计与实现
- 【C++数据结构学习笔记---线性表】用数组实现线性表
- 【C++数据结构学习笔记---线性表】用单链表实现线性表
- 高级数据结构设计--并查集及实现学习笔记(有趣篇)
- 开发笔记 (13) : AOI 服务的设计与实现
- 项目实战之中小网站数据缓存的设计与实现
- 项目管理实战之团队管理 对团队的管理需要重视以下几个方面 一个系统不仅需要优秀的分析和设计,更需要一个良好的过程将其从蓝图转化为实现。这个过程中最重要的是对团队的管理,也就是人的管理
- 【C++数据结构学习笔记---栈】用链表实现栈
- IM 开源项目 群组服务 缓存设计实现之 成员属性
- 项目实战之Quartz与Spring整合进行热部署的设计与实现
- 银行排队系统的设计与实现