问题说明几点:
①顾客逗留时间的计算,应该是离开事件发生的时刻减去这个顾客入队的时间,因为顾客在中间还有等待排队尚未办理业务的时候
②设置离开事件有如下几种情况:
Ⅰ这个顾客是第一个入队的,那么他离开的时间就是入队的时间和办理业务的时间
Ⅱ这个顾客是在前一个顾客离开后去办理业务的,那么他的离开时间就是前一个顾客的离开时间(时刻)加上他办理业务的时间
③本次算法用了队列和链表,主函数有四个,其中两个是核心的,除此之外包括一些基本操作函数
④随机数的设定用rand函数,但是要取模,rand函数丢给durtime和interval(书上是intertime,我觉得interval好理解)的值往往很大,如果不取模那么银行估计只能来极少数顾客了
⑤写这个算法之前,应该思路清晰,建议画流程图,写伪码,取好变量名(算法变量很多)以及准备好数据结构,最后再写代码
代码如下,希望能帮到你:
#include "stdafx.h" #include<stdio.h> #include<iostream> #include<assert.h> #include<stdlib.h> #define Status int #define OK 1 #define OVERFLOW -1 #define ERROR 0 typedef struct Linklist { int occurtime; int EType; struct Linklist *next; }*EvenList,Even;//事件链表和单个事件 typedef struct Linkqueue { int timefordeal;//办理业务的时间 int enqueuetime;//入队时间 struct Linkqueue *next; }QElemtype;//队列元素 typedef struct Manageforqueue { QElemtype *front; QElemtype *rear; int qlength;//队列长度 }Mngfq;//队列的管理结构 int Totaltime = 0; int CustomerNum = 0;//全局 int Closetime = 200; const int SIZE = 4; void BankSimulation(); void BankOpen(EvenList *evlist, Mngfq Q[SIZE]); void DeForCuArrival(Even en, EvenList evlist, Mngfq Q[SIZE]); void DeForCuDepart(Even en, EvenList evlist, Mngfq Q[SIZE]); void BankClose(); Status InitLinklist(EvenList *evlist); Status OrderInsert(EvenList evlist, Even *en); Status Pop(EvenList evlist); Status GetLhead(EvenList evlist, Even *en); bool IsLEmpty(EvenList evlist); int MinQLength(Mngfq Q[SIZE]); int QLength(Mngfq *Q); Status Enqueue(Mngfq *Q, QElemtype *customer); Status Dequeue(Mngfq *Q); Status GetQhead(Mngfq *Q, QElemtype *customer); Status InitQ(Mngfq Q[SIZE]); bool IsQEmpty(Mngfq *Q); int main() { BankSimulation(); return 0; } void BankSimulation() {//银行模拟框架函数 Mngfq Q[SIZE]; EvenList evlist; BankOpen(&evlist, Q); while(!IsLEmpty(evlist)) { Even en; GetLhead(evlist, &en); Pop(evlist); if (en.EType == 0) DeForCuArrival(en,evlist, Q); else DeForCuDepart(en, evlist, Q); } BankClose(); } void BankOpen(EvenList *evlist, Mngfq Q[SIZE]) { InitQ(Q); InitLinklist(evlist); Even *en = (Even*)malloc(sizeof(Even)); assert(en != NULL); en->EType = 0; en->occurtime = 0; en->next = NULL; OrderInsert(*evlist, en); } void DeForCuArrival(Even en, EvenList evlist, Mngfq Q[SIZE]) {//处理用户到来事件 CustomerNum++; int durtime, interval; interval = rand() % 15; durtime = rand() % 31;//随机数设定 QElemtype *customer = (QElemtype*)malloc(sizeof(QElemtype)); assert(customer != NULL); customer->timefordeal = durtime;//办理业务的时间 customer->enqueuetime = en.occurtime;//来的时刻就是入队的时刻 customer->next = NULL;//防止野指针操作 int i; i = MinQLength(Q);//寻找最短队列 Enqueue(&Q[i - 1], customer); if (QLength(&Q[i - 1]) == 1)//该顾客是队列中的第一个 { Even *enforle = (Even*)malloc(sizeof(Even)); assert(enforle != NULL); enforle->EType = i; enforle->occurtime = customer->enqueuetime + customer->timefordeal; enforle->next = NULL; OrderInsert(evlist, enforle); }//将离开事件插入到事件表中 if (en.occurtime + interval < Closetime)//下一个顾客来的时候银行还未结业 { Even *enforcome = (Even*)malloc(sizeof(Even)); assert(enforcome != NULL); enforcome->occurtime = en.occurtime + interval; enforcome->EType = 0; enforcome->next = NULL; OrderInsert(evlist, enforcome); } } void DeForCuDepart(Even en, EvenList evlist, Mngfq Q[SIZE]) {//处理顾客离开事件 QElemtype customer_leave; customer_leave.next = NULL; GetQhead(&Q[en.EType - 1], &customer_leave);//获取该顾客信息 Totaltime += en.occurtime - customer_leave.enqueuetime;//计算逗留时间 Dequeue(&Q[en.EType - 1]);//顾客离开
if (!IsQEmpty(&Q[en.EType - 1])) { Even *enforleave = (Even*)malloc(sizeof(Even)); assert(enforleave != NULL); QElemtype customer; customer.next = NULL; GetQhead(&Q[en.EType - 1], &customer); enforleave->EType = en.EType; enforleave->occurtime = en.occurtime + customer.timefordeal; enforleave->next = NULL; OrderInsert(evlist, enforleave); }//准备下一个顾客的离开事件 } void BankClose() {//输出一天中银行流量和顾客平均逗留时间 using namespace std;
cout << "The total of customer is : " << CustomerNum << endl; cout << "The average time of customers in bank : " << double(Totaltime) / CustomerNum << endl; } bool IsLEmpty(EvenList evlist) {//判空事件表 return evlist->next == NULL; } Status InitQ(Mngfq Q[SIZE]) {//初始化四个队列为空队列 for (int i = 0; i < 4; i++) { Q[i].front = Q[i].rear = (QElemtype*)malloc(sizeof(QElemtype)); if (Q[i].front == NULL) return OVERFLOW; Q[i].front->next = NULL; Q[i].qlength = 0; } return OK; } Status InitLinklist(EvenList *evlist) {//初始化链表为空链表 *evlist = (Even*)malloc(sizeof(Even)); if (*evlist == NULL) return OVERFLOW; (*evlist)->next = NULL; return OK; } Status OrderInsert(EvenList evlist, Even *en) {//将事件en按事件发生先手顺序插入到事件表evlist中 Even *p = evlist; while (p->next != NULL && p->next->occurtime < en->occurtime) p = p->next; en->next = p->next; p->next = en; return OK; } int MinQLength(Mngfq Q[SIZE]) {//返回四个队列中最短队列的序号 int i = Q[0].qlength; for (int j = 1; j < 4; j++) if (Q[i].qlength > Q[j].qlength) i = j; return i+1;//返回最短队列序号 } Status Enqueue(Mngfq *Q, QElemtype *customer) {//使顾客入队列 Q->rear->next = customer; Q->rear = customer; Q->qlength++;//队列长度增1 return OK; } int QLength(Mngfq *Q) {//返回队列Q的长度 return Q->qlength; } Status GetQhead(Mngfq *Q, QElemtype *customer) {//使customer存贮Q队列第一个顾客的信息 customer->enqueuetime = Q->front->next->enqueuetime; customer->timefordeal = Q->front->next->timefordeal; return OK; } Status Dequeue(Mngfq *Q) {//使Q队列的第一个顾客出队 if (IsQEmpty(Q)) return ERROR;//空队列 QElemtype *q; q = Q->front->next; Q->front->next = q->next; free(q); if (Q->front->next == NULL) Q->rear = Q->front; Q->qlength--; return OK; } bool IsQEmpty(Mngfq *Q) {//判空队列 return Q->qlength == 0; } Status Pop(EvenList evlist) {//删除链表中的第一个事件 if (IsLEmpty(evlist)) return ERROR; Even *q; q = evlist->next; evlist->next = q->next; free(q); return OK; } Status GetLhead(EvenList evlist, Even *en) {//获取事件表中的第一个事件,用en返回这个事件 en->EType = evlist->next->EType; en->occurtime = evlist->next->occurtime; en->next = NULL; return OK; }