2019独角兽企业重金招聘Python工程师标准>>>

前一章节讲的队列现在可以使用了。很多现实生活中的情形都包含队列。例如,在银行或超级市场的顾客队列,在机场的飞机队列,多任务计算机系统上的任务队列等。可以用队列包来模拟这些情形。

例如,假设你在商业街上设了一个提供建议的摊位。顾客可购买一分钟、两分钟或三分钟的建议。为确保交通顺畅,商业街限制排成一队等待的顾客数目最多为10(最大队列长度)。假设人们的出现是随机的,并且他们花在咨询上的时间随机分布于三个选择(一分钟、两分钟、三分钟)上。那么您平均每小时要接待多少顾客?每位顾客平均要等多长时间?队平均有多长?队列模拟能回答这些问题。

首先,让我们决定队列里面要放什么?您能够描述的是每一位顾客加入到队列中的时间和他(她)需要咨询的时间。这提示我们要对Item类型做下面的定义:

typedef struct item
{long arrive;    /*一位顾客加入队列的时间*/int processtime /*该顾客需要的咨询时间*/
} Item;

为转化队列包来处理这个结构,您所要做的就是用这里对Item的typedef定义替换上个例子中使用的int类型。做完这些之后,您就不用担心队列的具体工作机制,而是分析实际问题,即模拟等候队列。

有一种方法是这样的,让时间以1分钟为单位递增。在每分钟里检查是否有新的顾客到来。如果有一个顾客到来且队列未满,将此顾客添加到队列。这包括将此顾客的到达时间和他需要的咨询时间记录到一个Item结构中,而后将此项目添加到队列。但如果队列已满,就拒绝此顾客加入。为了做统计,需要保存顾客总数和被拒顾客(由于队列已满的而不能进入队列的人)的总数。

接下来,处理队列首端。即,如果队列非空且店主未被前面的顾客占用,则删除位于队列首端的项目。回忆一下,项目中存有此顾客加入队列的时间。通过比较这个时间和当时时间,就可得到此顾客在队列中的等待时间。这个项目还存有此顾客需要的咨询时间,这将决定此顾客占用店主的时间。用一个变量跟踪这一等待时间。如果店主正忙,没人可以出列。当然,此跟踪变量应能自动递减。

核心代码可以像下面这样,其中每一个循环对应于一分钟的活动

for(cycle=0;cycle<cyclelimit;cycle++)
{if(newcustomer(min_per_cus)){if(QueueIsFull(&line))turnaways++;else{customers++;temp = customertime(cycle);EnQueue(temp,&line);}}if(wait_time<=0 && !QueueIsEmpty(&line)){DeQueue(&temp,&line);wait_time = temp.processtime;line_wait += cycle - temp.arrive;served++;}if(wait_time>0)wait_time--;sum_line += QueueItemCount(&line);
}

以下是一些变量和函数的意义

min_per_cus    是顾客到达的平均间隔时间。

newcustomer( )使用C的rand()函数确定在这一分钟里是否有顾客到达。

turnaways       是被拒顾客的数目。

customers       是加入到队列中的顾客的数目。

temp               是描述新顾客的Item变量。

customertime() 设置temp结构的arrive和processtime成员。

wait_time         是店主完成当前顾客的咨询还需要的时间。

line_wait         是到目前为止队列中所有顾客等待的总时间。

served            是实际服务的顾客数目。

sum_line         是到目前为止队列的累计总长。

想想看如果用散布在程序中的malloc()和free()函数与指向节点的指针来实现此程序的话,代码将会多么 的混乱和晦涩。应用队列包使您集中精力于模拟的问题,而非编程细节。

程序清单17.9给出了模拟商业街建议摊位队列的完整代码。按照前面章节介绍的方法,使用了标准函数rand( ) srand( )和time( )来产生随机数。要使用此程序,记住按照如下所示更新queue.h头文件中对Item的定义:

typedef struct item
{long arrive;    /*一位顾客加入队列的时间*/int processtime /*该顾客需要的咨询时间*/
} Item;

还要记住链接mall.c和queue.c的代码。

程序清单17.9  mall.c程序

#include <stdio.h>
#include <stdlib.h>    /*为Random()和Srand()提供函数原型*/
#include <time.h>      /*为time( )函数提供原型*/
#include "queue.h"
#define MIN_PER_HR 60.0bool newcustomer(double x);  /*有新顾客到来?*/
Item customertime(long when); /*设置顾客参数*/int main(void)
{Queue line;Item temp;  /*关于新顾客的数据*/int hours;  /*模拟的小时数*/int perhour;/*每小时顾客的平均数*/long cycle,cyclelimit; /*循环计数器,计数器的上界*/long turnaways=0;      /*因队列已满而被拒绝的顾客数*/long customers=0;      /*被加入队列的顾客数*/long served=0;         /*在模拟期间得到服务的顾客数*/long sum_line=0;       /*累计的队列长度*/int wait_time=0;       /*从当前到sigmund空闲所需要的时间*/double min_per_cust;   /*顾客到来的平均时间间隔*/long line_wait = 0;    /*队列累计等待时间*/InitializeQueue(&line);srand(time());  /*随机初始化rand()函数*/puts("Case Study: Sigmund Lander's Advice Booth");puts("Enter the number of simulation hours: ");scanf("%d",&hours);cyclelimit = MIN_PER_HR * hours;puts("Enter the average number of customers per hour: ");scanf("%d",&perhour);min_per_cust = MIN_PER_HR / perhour;for(cycle = 0; cycle < cyclelimit; cycle++){if(newcustomer(min_per_cust)){if(QueueIsFull(&line))turnaways++;else{customers++;temp=customertime(cycle);EnQueue(temp,&line);}}if(wait_time <= 0 && !QueueIsEmpty(&line)){DeQueue(&temp,&line);wait_time = temp.processtime;line_wait += cycle - temp.arrive;served++;}if(wait_time > 0)wait_time --;sum_line += QueueItemCount(&line);}if(customers > 0){printf("Customers accepted: %ld\n",customers);printf(" customers served: %ld\n",served);printf("     turnaways: %ld\n",turnaways);printf("average queue size: %.2f\n",(double)sum_line / cyclelimit);printf(" average wait time: %.2f minutes\n",(double)line_wait / served);}elseputs("No customers!");EmptyTheQueue(&line);puts("Bye!");return 0;
}/*x是顾客到来的平均时间间隔*/
/*如果这1分钟内有顾客到来,则返回true*/
bool newcustomer(double x)
{if(rand()*x / RAND_MAX < 1)return true;else return false;
}/*when是顾客到来的时间
函数返回一个Item结构,该结构的顾客到来时间设置为when
需要咨询的时间设置为一个范围在1-3之间的随机值*/Item customertime(long when)
{Item cust;cust.processtime = rand()%3+1;cust.arrive = when;return cust;
}

程序允许用户指定模拟运行的小时数和每小时顾客的平均数。选择一个数目较大的小时数会得到一个较好的平均值,而选择一个较小的小时数会显示一定程度的随时间的随机变化。下面的运行结果说明了这些要点。注意到平均队长和等待时在80小时和800小时的情况下基本相同,但这两个量在两个1小时的情况下相关很大,同时与长期平均值相差也很大。这是因为小数量的统计示例更易受相对变化的影响。

Case Study:Sigmund Lander's Advice Booth
Enter the number of simulation hours:
80
Enter the average number of customers per hour:
20
customers accepted:1633customers served:1633turnaways:0
average queue size:0.46
average wait time:1.35 minutesCase Study:Sigmund Lander's Advice Booth
Enter the number of simulation hours:
800
Enter the average number of customers per hour:
20
customers accepted:16020customers served:16019turnaways:0
average queue size:0.44
average wait time:1.32 minutesCase Study:Sigmund Lander's Advice Booth
Enter the number of simulation hours:
1
Enter the average number of customers per hour:
20
customers accepted:20customers served:20turnaways:0
average queue size:0.23
average wait time:0.70 minutesCase Study:Sigmund Lander's Advice Booth
Enter the number of simulation hours:
1
Enter the average number of customers per hour:
20
customers accepted:22customers served:22turnaways:0
average queue size:0.75
average wait time:2.05 minutes

另一种使用程序的方法是保持小时数不变,而尝试用不同的每小时顾客平均数的情况。以下是探寻这种变化的示例:

Case Study:Sigmund Lander's Advice Booth
Enter the number of simulation hours:
80
Enter the average number of customers per hour:
25
customers accepted:1960customers served:1959turnaways:3
average queue size:1.43
average wait time:3.5 minutesCase Study:Sigmund Lander's Advice Booth
Enter the number of simulation hours:
80
Enter the average number of customers per hour:
30
customers accepted:2376customers served:2373turnaways:94
average queue size:5.85
average wait time:11.83 minutes

注意到当顾客访问频率提高后平均等待时间急速上升。在每小时20个顾客的情况下,平均等待时间为1.35分钟。25个时,此数值攀升到3.5分钟;而30个时更是急剧增加到11.83分钟。并且,被拒顾客数从0上升到3进而上升到94。店主Sigmund可以根据这个分析结果来决定他是否需要另一个摊位。

转载于:https://my.oschina.net/idreamo/blog/1518971

第17章 高级数据表示 17.5用队列进行模拟相关推荐

  1. 第17章-高级数据表示

    研究数据表示: 我们先从数据开始.假设要创建一个地址簿程序.应该使用什么数据形式储存信息?由于储存的每一项都包含多种信息,用结构来表示每一项很合适.如何表示多个项?是否用标准的结构数组?还是动态数组? ...

  2. 第十七章 高级数据表示

    程序清单17.1,films1.c: /* films1.c -- 使用一个结构数组 */ #include <stdio.h> #include <string.h> #de ...

  3. C day18 高级数据表示(链表,队列)

    这是C primer的最后一章了,前面已经学习了怎么创建变量,结构,数组,指针,会写函数,总之,把C作为工具层面的知识已经学完了,但是对于编程之路,这才算走完第一步,因为对于写程序最重要的是学习如何表 ...

  4. 【《C Primer Plus》读书笔记】第17章:高级数据表示

    [<C Primer Plus>读书笔记]第17章:高级数据表示 17.1 研究数据表示 17.2 从数组到链表 17.3 抽象数据类型(ADT) 17.4 队列ADT 17.5 用队列进 ...

  5. 17章 SPI控制器(XIlinx ZYNQ-7000 SOC UG-585文档)

    第17章 SPI控制器 注:本文为笔者自己翻译的XILINX ZYNQ-7000 SOC UG-585官方文档,文档版本UG585 (v1.12.2) July 1, 2018 文章目录 第17章 S ...

  6. Go第 17 章 :反射

    Go第 17 章 :反射 17.1 先看一个问题,反射的使用场景 17.2 使用反射机制,编写函数的适配器, 桥连接 17.3 反射的基本介绍 17.3.1 基本介绍 反射可以在运行时动态获取变量的各 ...

  7. Android高级终端开发学习笔记(《疯狂Android讲义》第11章-第17章)

    Android高级终端开发笔记 2021/6/19 下午 13:34开始 多媒体应用开发 Android支持的音频格式有:MP3 WAV 3GP等.支持的视频格式有MP4 3GP等. 多媒体数据既可以 ...

  8. C#高级编程9 第17章 使用VS2013-C#特性

    C#高级编程9 第17章 使用VS2013 编辑定位到 如果默认勾选了这项,请去掉勾选,因为勾选之后解决方案的目录会根据当前文件选中. 可以设置项目并行生成数 版本控制软件设置 所有文本编辑器行号显示 ...

  9. CSS3秘笈第三版涵盖HTML5学习笔记13~17章

    第13章,构建基于浮动的布局 使用的是float(浮动)属性 注:float:none值将取消所有浮动,通常只用来取消元素中已经应用的浮动. 切记:不需要给正文的div设计宽度,即使设计成固定宽度也不 ...

最新文章

  1. Fragment 复习一
  2. unity3d 地面印花_unity怎么实现挖掘泥土?
  3. php教程目录,php基础入门篇-文件和目录操作_PHP教程
  4. GitHub或正式登陆中国!拟在中国设立分公司
  5. linux设备文件生成,Linux设备文件自动生成(示例代码)
  6. 用户体验设计和精益设计的平衡之道
  7. 【GNN】图神经网络综述
  8. 134. PHP 工具
  9. java 不丢失精度运算
  10. 2021 写博客指南·万字长文警告
  11. PM也要学会每天反省
  12. 牛客练习赛53 E.老瞎眼 pk 小鲜肉(离线+BIT单点修改)
  13. 人脸识别支付欺诈手段和防范措施
  14. WES2009创建开发
  15. python:shape和reshape函数基本讲解
  16. H264--4--H264编码
  17. MLSQL生态一键体验
  18. 剪裁头像裁剪遇到关于小米华为适配问题的解决
  19. 【c语言】组件化打包—静态库lib
  20. linux sort -k

热门文章

  1. Ubuntu16.04执行sudo apt-get update时出现其他软件更新错误
  2. 企业信用报告有哪些用途?
  3. oracle无效列的列类型,oracle 无效的列类型: 1111
  4. 计算面积(绘图机器的绘图笔)
  5. 现在学3D建模入行是不是晚了?学好了还能找到高薪的好工作吗
  6. 对图片进行膨胀与腐蚀
  7. 荣耀magic 3系列冲击高端胜算几何?
  8. winform无法屏蔽回车事件、KeyPress事件不执行问题解决
  9. 关于DuiLib高DPI适配问题
  10. 创建框架协议(价值合同)