離散事件模擬實驗
阿新 • • 發佈:2019-02-13
#include<stdio.h> #include<stdlib.h> #include<time.h> typedef struct { int OccurTime; //事件發生時刻; int NType; //0表示到達事件,1~4表示四個視窗的離開事件 }Event; //事件型別,有序連結串列LinkList的資料元素型別 typedef struct ENode //事件連結串列型別 { Event data; struct ENode *next; }ENode,*EventList; typedef struct { int ArrivalTime; //到達銀行時間 int Duration; //辦理事務所需時間 }QElemType; //佇列的資料元素型別 typedef struct QNode { QElemType data; struct QNode *next; }QNode,*QueuePtr; typedef struct { QueuePtr front; //隊頭指標 QueuePtr rear; //隊尾指標 int num; }LinkQueue; int TotalTime; //記錄客戶總逗留時間 int CustomerNum; //記錄總的客戶 int CloseTime=9; //銀行關門時間初始化為22點 //函式原型宣告: void InitList(EventList &ev); //構造空表 void InitQueue(LinkQueue &Q); //構造空佇列 void OpenForDay(EventList &ev,LinkQueue Q[5]); //初始化操作 void CustomerArrived(EventList &ev,LinkQueue Q[5],Event en); //客戶到達函式 int Minimum(LinkQueue Q[5]); //找幾個中佇列人數最少的那隊 int ListEmpty(EventList ev); //判斷事件表是否為空; void Delfirst(EventList &ev,Event &p); void Bank_Simulation(EventList &ev,LinkQueue Q[5]); void CustomerDeparture(EventList &ev,LinkQueue Q[5],Event en); void DelQueue(LinkQueue &Q,QElemType &customer); //刪除隊頭元素 int QueueEmpty(LinkQueue Q); //判斷空佇列函式 void GetHead(LinkQueue Q,QElemType &customer); //取隊頭元素 void EnQueue(LinkQueue &Q,int n,int m); //在隊尾插入元素 int QueueLength(LinkQueue Q); //求佇列長度 void OrderInsert(EventList &ev,Event en); void show(EventList ev); void ShowQ(LinkQueue Q); //主函式 int main() { EventList ev; LinkQueue Q[5]; //****************** Bank_Simulation(ev,Q); return 0; } //* void Bank_Simulation(EventList &ev,LinkQueue Q[5]) { //***************** int n=5; OpenForDay(ev,Q); //初始化 Event p; while(ListEmpty(ev)!=1) //條件事件表不空 { printf("*********************************\n"); Delfirst(ev,p); //刪除第一個事件,資訊存放在p中 //ok printf("1=%d ",p.NType); printf("2=%d\n",p.OccurTime); if(p.NType==0) { CustomerArrived(ev,Q,p); //=0,則處理客戶到來事件 } else CustomerDeparture(ev,Q,p); //>0則處理客戶離開事件 show(ev); printf("[到銀行的時間.辦事時間]:\n"); for(int j=1;j<=4;j++) { ShowQ(Q[j]); } } printf("客戶總數: %d\n",CustomerNum); printf("客戶逗留總時間: %d\n",TotalTime); printf("平均時間: %f\n",(float)TotalTime/CustomerNum); } //處理客戶到達事件,en.NType=0; void CustomerArrived(EventList &ev,LinkQueue Q[5],Event en) { srand(time(0)); int durtime; //辦理業務的時間 int intertime; //下一位客戶的間隔時間 int i; //數量最少的佇列 Event x,y; CustomerNum++; //客戶總數+1; //test printf("客戶總數:%d\n",CustomerNum); durtime=rand()%5+1; //範圍在1~100之間 printf("業務時間:%d\n",durtime); intertime=rand()%2+1; printf("間隔時間:%d\n",intertime); x.OccurTime=en.OccurTime+intertime; //下一個使用者到達的時間 printf("下一個使用者到達的時間:%d\n",x.OccurTime); x.NType=0; if(x.OccurTime<CloseTime) { OrderInsert(ev,x);//插入事件表 } i=Minimum(Q); //求長度最短佇列 EnQueue(Q[i],en.OccurTime,durtime); //入隊 y.NType=i; // printf("哪一個佇列=%d\n",y.NType); y.OccurTime=en.OccurTime+durtime; printf("使用者離開時間=%d\n",y.OccurTime); // printf("Q[i].num=%d\n",Q[i].num); if(Q[i].num==1) { OrderInsert(ev,y);//設定第i佇列的一個離開事件並插入事件表 } return ; } //處理客戶離開事件 en.NType>0 void CustomerDeparture(EventList &ev,LinkQueue Q[5],Event p) { // printf("p.NType=%d\n",p.NType); int i=p.NType; Event x; QElemType customer; DelQueue(Q[i],customer); //刪除第i佇列的排頭客戶 TotalTime+=p.OccurTime-customer.ArrivalTime; //累計客戶逗留時間 // printf("客戶總逗留時間:%d\n",TotalTime); if(Q[i].front!=Q[i].rear) //若佇列不空,設定一個新的隊頭客戶離開事件 { GetHead(Q[i],customer); x.NType=i; x.OccurTime=p.OccurTime+customer.Duration; printf("%d %d\n",x.NType,x.OccurTime); OrderInsert(ev,x); } } //取某一隊的隊頭元素函式 void GetHead(LinkQueue Q,QElemType &customer) { customer=Q.rear->data; } //刪除隊頭元素 void DelQueue(LinkQueue &Q,QElemType &customer) { if(Q.front==Q.rear) { printf("該佇列為空!\n"); return; } QueuePtr p; p=Q.front->next; customer=p->data; Q.front->next=p->next; Q.num--; if(Q.rear==p) Q.rear=Q.front; free(p); } //刪除事件表中第一個事件,資訊存在p中 void Delfirst(EventList &ev,Event &p) { if(ev->next==NULL) return; else { p=ev->next->data; ev->next=ev->next->next; } } //尋找人數最少佇列 int Minimum(LinkQueue Q[5]) { int i; int min=1; for(i=1;i<=4;i++) { if(Q[min].num>Q[i].num) { min=i; } } return min; } //構造空表函式ok1 void InitList(EventList &ev) { EventList en; ev=(EventList)malloc(sizeof(ENode)); if(ev==NULL) { printf("構建空表失敗!"); exit(0); } ev->next=NULL; en=(EventList)malloc(sizeof(ENode)); en->data.NType=0; en->data.OccurTime=0; en->next=ev->next; ev->next=en; } //初始化函式ok2 void OpenForDay(EventList &ev,LinkQueue Q[5]) { int i; Event en; TotalTime=0; //初始化客戶總逗留時間為0; CustomerNum=0; //初始化總的客戶數量為0; InitList(ev); //構建空表; ev->data.OccurTime=0; //設定第一個客戶到達事件 ev->data.NType=0; en.NType=0; en.OccurTime=0; OrderInsert(ev,en); for(i=1;i<=4;i++) //構造空佇列 { InitQueue(Q[i]); //test ShowQ(Q[i]); } } //在事件表插入元素ok3 void OrderInsert(EventList &ev,Event en) { EventList p; EventList q=ev; p=(EventList)malloc(sizeof(ENode)); p->data.NType=en.NType; p->data.OccurTime=en.OccurTime; while(q->next!=NULL) { if(q->next->data.OccurTime==0 ||en.OccurTime<q->next->data.OccurTime) { p->next=q->next; q->next=p; return; } else { q=q->next; } } return; } //展示事件表函式ok4 void show(EventList ev) { while(ev->next->next) { printf("事件發生時間:%d",ev->next->data.OccurTime); printf(" 事件型別:%d\n",ev->next->data.NType); ev=ev->next; } } //判斷事件表是否為空ok5 int ListEmpty(EventList ev) { if(ev->next->next==NULL) return 1; else return 0; } //構造空佇列函式ok6 void InitQueue(LinkQueue &Q) { Q.front=Q.rear=(QueuePtr)malloc(sizeof(QNode)); if(Q.front==NULL) { printf("構造空佇列失敗!\n"); exit(0); } Q.front->next=NULL; Q.rear->next=Q.front->next; Q.num=0; } //判斷佇列是否為空ok7 int QueueEmpty(LinkQueue Q) { if(Q.front==Q.rear) return 1; else return 0; } //在某一隊中隊尾插入元素ok8 void EnQueue(LinkQueue &Q,int n,int m) { QueuePtr p; p=(QueuePtr)malloc(sizeof(QNode)); if(!p) { printf("分配記憶體失敗!"); exit(0); } p->data.ArrivalTime=n; p->data.Duration=m; p->next=NULL; Q.rear->next=p; Q.rear=p; Q.num++; } //展示佇列函式ok9 void ShowQ(LinkQueue Q) { if(Q.front==Q.rear) { printf("列印佇列為空!\n"); return; } do { printf("[%d:",Q.front->next->data.ArrivalTime); printf("%d] ",Q.front->next->data.Duration); Q.front=Q.front->next; }while(Q.rear->next!=Q.front->next); printf("\n"); return; }