C++抽象编程——STL(3)——解决排队问题的代码及其分析
2017-03-27 12:20
525 查看
这篇文章是基于上一篇文章的分析写出来的代码,地址为:离散事件模拟与排队问题
这个程序主要模拟了我们日常的超市购物排队问题。顾客到达检查线,然后排队等待服务。当收银员服务完上一位顾客的时候,这时他就有空闲的时间,然后为下一个顾客服务。在这个模拟中,每一单位时间内都会执行下面的操作,直到模拟时间结束:
判断新的顾客是否到达。顾客都是随机到达的,而且他到达的概率也是随机的,这个取决于我们定义的常数ARRIVAL_PROBABILITY。
如果收银员很,这个时候,出纳员已经花了一分钟的时间在该客户。 最终,客户的时间要求得到满足,这样可以释放出纳员。
如果收银员是空闲的,就为下一位客户服务。 服务时间取决于MIN_SERVICE_TIME 和MAX_SERVICE_TIME之间的随机时间。
PS:如果下面的产生随机数的算法不理解,那就跳过吧,你只要知道它的功能就好了,我接下来的博文会有讲到为什么会有这样的算法。理由是什么(在《函数与库》的博文中)
结果;
- 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。 运行这些参数的模拟结果如下:
正如你所看到的,概率翻倍使得平均等待时间从10秒以下增长到超过两分钟,这显然是一个急剧性的增长。 表现不佳的原因是第二次模拟的到达率意味着新客户以相同的速率到达他们的服务点(即同时到达同一服务点)。 当遇到这种情况时,队列的长度和平均等待时间都开始快速增长。 这种模拟可以尝试不同的参数值。 这些实验反过来又可以在相应的现实系统中找出潜在的问题来源。
这里queue类就算是结束了,接下来我就总结我们用的最多的,也是最重要的类——vector类。这个极其强大的数据结构我们在各类的排序算法中都能与它碰面,非常重要!!!
这个程序主要模拟了我们日常的超市购物排队问题。顾客到达检查线,然后排队等待服务。当收银员服务完上一位顾客的时候,这时他就有空闲的时间,然后为下一个顾客服务。在这个模拟中,每一单位时间内都会执行下面的操作,直到模拟时间结束:
判断新的顾客是否到达。顾客都是随机到达的,而且他到达的概率也是随机的,这个取决于我们定义的常数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。 运行这些参数的模拟结果如下:
正如你所看到的,概率翻倍使得平均等待时间从10秒以下增长到超过两分钟,这显然是一个急剧性的增长。 表现不佳的原因是第二次模拟的到达率意味着新客户以相同的速率到达他们的服务点(即同时到达同一服务点)。 当遇到这种情况时,队列的长度和平均等待时间都开始快速增长。 这种模拟可以尝试不同的参数值。 这些实验反过来又可以在相应的现实系统中找出潜在的问题来源。
这里queue类就算是结束了,接下来我就总结我们用的最多的,也是最重要的类——vector类。这个极其强大的数据结构我们在各类的排序算法中都能与它碰面,非常重要!!!
相关文章推荐
- 菱形继承问题分析及其在C++的解决方法(虚继承)
- Windows平台下C++插件系统实现的几个关键技术问题及其解决思路
- 分析ADSL拨号中出现的错误代码 原因及其解决办法
- 关于c++与java中文乱码问题分析与解决
- 左右c++与java中国的垃圾问题的分析与解决
- C++代码实现Ford-Fulkerson方法Edmonds Karp算法解决最大流问题
- Dev_c++下解决编译winsock和pthread 的链接问题C++&STL
- Windows平台下C++插件系统实现的几个关键技术问题及其解决思路
- c/c++服务器程序内存泄露问题分析及解决
- c/c++服务器程序内存泄露问题分析及解决
- 文《左右c++与java中国的垃圾问题的分析与解决》一bug分析
- 【高精度】c++ stl解决poj1001问题
- Xcode 5 中引入 C++ 模板代码无法编译通过的问题解决
- 从零开始学C++之STL(七):剩下5种算法代码分析与使用示例(remove 、rotate 、sort、lower_bound、accumulate)
- 文《关于c++与java中文乱码问题分析与解决》中一个bug分析
- C/C++运行中的一些问题及其解决
- 【高精度】c++ stl解决poj1001问题
- c++沉思录笔记(21章代码)通过函数对象解决c++的函数嵌套问题
- 从零开始学C++之STL(七):剩下5种算法代码分析与使用示例(remove 、rotate 、sort、lower_bound、accumulate)
- 解决Eclipse中C++代码显示Symbol 'std' could not be resolved的问题