数据结构队列 离散事件模拟 银行排队问题

【数据结构】 队列 离散事件模拟 银行营业1.问题介绍假设银行有四个窗口对外接待客户,从早晨开门起不断有客户进入银行每个窗口每个时刻只能接待一个客户,因此人数过多时需在每个窗口进行排队现在编制一个程序模型银行的业务活动,并计算一天中客户在银行逗留平均时间2.问题分析该问题可以分为几个事件,1.客户到达事件 2.客户离开事件(四个窗口)按事件发生的先后顺序进行处理所有的事件可以使用...
摘要由CSDN通过智能技术生成

【数据结构】 队列 离散事件模拟 银行排队问题

1.问题介绍

假设银行有四个窗口对外接待客户,从早晨开门起不断有客户进入
银行每个窗口每个时刻只能接待一个客户,因此人数过多时需在每个窗口进行排队
现在编制一个程序模型银行的业务活动,并计算一天中客户在银行逗留平均时间

2.问题分析

该问题可以分为几个事件,1.客户到达事件 2.客户离开事件(四个窗口)
按事件发生的先后顺序进行处理
所有的事件可以使用一个有序链表存储,事件的插入按发生时间进行排序
四个窗口中排队可以用四个队列表示

3.基本思路

各种类型的定义

客户:客户是队列中的数据元素,包括 到达时间,办理业务所需时间
事件:事件是有序链表中的数据元素,包括 事件发生时间 事件类型(到达事件 ,四个窗口离开事件)

事件的定义

到达事件:每次客户到达产生两个随机数,一个表示该客户需要办理业务的时间 ,另一个表示下一个客户达到的间隔时间
假设第一个客户到达的时间是0,这样便实现了客户的不间断到达。
客户达到后需要找到最短的队列,然后将该客户的到达时间和处理时间插入队列
如果该队列的长度为1,设定一个离开事件并插入事件表

离开事件:
首先确定客户离开的是哪一个队列,删除其队头元素
计算客户逗留时间
如果该队列非空,设定下一个离开事件并插入事件表

模拟结果:

设定每个客户逗留时间不超过三十分钟,两个客户到达时间相隔不超过八分钟,设置营业时间为600分钟,运行结果如下:
平均逗留时间为27.1173分钟。
在这里插入图片描述

上述为书本中的基本思路,但与实际情况肯定有较大出入, 一个明显的问题是:没有更换队列的操作,
倘若某一队列中的人处理事务时间较短,则会造成某个时间一个队列为空,其余队列有两人以上在排队的情况,这在现实中显然是难以发生的
解决方法是在离开事件中加入判断,倘若该队列为空且其余队列有两人以上排队,进行更换队列操作。
更换队列:
1.找到需要更换的客户所在队列
2.将客户转移到空队列
3.设定该队列的一个离开事件

优化后模拟结果

使用同样参数,运行优化后程序,客户平均逗留时间为23.61分钟,有较大提升,且与实际预测情况一致
附加部分代码博客最后。
在这里插入图片描述

核心代码:

初始化

void OpenForDay() {
   
	//初始化操作
	TotalTime = 0; CustomerNum = 0;   //初始化累计事4件和客户数为 0
	InitList(ev);					  //初始事件链表为空表
	en.OccurTime = 0; en.NType = 0;	  //设定第一个客户到达事件
	ListInsert_L(ev, 1, en);		  //插入事件表
	for (int  i = 1; i <= 4; i++)
	{
   
		InitQueue(q[i]);			  //初始化队列
	}
}//OpenForDay

客户到达事件:

void CustomerArrived() {
   
	//处理客户到达事件 en.Type = 0.
	++CustomerNum;
	int durtime, intertime;
	durtime = rand() % 30;		//客户处理事务时间
	intertime = rand() % 8;		//下一个客户到达事件间隔
	int t = en.OccurTime + intertime;  //下一个客户到达时刻
	if (t < CloseTime)
		OrderInsert(ev, {
    t,0 }, cmp);
	int i = Minmum(q);					//找到最短队列
	EnQueue(q[i], {
    en.OccurTime, durtime });	//客户进入队列i
	if (QueueLenth(q[i]) == 1)
		OrderInsert(ev,{
   en.OccurTime + durtime, i}, cmp); //队列长度为1时,设定一个离开事件
}//CustomerArrived

客户离开事件

void CustomerDeparture() {
   
	//处理客户离开事件,en.NTpye>0
	QElemType customer ;
	int i = en.NType;
	DeQueue(q[i], customer);  //删除第i队列的排头客户
	TotalTime += en.OccurTime - customer.ArrivaTime;//累计客户逗留时间
	if (!QueueEmpty(q[i])) {
   
		GetHead(q[i], customer);
		OrderInsert(ev, {
    en.OccurTime + customer.Duration,i }, cmp);//设定第i队列的离开事件
	}
}//CustomerDeparture

模拟过程

void Bank_Simulation() {
   
	OpenForDay();
	while (!ListEmpty(ev)) {
   
		Link p;
		DelFirst(GetHead(ev), p); en = GetCurElem(p);
		if (en.NType == 0) {
   
			CustomerArrived();			//处理客户到达事件
			cout << p->data.OccurTime << " 有客户到达" << endl;

		}
		else {
   
			CustomerDeparture();
			cout << p->data.OccurTime << " 有客户离开" << endl;
		}		//处理客户离开事件
	}
	cout << (float)TotalTime / CustomerNum;
}//Bank_Simulation

其余代码

LinkQueue代码见 队列的基本操作
只需修改 QElemType 数据类型

typedef struct {
   
	int ArrivaTime;		//到达时刻
	int Duration;		//办理事务所需要时间
}QElemType;
  • 7
    点赞
  • 39
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值