数据结构-模拟银行业务

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

#define WINDOWS 10  //定义窗口数

typedef struct _Event//事件结构体
{
 struct _Event *next;
 int OccurTime;//事件发生时刻
 int NType;//事件类型(0表示客户到来,其他表示客户离开)
}EventType,*EventList;

typedef struct _Elem//窗口队列中的元素结构体
{
 struct _Elem *next;
 int ArrivalTime;//客户到达时刻
 int Duration;//客户办理业务需要的时间
}ElemType,*ElemList;

typedef struct
{
 ElemList front;
 ElemList rear;
}pElem;//队列的头指针和尾指针

int CustomerNum;//总的客户数
int TotalTime;//总的处理时间
int CloseTime;//关门时间

void InitEventList(EventList *head)//事件链表初始化(可能是多余的,我觉得^_^)
{
 (*head)->next=NULL;
}
void InitElemList(pElem *ptr)//窗口队列初始化
{
 ElemType *p=(ElemType *)malloc(sizeof(ElemType));
 p->next=NULL;
 ptr->front=ptr->rear=p;
}
void EnterEvList(EventList *head,EventType en)//事件链表的插入操作
{
 EventType *tmp1=(*head)->next,*tmp2=(*head);//tmp2是tmp1的前驱
 EventType *tmp=(EventList)malloc(sizeof(EventType));
 tmp->NType=en.NType;
 tmp->OccurTime=en.OccurTime;
 tmp->next=NULL;
 while(tmp1)
 {
  if(tmp1->OccurTime>tmp->OccurTime)
  {
   tmp2->next=tmp;
   tmp->next=tmp1;
   return;
  }
  else
  {
   tmp1=tmp1->next;
   tmp2=tmp2->next;
  }
 }
 if(!tmp1)
 {
  tmp2->next=tmp;
 }
}
void Push(pElem *ptr,ElemType custo)//队列的入队操作
{
 ElemType *tmp=(ElemType *)malloc(sizeof(ElemType));
 tmp->ArrivalTime=custo.ArrivalTime;
 tmp->Duration=custo.Duration;
 tmp->next=NULL;
 ptr->rear->next=tmp;
 ptr->rear=tmp;
}
void DeEvList(EventList *head,EventType *p)//链表的删除操作
{
 EventType *tmp;
 if(NULL==(*head)->next)
 {
  printf("The List is Empty\n");
  return;
 }
 p->NType=(*head)->next->NType;
 p->OccurTime=(*head)->next->OccurTime;
 tmp=(*head)->next;
 (*head)->next=(*head)->next->next;
 free(tmp);
}
void GetHeadQU(pElem *ptr,ElemType *p)//取队列的头结点
{
 p->ArrivalTime=ptr->front->next->ArrivalTime;
 p->Duration=ptr->front->next->Duration;
}
void Pop(pElem *ptr,ElemType *p)//队列的出队操作
{
 ElemType *tmp;
 if(ptr->front==ptr->rear)
 {
  printf("The Queue is Empty\n");
  return;
 }
 p->ArrivalTime=ptr->front->next->ArrivalTime;
 p->Duration=ptr->front->next->Duration;
 tmp=ptr->front->next;
 ptr->front->next=ptr->front->next->next;
 if(NULL==ptr->front->next)
 {
  ptr->rear=ptr->front;
 }
}
int Length_LIST(EventList *head)//取链表的长度
{
 EventType *p=(*head)->next;
 int i=0;
 while(p)
 {
  i++;
  p=p->next;
 }
 return i;
}
int Length_QU(pElem*ptr)//取队列的长度
{
 ElemType *p=ptr->front->next;
 int i=0;
 while(p)
 {
  i++;
  p=p->next;
 }
 return i;
}
int Minimum(pElem **ptr)//求最短的队列
{
 int i,tmp2=1;
 int tmp=Length_QU(ptr[1]);
 for(i=2;i<=WINDOWS;i++)
 {
  if(tmp>Length_QU(ptr[i]))
  {
   tmp2=i;
   tmp=Length_QU(ptr[i]);
  }
 }
 return tmp2;
}
int EmptyList(EventList *head)//判断链表是否为空
{
 if(NULL==(*head)->next)
  return 1;
 else
  return NULL;
}
int EmptyQU(pElem *ptr)//判断队列是否为空
{
 if(ptr->front==ptr->rear)
  return 1;
 else
  return NULL;
}
void Random(int *durtime,int *intertime)//产生随机数
{
 srand(time(NULL));
 *durtime=rand()%10+5;
 *intertime=rand()%4+1;
}
void OpenForDay(EventList *head,pElem **ptr)
{
 EventType en;
 TotalTime=0;
 CustomerNum=0;
 InitEventList(head);
 en.NType=0;
 en.OccurTime=0;
 EnterEvList(head,en);
 for(int i=1;i<=WINDOWS;i++)
 {
  InitElemList(ptr[i]);
 }
}
void CustomerArrived(EventType en,EventList *head,pElem **ptr)
{
 int durtime,intertime,t,i;
 EventType tmp;
 ElemType tmp1;
 ++CustomerNum;
 Random(&durtime,&intertime);
 t=en.OccurTime+intertime;
 printf("客户到达 到达时间为 %d\n",en.OccurTime);
 tmp.NType=0;
 tmp.OccurTime=t;
 if(t<CloseTime)
  EnterEvList(head,tmp);
 i=Minimum(ptr);
 tmp1.ArrivalTime=en.OccurTime;
 tmp1.Duration=durtime;
 Push(ptr[i],tmp1);
 if(Length_QU(ptr[i])==1)
 {
  tmp.NType=i;
  tmp.OccurTime=en.OccurTime+durtime;
  EnterEvList(head,tmp);
 }
}

void CustomerDeparture(EventType en,EventList *head,pElem **ptr)
{
 int i;
 ElemType p;
 EventType tmp;
 i=en.NType;
 Pop(ptr[i],&p);
 TotalTime+=(en.OccurTime-p.ArrivalTime);
 printf("客户离开 所在的窗口为 %d,到达时间是 %d,离开时间是 %d\n",i,p.ArrivalTime,en.OccurTime);
 if(!EmptyQU(ptr[i]))
 {
  GetHeadQU(ptr[i],&p);
  tmp.NType=i;
  tmp.OccurTime=p.Duration+en.OccurTime;
  EnterEvList(head,tmp);
 }
}

void Bank_Simulation(int CloseTime,EventList *head,pElem **ptr)
{
 OpenForDay(head,ptr);
 EventType tmp;
 while(!EmptyList(head))
 {
  DeEvList(head,&tmp);
  if(tmp.NType==0)
   CustomerArrived(tmp,head,ptr);
  else
   CustomerDeparture(tmp,head,ptr);
 }
 printf("总处理时间%d\n",TotalTime);
 printf("总的客户数%d\n",CustomerNum);
 printf("The Average Time is %f\n",(float)TotalTime/CustomerNum);
}
int main()

 pElem *ptr[WINDOWS+1];
 EventType *tmp=(EventType*)malloc(sizeof(EventType));
 tmp->next=NULL;
 EventList *head=&tmp;
 printf("Please input the close time(minutes):");
 scanf("%d",&CloseTime);
 for(int i=1;i<=WINDOWS;i++)
 {
  ptr[i]=(pElem*)malloc(sizeof(pElem));
 }
 Bank_Simulation(CloseTime,head,ptr);
 return 0;
}

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
【问题描述】 客户业务分为两种。第一种是申请从银行得到一笔资金,即取款或借款。第二种是向银行投入一笔资金,即存款或还款。银行有两个服务窗口,相应地有两个队列。客户到达银行后先排第一个队。处理每个客户业务时,如果属于第一种,且申请额超出银行现存资金总额而得不到满足,则立刻排入第二个队等候,直至满足时才离开银行;否则业务处理完后立刻离开银行。每接待完一个第二种业务的客户,则顺序检查和处理(如果可能)第二个队列中的客户,对能满足的申请者予以满足,不能满足者重新排到第二个队列的队尾。注意,在此检查过程中,一旦银行资金总额少于或等于刚才第一个队列中最后一个客户(第二种业务)被接待之前的数额,或者本次已将第二个队列检查或处理了一遍,就停止检查(因为此时已不可能还有能满足者)转而继续接待第一个队列的客户。任何时刻都只开一个窗口。假设检查不需要时间。营业时间结束时所有客户立即离开银行。 写一个上述银行业务的事件驱动模拟系统,通过模拟方法求出客户在银行内逗留的平均时间。 【基本要求】 利用动态存储结构实现模拟。 【测试数据】 一天营业开始时银行拥有的款额为10000(元),营业时间为600(分钟)。其他模拟参 量自定,注意测定两种极端的情况:一是两个到达事件之间的间隔时间很短,而客户的交易时间很长,另一个恰好相反,设置两个到达事件的间隔时间很长,而客户的交易时间很短。 【实现提示】 事件有两类:到达银行和离开银行。初始时银行现存资金总额为total。开始营业后的第一今事件是客户到达,营业时间从0到closetime。到达事件发生时随机地设置此客户的交易时间和距下一到达事件之间的时间间隔。每个客户要办理的款额也是随机确定的,用负值和正值分别表示第一类和第二类业务。变量total,closetime以及上述两个随机量的上下界均交互地从终端读入,作为模拟参数。 两个队列和一个事件表均要用动态存储结构实现。注意弄清应该在什么条件下设置离开事件,以及第二个队列用怎样的存储结构实现时可以获得较高的效率。注意:事件表是按时间顺序有序的。 【选作内容】 自己实现动态数据类型。例如对于客户结点,定义pool为 CustNodepoolfMAX]; // 结构类型CustNode含四个域:aITHIne,durtime,amount,next 或者定义四个同样长的,以上述域名为名字的数组。初始时,将所有分量的next域链接起来,形成一个静态链找,设置一个楼顶元素下标指示量top,top=0表示找空。动态存储分配函数可以取名为myMalloc,其作用是出钱,将钱顶元素的 下标返回。若返回的值为0,则表示无空间可分配。归还函数可取名为myFree,其作用是把该分量入钱。用FOR-TRAN和BASIC等语言实现时只能如此地自行组织。 自己手写的数据结构作业,选做部分也实现。

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值