#include <algorithm>
#include <cstdlib>
#include <cstdio>
using namespace std;
typedef int Status;
typedef struct Event
{
int OccurTime; //事件发生时刻
int NType; //事件类型,0表示到达事件,1-4表示四个窗口的离开事件
struct Event *next;
}Event,ElemType; //事件类型,有序链表LinkList的数据元素类型
typedef Event LinkList,EventList; //事件链表类型,定义为有序链表
typedef struct QElemType
{
int ArrivalTime; //到达时刻
int Duration; //办理事务所需时间
struct QElemType *next;
}QElemType; //队列的数据元素类型
typedef struct
{
QElemType *head; //队头
QElemType *tail; //队尾
}LinkQueue;
EventList Ev; //事件表
Event En; //事件
QElemType Customer; //客户记录
int TotalTime; //总的客户逗留时间
int CustomerNum; //总的客户数
LinkQueue q[5]; //4个客户队列
Status InitList(LinkList *L) //初始化事件表
{
L->OccurTime=0;
L->NType=0;
L->next=NULL;
return 1;
}
Status OrderInsert(LinkList *L,Event *evt) //按顺序将事件插入事件表
{
Event *L1,*L2;
L2=(Event *)malloc(sizeof(Event));
if (L2==NULL) return -2;
L2->OccurTime=evt->OccurTime;
L2->NType=evt->NType;
L2->next=NULL;
L->NType++;
if (L->next==NULL)
{
L->next=L2;
L2->next=NULL;
}
else
{
L1=L;
while (L1->next!=NULL && L1->next->OccurTime<L2->OccurTime)
{
L1=L1->next;
}
L2->next=L1->next;
L1->next=L2;
}
return 1;
}
Status ListEmpty(LinkList *L) //检查窗口是否有人
{
if (L->next==NULL) return 1;
return 0;
}
Status DelFirst(LinkList *L,Event *evt) //取出时间表里面的事件
{
Event *L1;
if (L->next==NULL) return 0;
L->NType--;
L1=L->next;
evt->OccurTime=L1->OccurTime;
evt->NType=L1->NType;
L->next=L1->next;
free(L1);
return 1;
}
Status InitQueue(LinkQueue *Q) //初始化事件队列
{
QElemType *Q1;
Q1=(QElemType *)malloc(sizeof(QElemType));
if (!Q1) return -2;
Q1->ArrivalTime=0;
Q1->Duration=0;
Q1->next=NULL;
Q->head=Q1;
Q->tail=Q1;
return 1;
}
Status GetHead(LinkQueue *Q,QElemType *cut) //取出事件
{
QElemType *Q1;
if (Q->head==Q->tail) return 0;
Q1=(Q->head)->next;
cut->ArrivalTime=Q1->ArrivalTime;
cut->Duration=Q1->Duration;
return 1;
}
Status EnQueue(LinkQueue *Q,QElemType *cut) //插入事件到事件队列
{
QElemType *Q1,*Q2;
Q2=(QElemType *)malloc(sizeof(QElemType));
if (!Q2) return -2;
Q2->ArrivalTime=cut->ArrivalTime;
Q2->Duration=cut->Duration;
Q2->next=NULL;
Q1=Q->head;
Q1->Duration++;
(Q->tail)->next=Q2;
Q->tail=Q2;
return 1;
}
Status DeQueue(LinkQueue *Q,QElemType *cut) //在事件队列里面删除已办完事件
{
QElemType *Q1,*Q2;
Q1=Q->head;
Q1->Duration--;
Q2=(Q->head)->next;
if (!Q2) return 0;
cut->ArrivalTime=Q2->ArrivalTime;
cut->Duration=Q2->Duration;
Q1->next=Q2->next;
if (Q1->next==NULL) Q->tail=Q1;
free(Q2);
return 1;
}
int MinQueue(LinkQueue Q[],int n) //选出发生最早的事件
{
int temp;
int i,min;
min=1;
temp=Q[1].head->Duration;
for (i=2;i<n;i++)
{
if (Q[i].head->Duration<temp)
{
temp=Q[i].head->Duration;
min=i;
}
}
return min;
}
void OpenForDay() //初始化操作
{
int i;
TotalTime=0; //初始化总的时间为0
CustomerNum=0; //初始化总的客户数为0
InitList(&Ev); //初始化事件链表为空
En.OccurTime=0; //设定第一个客户到达事件
En.NType=0; //
OrderInsert(&Ev,&En); //插入事件表
q[0].head=q[0].tail=NULL;
for (i=1;i<5;i++) //置空队列
{
InitQueue(&q[i]);
}
}
void CustomerArrived() //处理客户到达事件
{
Event en;
QElemType cu;
double durtime,intertime;
int i,t;
int a=1,b=20,x=1,y=5;
durtime=a+rand()%(b-a+1); //生成随机数
intertime=x+rand()%(y-x+1); //生成随机数
++CustomerNum;
t=En.OccurTime+intertime; //下一个客户到达时间
if (t<480) //银行没关门则插入事件表
{
en.OccurTime=t;
en.NType=0;
en.next=NULL;
OrderInsert(&Ev,&en);
}
cu.ArrivalTime=En.OccurTime;
cu.Duration=durtime;
i=MinQueue(q,5); //求长度最短的队列
EnQueue(&q[i],&cu); //插入最短的队列
if (q[i].head->Duration==1)
{
en.OccurTime=cu.ArrivalTime+cu.Duration;
en.NType=i;
en.next=NULL;
OrderInsert(&Ev,&en);
}
}
void CustomerDeparture() //处理客户离开事件
{
Event en;
int i=0;
i=En.NType;
DeQueue(&q[i],&Customer); //删除第i队列的排头客户
TotalTime+=En.OccurTime-Customer.ArrivalTime; //累计逗留时间
if (q[i].head->Duration!=0) //设定第i队列的一个离开事件并插入事件表
{
GetHead(&q[i],&Customer);
en.NType=i;
en.OccurTime=En.OccurTime+Customer.Duration;
OrderInsert(&Ev,&en);
}
}
int main()
{
OpenForDay();
while (!ListEmpty(&Ev)) //当事件表不为空
{
DelFirst(&Ev,&En);
if (En.NType==0) //如果为到达事件则处理到达事件
{
CustomerArrived();
}
else
{
CustomerDeparture();
}
}
printf("总时间=%d\n总人数=%d\n",TotalTime,CustomerNum);
printf("平均时间 %.3f\n ",(float)TotalTime/CustomerNum);
return 0;
}
数据结构_离散事件的模拟
最新推荐文章于 2022-05-06 20:15:15 发布