C++抽象编程——STL(3)——解决排队问题的代码及其分析

这篇文章是基于上一篇文章的分析写出来的代码,地址为:离散事件模拟与排队问题
这个程序主要模拟了我们日常的超市购物排队问题。顾客到达检查线,然后排队等待服务。当收银员服务完上一位顾客的时候,这时他就有空闲的时间,然后为下一个顾客服务。在这个模拟中,每一单位时间内都会执行下面的操作,直到模拟时间结束:

  • 判断新的顾客是否到达。顾客都是随机到达的,而且他到达的概率也是随机的,这个取决于我们定义的常数ARRIVAL_PROBABILITY。
  • 如果收银员很,这个时候,出纳员已经花了一分钟的时间在该客户。 最终,客户的时间要求得到满足,这样可以释放出纳员。
  • 如果收银员是空闲的,就为下一位客户服务。 服务时间取决于MIN_SERVICE_TIME 和MAX_SERVICE_TIME之间的随机时间。

PS:如果下面的产生随机数的算法不理解,那就跳过吧,你只要知道它的功能就好了,我接下来的博文会有讲到为什么会有这样的算法。理由是什么(在《函数与库》的博文中)

#include <iostream>
#include <cmath>
#include <ctime>
#include <iomanip>
#include <queue>
#include <cstdlib>
using namespace std;
/* Constants */
const double ARRIVAL_PROBABILITY = 0.05; /*顾客到达的概率*/
const int MIN_SERVICE_TIME = 5;/*最少的服务时长*/
const int MAX_SERVICE_TIME = 15;/*最长的服务时长*/
const int SIMULATION_TIME = 2000;/*模拟的时间*/
/* Function prototypes */
void runSimulation(int & nServed, int & totalWait, int & totalLength);
void printReport(int nServed, int totalWait, int totalLength);
bool randomChance(double p);/*判断产生的随机概率是不是小于p*/ 
double randomReal(double low, double high); /*在这两个参数之间产生一个随机实数*/
int randomInteger(int low, int high);/*在这两个参数之间产生一个随机整数*/ 
/* Main program */
int main() {
    int nServed;
    int totalWait;
    int totalLength;
    runSimulation(nServed, totalWait, totalLength);
    printReport(nServed, totalWait, totalLength);
    return 0;
}
/*
* Function: runSimulation
* Usage: runSimulation();
* -----------------------
*这个函数执行实际的模拟,里面有三个参数,分别代表的是,服务的人数,顾客等待的时
*间,和队伍的长度。在每一次模拟中都通过引用参数返回 
*/
void runSimulation(int & nServed, int & totalWait, int & totalLength) {
    /*初始化队列*/ 
    queue<int> customerQueue;
    int timeRemaining = 0;/*记录剩余的时间*/ 
    nServed = 0;
    totalWait = 0;
    totalLength = 0;
    /*---------*/
    for(int t = 0; t < SIMULATION_TIME; t++) {
        if(randomChance(ARRIVAL_PROBABILITY)) {
            customerQueue.push(t);
        }
        if(timeRemaining > 0) {
            timeRemaining--;
        } else if (!customerQueue.empty()) {
            int dequeue = customerQueue.front(); /*记录出队列的那个元素*/ 
            totalWait += t - dequeue;
            customerQueue.pop(); /*将那个元素移除出队列*/
            nServed++; /*已服务的人数加1*/
            timeRemaining = randomInteger(MIN_SERVICE_TIME, MAX_SERVICE_TIME);
        }
        totalLength += customerQueue.size();  
    }
}
/*
* Function: printReport
* Usage: printReport(nServed, totalWait, totalLength);
* ----------------------------------------------------
* 展示结果 ,这里我用中文输出 
*/
void printReport(int nServed, int totalWait, int totalLength) {
    cout << "模拟结果展示:" 
         << endl;
    cout << fixed << setprecision(2);
    cout << " 模拟时长: " << setw(4)
         << SIMULATION_TIME << endl;
    cout << " 顾客到达的概率: " << setw(7)
         << ARRIVAL_PROBABILITY << endl;
    cout << " 最小服务时长: " << setw(4)
         << MIN_SERVICE_TIME << endl;
    cout << " 最大服务时长: " << setw(4)
         << MAX_SERVICE_TIME << endl;
    cout << endl;
    cout << "已服务的人数: " << setw(4) << nServed << endl;
    cout << "平均等待时长: " << setw(7)
         << double(totalWait) / nServed << endl;
    cout << "平均队列长度: " << setw(7)
         << double(totalLength) / SIMULATION_TIME << endl;
}
void initRandomSeed() {
    static bool initialized = false;
    if (!initialized) {
    srand(int(time(NULL)));
    initialized = true;
    }
}
bool randomChance(double p) {
    initRandomSeed();
    return randomReal(0,1) < p;
} 
int randomInteger(int low, int high) {
    initRandomSeed();
    double d = rand() / (double(RAND_MAX) + 1);
    double s = d * (double(high) - low + 1);
    return int(floor(low + s));
}
double randomReal(double low, double high) {
    initRandomSeed();
    double d = rand() / (double(RAND_MAX) + 1);
    double s = d * (high - low);
    return low + s;
}

结果;
模拟

代码分析

从程序中我们可以看出,这个模拟主要由下面的几个常数控制的:
- SIMULATION_TIME - 此常数指定模拟的持续时间(This constant specifies the duration of the simulation)
- ARRIVAL_PROBABILITY -此常数表示新客户在单个时间单位内到达结帐线的概率。 根据标准统计惯例,概率表示为0和1之间的实数.(This constant indicates the probability that a new
customer will arrive at the checkout line during a single unit of time. In keeping with standard statistical convention, the probability is expressed as a real number between 0 and 1.)
- MIN_SERVICE_TIME, MAX_SERVICE_TIME 这些常量定义合法的客户服务时间范围。 对于任何特定的客户,服务的时间都在这个范围内。(These constants define the legal range of customer service time. For any particular customer, the amount of time spent at the cashier is determined by picking a random integer in this range.)

当程序模拟结束的时候,就会展示下面的一些内容:

  • 已经服务的顾客数(The number of customers served)
  • 平均等待时长(The average amount of time customers spent in the waiting line)
  • 队伍的平均长度(The average length of the waiting line)

模拟的行为主要取决于用于控制它的常数值。 假设,客户到达的概率从0.05增加到0.10。 运行这些参数的模拟结果如下:
模拟2

正如你所看到的,概率翻倍使得平均等待时间从10秒以下增长到超过两分钟,这显然是一个急剧性的增长。 表现不佳的原因是第二次模拟的到达率意味着新客户以相同的速率到达他们的服务点(即同时到达同一服务点)。 当遇到这种情况时,队列的长度和平均等待时间都开始快速增长。 这种模拟可以尝试不同的参数值。 这些实验反过来又可以在相应的现实系统中找出潜在的问题来源。

这里queue类就算是结束了,接下来我就总结我们用的最多的,也是最重要的类——vector类。这个极其强大的数据结构我们在各类的排序算法中都能与它碰面,非常重要!!!

  • 0
    点赞
  • 14
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值