离散事件模拟-数据结构算法

问题说明几点:

①顾客逗留时间的计算,应该是离开事件发生的时刻减去这个顾客入队的时间,因为顾客在中间还有等待排队尚未办理业务的时候


②设置离开事件有如下几种情况:

Ⅰ这个顾客是第一个入队的,那么他离开的时间就是入队的时间和办理业务的时间

Ⅱ这个顾客是在前一个顾客离开后去办理业务的,那么他的离开时间就是前一个顾客的离开时间(时刻)加上他办理业务的时间


③本次算法用了队列和链表,主函数有四个,其中两个是核心的,除此之外包括一些基本操作函数


④随机数的设定用rand函数,但是要取模,rand函数丢给durtime和interval(书上是intertime,我觉得interval好理解)的值往往很大,如果不取模那么银行估计只能来极少数顾客了


⑤写这个算法之前,应该思路清晰,建议画流程图,写伪码,取好变量名(算法变量很多)以及准备好数据结构,最后再写代码


代码如下,希望能帮到你:

#include "stdafx.h" 
#include<stdio.h>
#include<iostream>
#include<assert.h>
#include<stdlib.h>
#define Status int 
#define OK 1
#define OVERFLOW -1
#define ERROR 0
typedef struct Linklist
{
	int occurtime;
	int EType;
	struct Linklist *next;
}*EvenList,Even;//事件链表和单个事件
typedef struct Linkqueue
{
	int timefordeal;//办理业务的时间
	int enqueuetime;//入队时间
	struct Linkqueue *next;
}QElemtype;//队列元素
typedef struct Manageforqueue
{
	QElemtype *front;
	QElemtype *rear;
	int        qlength;//队列长度
}Mngfq;//队列的管理结构

int Totaltime = 0;
int CustomerNum = 0;//全局
int Closetime = 200;
const int SIZE = 4;

void BankSimulation();
void BankOpen(EvenList *evlist, Mngfq Q[SIZE]);
void DeForCuArrival(Even en, EvenList evlist, Mngfq Q[SIZE]);
void DeForCuDepart(Even en, EvenList evlist, Mngfq Q[SIZE]);
void BankClose();
Status InitLinklist(EvenList *evlist);
Status OrderInsert(EvenList evlist, Even *en);
Status Pop(EvenList evlist);
Status GetLhead(EvenList evlist, Even *en);
bool IsLEmpty(EvenList evlist);
int MinQLength(Mngfq Q[SIZE]);
int QLength(Mngfq *Q);
Status Enqueue(Mngfq *Q, QElemtype *customer);
Status Dequeue(Mngfq *Q);
Status GetQhead(Mngfq *Q, QElemtype *customer);
Status InitQ(Mngfq Q[SIZE]);
bool IsQEmpty(Mngfq *Q);

int main()
{
	BankSimulation();
	return 0;
}

void BankSimulation()
{//银行模拟框架函数
	Mngfq Q[SIZE];
	EvenList evlist;
	BankOpen(&evlist, Q);
	while(!IsLEmpty(evlist))
	{
		Even en;
		GetLhead(evlist, &en);
		Pop(evlist);
		if (en.EType == 0)
			DeForCuArrival(en,evlist, Q);
		else
			DeForCuDepart(en, evlist, Q);
	}
	BankClose();
}

void BankOpen(EvenList *evlist, Mngfq Q[SIZE])
{
	InitQ(Q);
	InitLinklist(evlist);

	Even *en = (Even*)malloc(sizeof(Even));
	assert(en != NULL);

	en->EType = 0;
	en->occurtime = 0;
	en->next = NULL;

	OrderInsert(*evlist, en);
}

void  DeForCuArrival(Even en, EvenList evlist, Mngfq Q[SIZE])
{//处理用户到来事件
	CustomerNum++;
	int durtime, interval;
	interval = rand() % 15;
	durtime = rand() % 31;//随机数设定

	QElemtype *customer = (QElemtype*)malloc(sizeof(QElemtype));
	assert(customer != NULL);
	customer->timefordeal = durtime;//办理业务的时间
	customer->enqueuetime = en.occurtime;//来的时刻就是入队的时刻
	customer->next = NULL;//防止野指针操作

	int i;
	i = MinQLength(Q);//寻找最短队列
	Enqueue(&Q[i - 1], customer);
	if (QLength(&Q[i - 1]) == 1)//该顾客是队列中的第一个
	{
		Even *enforle = (Even*)malloc(sizeof(Even));
		assert(enforle != NULL);

		enforle->EType = i;
		enforle->occurtime = customer->enqueuetime + customer->timefordeal;
		enforle->next = NULL;
		OrderInsert(evlist, enforle);
	}//将离开事件插入到事件表中

	if (en.occurtime + interval < Closetime)//下一个顾客来的时候银行还未结业
	{
		Even *enforcome = (Even*)malloc(sizeof(Even));
		assert(enforcome != NULL);

		enforcome->occurtime = en.occurtime + interval;
		enforcome->EType = 0;
		enforcome->next = NULL;
		OrderInsert(evlist, enforcome);
	}
}

void DeForCuDepart(Even en, EvenList evlist, Mngfq Q[SIZE])
{//处理顾客离开事件
	QElemtype customer_leave;
	customer_leave.next = NULL;
	GetQhead(&Q[en.EType - 1], &customer_leave);//获取该顾客信息

	Totaltime += en.occurtime - customer_leave.enqueuetime;//计算逗留时间                      
	Dequeue(&Q[en.EType - 1]);//顾客离开
	if (!IsQEmpty(&Q[en.EType - 1]))
	{
		Even *enforleave = (Even*)malloc(sizeof(Even));
		assert(enforleave != NULL);

		QElemtype customer;
		customer.next = NULL;
		GetQhead(&Q[en.EType - 1], &customer);
		enforleave->EType = en.EType;
		enforleave->occurtime = en.occurtime + customer.timefordeal;
		enforleave->next = NULL;
		OrderInsert(evlist, enforleave);
	}//准备下一个顾客的离开事件
}

void BankClose()
{//输出一天中银行流量和顾客平均逗留时间
	using namespace std;
	cout << "The total of customer is : " << CustomerNum << endl;
	cout << "The average time of customers in bank : " << double(Totaltime) / CustomerNum << endl;
}

bool IsLEmpty(EvenList evlist)
{//判空事件表
	return evlist->next == NULL;
}

Status InitQ(Mngfq Q[SIZE])
{//初始化四个队列为空队列
	for (int i = 0; i < 4; i++)
	{
		Q[i].front = Q[i].rear = (QElemtype*)malloc(sizeof(QElemtype));
		if (Q[i].front == NULL)
			return OVERFLOW;
		Q[i].front->next = NULL;
		Q[i].qlength = 0;
	}
	return OK;
}

Status InitLinklist(EvenList *evlist)
{//初始化链表为空链表
	*evlist = (Even*)malloc(sizeof(Even));
	if (*evlist == NULL)
		return OVERFLOW;
	(*evlist)->next = NULL;
	return OK;
}

Status OrderInsert(EvenList evlist, Even *en)
{//将事件en按事件发生先手顺序插入到事件表evlist中
	Even *p = evlist;
	while (p->next != NULL && p->next->occurtime < en->occurtime)
		p = p->next;

	en->next = p->next;
	p->next = en;
	return OK;
}

int MinQLength(Mngfq Q[SIZE])
{//返回四个队列中最短队列的序号
	int i = Q[0].qlength;
	for (int j = 1; j < 4; j++)
		if (Q[i].qlength > Q[j].qlength)
			i = j;

	return i+1;//返回最短队列序号
}

Status Enqueue(Mngfq *Q, QElemtype *customer)
{//使顾客入队列
	Q->rear->next = customer;
	Q->rear = customer;
	Q->qlength++;//队列长度增1
	return OK;
}

int QLength(Mngfq *Q)
{//返回队列Q的长度
	return Q->qlength;
}

Status GetQhead(Mngfq *Q, QElemtype *customer)
{//使customer存贮Q队列第一个顾客的信息
	customer->enqueuetime = Q->front->next->enqueuetime;
	customer->timefordeal = Q->front->next->timefordeal;
	return OK;
}

Status Dequeue(Mngfq *Q)
{//使Q队列的第一个顾客出队
	if (IsQEmpty(Q))
		return ERROR;//空队列

	QElemtype *q;
	q = Q->front->next;
	Q->front->next = q->next;
	free(q);
	if (Q->front->next == NULL)
		Q->rear = Q->front;
	Q->qlength--;
	return OK;
}

bool IsQEmpty(Mngfq *Q)
{//判空队列
	return Q->qlength == 0;
}

Status Pop(EvenList evlist)
{//删除链表中的第一个事件
	if (IsLEmpty(evlist))
		return ERROR;

	Even *q;
	q = evlist->next;
	evlist->next = q->next;
	free(q);
	return OK;
}

Status GetLhead(EvenList evlist, Even *en)
{//获取事件表中的第一个事件,用en返回这个事件
	en->EType = evlist->next->EType;
	en->occurtime = evlist->next->occurtime;
	en->next = NULL;
	return OK;
}


猜你喜欢

转载自blog.csdn.net/weixin_41133154/article/details/79033300
今日推荐