离散事件模拟——银行排队

某银行有四个窗口接待客户,每个窗口在某个时刻只能接待一个客户,人数多时则需要进行排队,刚进来的客户,窗口无人则进行业务办理,有人则排队,排在人数最少的队伍后面。
问题:计算在银行关闭之前,计算客户在银行逗留的平均时间

用c写的,给书上代码的实现了下,代码如下:

#include <stdio.h>
#include<malloc.h>
#include <stdlib.h>
#include <time.h>
typedef struct {
	int OccurTime;
	int NType;//事件0,1,2,3,4
}ElemType; 

typedef struct Lnode {
	ElemType data;
	struct Lnode* next;
}Lnode, * LinkList; //事件表,链表

typedef LinkList EvenList;//事件链表类型

typedef struct {
	int ArrivalTime;//到达时刻
	int Duration; //办理事务事件
}QElemType;//队列

typedef struct QNode {
	QElemType data;  
	struct QNode* next; 
}QNode, * QueuePtr;//银行排队链表

typedef struct {
	QueuePtr front;
	QueuePtr rear;
}LinkQueue;//队列


EvenList ev; //事件驱动
ElemType en; //事件
LinkQueue Q[5];//排队器
QElemType customer; //排队中的人
int TotalTime, CustomerNum; //总时间 总人数


void LinkInit(LinkList& L) { // 事件初始化
	L = (LinkList)malloc(sizeof(Lnode));
	L->next = NULL;
}
void LinkInsert(LinkList L, int i, ElemType e) //事件插入
{
	if (i <= 0)	return;
	int  j = 0;
	while (L && j < i - 1) {
		L = L->next;
		j++;
	}
	if (!L) return;
	LinkList s = (LinkList)malloc(sizeof(Lnode));
	s->data = e;
	s->next = L->next;
	L->next = s;

}
void LinkDispaly(LinkList L) {  //打印
	//printf("%d ", L->data);
	while (L = L->next)
	{
		printf("%d ", L->data.OccurTime);
	}
	printf("\n");
}
int Order(LinkList L, ElemType e) {//事件在链表中的位置,按大小顺序
	int i = 1;
	while (L=L->next)
	{
		if (e.OccurTime > L->data.OccurTime) {
			i++;
		}
	}
	return i;
}
void QueueInit(LinkQueue& Q) {
	QueuePtr node = (QueuePtr)malloc(sizeof(QNode));
	node->next = NULL;
	Q.front = node;
	Q.rear = node;
}
void QeueInsert(LinkQueue& Q, QElemType e) {
	QueuePtr node = (QueuePtr)malloc(sizeof(QNode));
	Q.rear->data = e;
	node->next = Q.rear->next;
	Q.rear->next = node;
	Q.rear = node;
}
QElemType QeueDelete(LinkQueue& Q) {
	QElemType re;
	re.ArrivalTime = NULL;
	re.Duration = NULL;
	if (Q.front == Q.rear) {
		return re;
	}
	QueuePtr s;
	re = Q.front->data;
	s = Q.front;
	Q.front = Q.front->next;
	free(s);
	return re;
}
int QueueLength(LinkQueue Q) {
	int count = 0;
	while (Q.front != Q.rear)
	{
		count++;
		Q.front = Q.front->next;
	}
		return count;
}
int MinLength(LinkQueue *Q) {
	int re = 1;
	for (int i = 1; i <=4 ; i++)
	{
		re = QueueLength(Q[i - 1]) > QueueLength(Q[i]) ? i : re;
	}
	return re;
}
QElemType QueueHead(LinkQueue Q) {
	return Q.front->data;
}
void OpenForDay() {
	TotalTime = 0;
	CustomerNum = 0;
	LinkInit(ev);
	en.OccurTime = 0;
	en.NType = 0;
	LinkInsert(ev, 1, en);
	for (int i = 1; i <= 4; i++)
	{
		QueueInit(Q[i]);
	}
}
void CustomerArrived(ElemType e,int CloseTime) {
	int i;
	QElemType re;
	CustomerNum++;
	srand((unsigned)time(NULL));
	int intertime = rand() % 10+3;
	int durtime = rand() % 10+10;
	en.NType = 0;
	en.OccurTime = intertime + e.OccurTime;
	re.ArrivalTime = e.OccurTime;
	re.Duration = durtime;

	if (en.OccurTime < CloseTime) {
		LinkInsert(ev, Order(ev, en), en);
	}

	i = MinLength(Q);
	QeueInsert(Q[i], re);

	en.OccurTime = e.OccurTime + durtime;
	en.NType = i;
	if (QueueLength(Q[i]) == 1) {
		LinkInsert(ev,Order(ev,en),en);
	}
}
void CustomerDeparture(ElemType e) {
	int i = e.NType;
	ElemType re;
	customer = QeueDelete(Q[i]);
	TotalTime += e.OccurTime - customer.ArrivalTime;
    if(QueueLength(Q[i])!=0){
		customer = QueueHead(Q[i]);
		re.NType = i;
		re.OccurTime = customer.Duration + e.OccurTime;
		LinkInsert(ev, Order(ev, re), re);
	}
}
void Bank_Simulation(int CloseTime) {
	LinkList q;
	OpenForDay();
	ev = ev->next;
	while (ev->data.OccurTime<CloseTime)
	{
		if (ev->data.NType == 0) {
			CustomerArrived(ev->data, CloseTime);
		}
		else
		{
			CustomerDeparture(ev->data);
		}
		q = ev;
		ev = ev->next;
		free(q);
		printf("当前时间表:");
		LinkDispaly(ev);
		printf("当前总时间:%d,当前总人数:%d \n \n", TotalTime, CustomerNum);

		
	}
	printf("%f\n", (float)TotalTime / CustomerNum);
}


int main() {
   	Bank_Simulation(1000);
	return 0;
}
  • 0
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值