C++事件驱动型银行排队模拟

2020-01-06 15:56:43刘景俊

处理顾客离开事件 

处理“顾客离开事件”的逻辑:
 1.顾客所在服务窗口置为空闲,统计顾客信息;
 2.出队事件队列;
 3.若顾客队列不为空且有空闲的服务窗口,生成“顾客离开事件”。 

下面是代码:


 void Manager::customer_departure() {
 int current_time = _current_event->occur_time;
 int service_index = _current_event->service_index;//顾客离开的服务窗口

 _customer_stay_time += current_time -
     _services[service_index].get_customer_arrive_time();//统计顾客在银行的滞留时间
 ++_total_served_customer_num;//接受服务的顾客数目加1
 _services[service_index].set_idle();
 _event_queue.dequeue();

 if(_customer_queue.size() > 0) {
  service_index = get_idle_service_index();//有顾客离开,必然可以获得1个空闲服务窗口,这里获取最小序号的服务窗口
  generate_departure_event(service_index, current_time);
 }
} 

清理工作:
 1.寻找仍在接受服务的顾客并统计他们的信息;
 2.释放动态申请的内存。 

下面是代码:


 void Manager::end() {
 for (int i = 0; i < _service_num; i++) {
  if (!_services[i].is_idle()) {//统计正在接受服务的顾客的信息
   int service_start_time = _services[i].get_service_start_time();
   int arrive_time = _services[i].get_customer_arrive_time();
   int duration = _services[i].get_customer_duration();

   _customer_stay_time += service_start_time + duration - arrive_time;
   ++_total_served_customer_num;
  }
 }

 //释放动态申请的内存
 _customer_queue.clear();
 _event_queue.clear();
 delete[] _services;
} 

关于队列的说明 

程序中使用的是自定义的队列,根据需求,可以使用STL中的优先队列和队列,前者用于事件队列,后者用于顾客队列。
 优先队列的头部总是优先级最高的节点,对于事件来说,就是发生的时间越早,事件优先级越高,所以这是一个最小堆——时间发生的时间最小(最早)的位于堆顶。这涉及到对Event类型的比较,使用STL的greater<Event>(需要重载operator>)或是自定义的函数对象来比较2个Event对象:
 (1)重载operator>运算符


 //声明使用greater<Event>作为比较函数的优先队列
std::priority_queue<Event, std::vector<Event>, std::greater<Event>> _event_queue; //event_queue.h

#ifndef BANKQUEUE_EVENT_QUEUE_H
#define BANKQUEUE_EVENT_QUEUE_H

#include "random.h"

enum class EventType : int {
 ARRIVIED,
 DEPARTURE
};

class Event {
 public:
 Event():occur_time(Random::uniform(RANDOM_PARAMETER)),
     event_type(EventType::ARRIVIED),
     service_index(-1),
     next(nullptr){}

 Event(int occur_time):occur_time(occur_time),
     event_type(EventType::ARRIVIED),
     service_index(-1),
     next(nullptr){}
 Event(int occur_time, EventType event_type, int service_index):
     occur_time(occur_time),
     event_type(event_type),
     service_index(service_index),
     next(nullptr) {}

 friend bool operator< (const Event& event1, const Event& event2);//模仿STL的实现,都是通过'<'来完成余下的比较操作符
 friend bool operator> (const Event& event1, const Event& event2);//供`greater<Event>`使用

 public:
 int occur_time;
 int service_index;
 EventType event_type;
 Event *next;
};

inline bool operator< (const Event& event1, const Event& event2) {
 return event1.occur_time < event2.occur_time;
}

inline bool operator> (const Event& event1, const Event& event2) {
 return event2 < event1;//通过'<'实现'>'的功能
}

#endif //BANKQUEUE_EVENT_QUEUE_H