模拟ATM机为客户队列提供服务。
用户输入队列最大人数、持续模拟时间、平均人流量。
程序采用随机方式自然模拟,最后得出统计数据:客户数、遗失的客户数、客户平均等待时间等。
(这里默认假设每位用户操作ATM的时间为1到3分钟,可以修改set()函数来自设定时间。)
//头文件 queue.h
#ifndef QUEUE_H_
#define QUEUE_H_
class Customer
{
public:
Customer(){arrive = processtime = 0;}
void set (long when);
long when ()const {return arrive;}
int ptime()const {return processtime;}
private:
long arrive;
int processtime;
};
typedef Customer Item;
class Queue
{
public:
Queue(int qs = Q_SIZE);
~Queue();
bool isempty()const;
bool isfull()const;
int queuecount()const;
bool enqueue(const Item &item);
bool dequeue(Item &item);
private:
Queue(const Queue & q):qsize (0){} //禁止传递类引用的构造函数(默认复制构造函数)
Queue & operator=(const Queue & q){return *this;} //禁止默认赋值操作符
struct Node{Item item;struct Node * next;}; //类嵌套结构,结构嵌套类
enum{Q_SIZE = 10};
Node * front;
Node * rear;
int items;
const int qsize;
};
#endif
//类方法文件 queue.cpp
#include "queue.h"
#include <cstdlib>
Queue::Queue(int qs):qsize(qs)
{
front = rear = NULL;
items = 0;
}
Queue::~Queue()
{
Node * temp;
while (front != NULL)
{
temp = front;
front = front->next;
delete temp;
}
}
bool Queue::isempty()const
{
return items == 0;
}
bool Queue::isfull()const
{
return items == qsize;
}
int Queue::queuecount()const
{
return items;
}
bool Queue::enqueue(const Item & item) //将新数据加入链表尾
{
if(isfull())
return false;
Node * add = new Node;
if(add == NULL)
return false;
add->item = item;
add->next = NULL;
items++;
if(front==NULL)
front = add;
else
rear->next = add;
rear = add;
return true;
}
bool Queue::dequeue(Item & item) //删除链表中首位单元
{
if(front == NULL)
return false;
item = front->item; //这里很巧妙,先删除队首客户,再在外部调用中等待该客户需要的服务时间。
items--;
Node * temp = front;
front = front->next;
delete temp;
if(items == 0)
rear = NULL;
return true;
}
void Customer::set(long when)
{
processtime = std::rand()%3+1; //需要停留的分钟数(这里是1到3分钟)
arrive = when; //客户到达的时间(开始模拟后的第几分钟)
}
//main.cpp
#include <iostream>
#include <cstdlib>
#include <ctime>
#include "queue.h"
const int MIN_PER_HR = 60;
bool newcustomer(double x);
int main()
{
using::std::cin;
using::std::cout;
using::std::endl;
using::std::ios_base;
std::srand(std::time(0)); //为随机函数提供种子
cout<<"案例研究:银行自动取款/n/n";
cout<<"输入队列的最大人数: ";
int qs;
cin>>qs;
Queue line(qs);
cout<<"输入需要模拟的时间(小时): ";
int hours;
cin>>hours;
long cyclelimit = MIN_PER_HR * hours;
cout<<"输入平均每小时用户人数: ";
double perhour;
cin>>perhour;
double min_per_cust;
min_per_cust = MIN_PER_HR / perhour; //60分钟除以每小时人数,得到客户到达的间隔时间。
cout<<endl;
Item temp;
long turnaways = 0;
long customers = 0;
long served = 0;
long sum_line = 0;
int wait_time = 0;
long line_wait = 0;
for (int cycle = 0;cycle < cyclelimit;cycle++) //cyclelimit(总模拟分钟数)。
{
if (newcustomer(min_per_cust)) //判断是否来人。
{
if (line.isfull()) //判断队列是否满了。
turnaways++; //丢失的客户数。
else
{
customers++; //加入队列的客户数。
temp.set(cycle); //设置并记录客户信息。
line.enqueue(temp); //将客户加入队列。
}
}
if (wait_time <= 0 && !line.isempty()) //line.isempty()判断队列是否为空,wait_time判断客户是否处理完毕。
{
line.dequeue(temp); //删除队列中首位客户。
wait_time = temp.ptime(); //得到当前客户需要的服务时间。
line_wait += cycle - temp.when(); //首先用当前分钟数减去客户到达时分钟数,得到等待分钟数,并累加。
served++; //得到服务的客户数。
}
if(wait_time > 0)
{
wait_time--; //客户需要的服务时间减一分钟。
}
sum_line += line.queuecount(); //累加每分钟队列人数。
}
if (customers > 0)
{
cout<<"接待的客户数: "<<customers<<endl;
cout<<"成功提供服务数: "<<served<<endl;
cout<<"因队列满而遗失的客户: "<<turnaways<<endl;
cout<<"平均每分钟队列中人数: ";
cout.precision(2);
cout.setf(ios_base::fixed,ios_base::floatfield);
cout.setf(ios_base::showpoint);
cout<<(double)sum_line / cyclelimit<<endl; //每分钟队列人数的累加 除以 总分钟数 得到平均队列人数。
cout<<"得到服务的客户平均等待时间: "
<<(double)line_wait / served<<" 分钟/n";
//得到服务的每位客户的总等待时间 除以 成功提供服务的客户总数 得到 平均每位得到服务的客户等待时间。
}
else
cout<<"没有客户!/n";
cout<<endl;
cout<<"银行自动取款,模拟结束!/n";
return 0;
}
bool newcustomer(double x)
{
return (std::rand()* x/RAND_MAX < 1); //随机数 * 客户到达的间隔时间 / 随机最大数(得到0到X之间)
//平均每隔X次,这个值会有1次小于1.不过如果客户到达的平均时间间隔少于1分钟,则该方法无效。解决办法,提高时间分辨率,比如每次循环代表10秒。
}