离散事件模拟

#include<stdio.h>
#include<stdlib.h>
#include<time.h>
#include<conio.h>

#define ArriveTime 5   //两个相邻客户到达银行的时间间隔不超过5分钟
#define EventTime  30   //每个客户办理业务的事件不超过30分钟
#define ClostTime  100   //关门时间
#define QueueNum   5   //队列数,即窗口数

typedef struct {
 int ArrivalTime ;   //到达时刻
 int Duration ;    //办理事物所需时间
} QElemType;
typedef struct QNode           
{
 QElemType data;
 struct QNode *next;
} QNode, *QueuePtr;
typedef struct                   
{
 QueuePtr front;            //队头指针
 QueuePtr rear;             //队尾指针
} LinkQueue;

void InitQueue(LinkQueue *Q) ;
void EnQueue(LinkQueue *Q, QElemType e) ;
int QueueLength(LinkQueue Q) ;
void DeQueue(LinkQueue *Q, QElemType *e) ;
int QueueEmpty(LinkQueue Q) ;
void GetHead(LinkQueue Q,QElemType *e) ;

//--------------------------------------------------------//

typedef struct {
 int OccurTime ;    //事件发生时刻
 int NType ;     //事件类型,0表示到达事件,1至4表示四个窗口的离开事件
} Event , ElemType;    //事件类型,有序表LinkList的数据元素类型
typedef struct LNode
{
 ElemType data;
 struct LNode *next;
}LNode,*LinkList;
typedef LinkList EventList ; //事件链表类型,定义为有序链表

void InitList(LinkList *L) ;
void OrderInsert(LinkList *L,ElemType e , int (*cmp)(ElemType a , ElemType b )) ; //按序插入
int ListEmpty( LinkList L ) ;
LNode GetHeadL( LinkList L ) ;
int DelFirst( LinkList *L , LNode h , LNode *p ) ;
ElemType GetCurElem( LNode p ) ;

//--------------------------------------------------------//

//--------程序中用到的主要变量--------------//
EventList ev ;    //事件表
Event  en ;    //事件
LinkQueue q[ QueueNum ] ;  //4个客户队列
QElemType customer ;   //客户记录
int   TotalTime , CustomerNum ;//累计客户逗留时间和客户数

int cmp( Event a , Event b ) ;
void OpenForDay( ) ;
void Random( int *durtime , int *intertime ) ;
int Minimun( LinkQueue q[ ] ) ;
void CustomerArrived( ) ;
void CustomerDepture( ) ;
void Bank_Simulation( ) ;

//---------------------------------------------------------//

#include "head.h"

int cmp( Event a , Event b )
{ //依事件a发生时刻< 或 = 或 > 事件b的发生时刻分别返回-1或0或1
 if( a.OccurTime < b.OccurTime )
  return -1 ;
 else
 {
  if( a.OccurTime == b.OccurTime )
   return 0 ;
  else
   return 1 ;
 }
}

void OpenForDay( )
{
 int i ;

 TotalTime = 0 ; CustomerNum = 0 ;
 InitList( &ev ) ;       //初始化事件链表为空表
 en.OccurTime = 0 ; en.NType = 0 ;   //设定第一个客户到达事件
 OrderInsert( &ev , en , cmp ) ;    //插入事件表.OrderInsert:按序插入

 for( i = 1 ; i < QueueNum ; ++ i )
  InitQueue( &q[ i ] ) ;
}

void Random( int *durtime , int *intertime )
{
 srand( (unsigned)time( NULL ) );
 (*durtime) = rand( )%EventTime + 1  ;
// srand( (unsigned)time( NULL ) );
 (*intertime) = rand( )%ArriveTime + 1 ;
}

int Minimun( LinkQueue q[ ]  )
{
 int i , len , minque = 0 , min = 100 ;
 for( i = 1 ; i < QueueNum ; ++ i )
 {
  len = QueueLength( q[ i ] ) ;
  if( len < min )
  {
   min = len ;
   minque = i ;
  }
 }
 return minque ;
}

void CustomerArrived( )
{ //处理客户到达事件en.NType = 0
 int durtime , intertime , i ;
 Event ena ;
 QElemType qet ;

 ++ CustomerNum ;
 printf("Customer %d arrived at %d and ", CustomerNum, en.OccurTime);
 Random( &durtime , &intertime ) ;    //生成随机数
 ena.OccurTime = en.OccurTime + intertime ;  //下一客户到达时刻
 ena.NType = 0 ;
 if( ena.OccurTime < ClostTime )
  OrderInsert( &ev , ena , cmp ) ;

 i = Minimun( q ) ;        //求长度最短队列
 qet.ArrivalTime = en.OccurTime ;
 qet.Duration = durtime ;
 EnQueue( &q[ i ] , qet ) ; 
 if( QueueLength( q[ i ] ) == 1 )
 { 
  ena.OccurTime = en.OccurTime + durtime ;
  ena.NType = i ;
  OrderInsert( &ev , ena , cmp ) ;   //设定第i个队列的一个离开事件并插入事件表
 }
}

void CustomerDepture( )
{ //处理客户离开事件,en.NType > 0
 int i ;
 QElemType customer ;
 ElemType ena ;

 printf("Customer departure at %d\n", en.OccurTime) ;
 i = en.NType ;
 DeQueue( &q[ i ], &customer ) ;     //删除第i队列的排头客户
 TotalTime += en.OccurTime - customer.ArrivalTime ;//累计客户逗留时间

 if( !QueueEmpty( q[ i ] ))      //设定第i队列的一个离开事件并非插入事件表
 {
  GetHead( q[ i ] , &customer ) ;
  ena.OccurTime = en.OccurTime + customer.Duration ;
  ena.NType = i ;
  OrderInsert( &ev , ena , cmp ) ;
 }
}

void Bank_Simulation( )
{
 LNode p ;
 int i = 0 ;

 OpenForDay( ) ;
 while( !ListEmpty( ev ) )
 {
  if( DelFirst( &ev , GetHeadL( ev ) , &p ) )
  {
   en = GetCurElem( p ) ;
   if( 0 == en.NType )
    CustomerArrived( ) ;
   else
    CustomerDepture( ) ;
  }
  if (++i % 10 == 0)
  {
   printf( "\n----- 按任意键,继续 -----" ) ;
   getch( ) ;
   printf( "\n\n" ) ;
  }
 }
 printf( "The Averge Time is %f.\n" , ( float )TotalTime/CustomerNum ) ;
}


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

//被改造的函数

void OrderInsert(LinkList *L,ElemType e , int (*cmp)(ElemType a , ElemType b )) //按序插入
{
 LinkList s , p , q ;
 s = (LinkList)malloc(sizeof(LNode));
 s->data = e;
 
 q = (*L) ;        
 p = q->next ;
 while( p )
 {
  if( cmp( p->data , e ) > 0 )
  {
   s->next = q->next;                  
   q->next = s;
   return ;
  }
  q = p ;
  p = p->next ;
 }
 s->next = (*L)->next ;     //当事件链表为空时
 (*L)->next = s ;
}

 

int DelFirst( LinkList *L , LNode h , LNode *p )
{ //已知h指向线性链表的头结点,删除链表中第一个结点并以p返回
 *p = *(h.next) ;
 if( p )
 {
  h.next = (*p).next ;
  **L = h ;
  return 1 ;     //删除成功
 }
 return 0 ;      //删除失败
}

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值