数据结构_离散事件的模拟

#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;
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值