银行业务模拟

银行业务模拟是队列中非常经典的应用之一,各种版本的数据结构教材在队列这一章节援引这一应用。

本程序算法来源于《数据结构(C语言版)》(清华大学出版社 严蔚敏,吴伟民编著)第65页。

本程序在Ubuntu14.10平台上,利用g++编译通过。

#include <stdio.h>
#include <stdlib.h>
#include <malloc.h>
#include <time.h>
#define TRUE            1
#define FALSE           0
#define OK              1
#define ERROR           0
#define INFEASIBLE      -1
#define OVERLOW         -2
#define QNUMBER            5    //The bank has 4 windows
                            //You can set the number of bank windows here!!
                            //Note:the number of windows must lower than 4 !!
#define OPENTIME        8    //Bank opens at 8:00
#define CLOSETIME       18  //Bank closes at 18:00
#define Q1_CUSTNUM        10000    //The first numberical order for first customer in queue1
#define Q2_CUSTNUM        20000    //The first numberical order for first customer in queue2
#define Q3_CUSTNUM        30000    //The first numberical order for first customer in queue3
#define Q4_CUSTNUM        40000    //The first numberical order for first customer in queue4
#define INTERTIME_LOWER 1        //You can set the range of intertime and durtime here!!
#define INTERTIME_UPPER    10
#define DURTIME_LOWER    5
#define DURTIME_UPPER    20
/*-------------------------------------------------------
          definition of the storage structure
-------------------------------------------------------*/
typedef struct 
{
    int OccurTime;    //when event occur
    int NType;        //0 re customer arrives,1-4 re customer at 1-4 window depart
}Event,ElemType;
typedef struct EventNode
{
    Event event;
    struct EventNode *next;
}EventNode,*EventPtr;
typedef struct 
{
    EventPtr head;
    EventPtr rear;
    int length;
}EventList;


typedef struct 
{
    int ArrivalTime;    //the time customer arrives
    int Durtime;        //the time customer in service
    int CustNum;        //a code for every customer
}QElemType;
typedef struct QNode
{
    QElemType customer;
    struct  QNode *next;
}QNode,*QueuePtr;
typedef struct 
{
    QueuePtr head;
    QueuePtr rear;
    int length;
}LinkQueue;

EventList ev;
Event en;                    
LinkQueue q[QNUMBER];                //four customer queues
QElemType customer;            //custromer record
int TotalTime,CustomerNum,CloseTime;//record for the total time customers in bank, 
                                    //and how many customers in bank one day.
int q1,q2,q3,q4;            //customer counter for matching queue.
typedef int Status;
/*-----------------------------------------------------
        function of element OP of LinkQueue
-----------------------------------------------------*/
Status InitQueue(LinkQueue &Q){
    Q.head = Q.rear = (QueuePtr)malloc(sizeof(QNode));
    if(!Q.head)  exit(OVERLOW);
    Q.head->next = NULL;
    Q.length = 0;
    return OK;
}

Status EnQueue(LinkQueue &Q,QElemType e){
    QueuePtr p;
    p = (QueuePtr)malloc(sizeof(QNode));
    if(!p)  exit(OVERLOW);
    p->customer = e; p->next = NULL;
    Q.rear->next = p;
    Q.rear = p;
    Q.length++;
    return OK;
}

Status IsQEmpty(LinkQueue Q){
    if(Q.head == Q.rear) return TRUE;    //Q.length ==0;
    else return FALSE;
}

Status GetQHead(LinkQueue Q,QElemType &e){
    e = Q.head->next->customer;
    return OK;
}

Status DelQueue(LinkQueue &Q,QElemType &e){
    QueuePtr p;
    if(IsQEmpty(Q)) return ERROR;
    p = Q.head->next;
    e = p->customer;
    Q.head->next = p->next;
    if(Q.rear == p)        //Queue only has one elememt
        Q.rear = Q.head;
    free(p);
    Q.length--;
    return OK;
}

Status QueueLength(LinkQueue Q){
    return Q.length;
}

Status TypeQueue(LinkQueue Q,int qnum){
    QueuePtr p;
    p = Q.head->next;
    int atime;
    if(p == NULL){
        printf("Empty ListQueue:%d
",qnum);
        return OK;
    }
    printf("ListQueue:%-3dlength=%d
",qnum,Q.length);
    printf("ArrivalTime	Customer_Num	Durtime
");
    while(p!=NULL){
        atime = p->customer.ArrivalTime;
        printf("%d:%d%d		%d		%d
",OPENTIME+atime/60,atime%60/10,atime%10,
            p->customer.CustNum,p->customer.Durtime);
        p = p->next;
    }
    return OK;

}
/*-----------------------------------------------------
        function of element OP of EventList
-----------------------------------------------------*/
typedef int (*fp)(Event,Event);
int compare(Event a,Event b){
    if(a.OccurTime < b.OccurTime)  return -1;
    if(a.OccurTime == b.OccurTime)  return 0;
    if(a.OccurTime > b.OccurTime)  return 1;
}


Status InitList(EventList &E){
    E.head = E.rear = (EventPtr)malloc(sizeof(EventNode));
    if(!E.head) exit(OVERLOW);
    E.head->next = NULL;    //E.rear->next == NULL;
    E.length = 0;
    return OK;
}

Status ListEmpty(EventList E){
    if(E.length == 0) return TRUE;
    else return FALSE;
}

Status OrderInsert(EventList &E,Event e,fp cmp){
    //ascending order according the occurtime.
    Status TypeEventList(EventList E);
    EventPtr p,q,s;
    p = (EventPtr)malloc(sizeof(EventNode));
    if(!p)  exit(OVERLOW);
    p->event = e; p->next = NULL;
    if(E.head == E.rear){
        E.rear->next = p;    //E.head->next = p;(E.head = E.rear;)
        E.rear = p;
        E.length++;
        return OK;
    }
    if(E.head != E.rear){
        q = E.head->next;
        if(cmp(e,q->event) < 0){
            E.head->next = p;
            p->next = q;
            E.length++;
            return OK;
        }
        while(cmp(e,q->event) >= 0){
            s = q;
            q = q->next;
            if(q == NULL){
                E.rear = p;
                break;
            }
        }
        s->next = p;
        p->next = q;
        E.length++;
    }
    return OK;
}

Status GetEHead(EventList E,Event &e){
    e = E.head->next->event;
    return OK;
}

Status DelFirst(EventList &E,Event &e){
    Status TypeEventList(EventList E);
    GetEHead(E,e);
    EventPtr ep;
    ep = E.head->next;
    E.head->next = ep->next;
    if(E.rear == ep)
        E.rear = E.head;
    free(ep);
    E.length--;
    return OK;
}

Status TypeEventList(EventList E){
    EventPtr p;
    int otime;
    p = E.head->next;
    if(p == NULL){
        printf("Empty List
");
        return OK;
    }
    printf("EventList:length=%d
",E.length);
    printf("OccurTime	NType
");
    while(p!=NULL){
        otime = p->event.OccurTime;
        printf("%d:%d%d		%2d
",OPENTIME+otime/60,otime%60/10,
            otime%10,p->event.NType);
        p = p->next;
    }
    return OK;
}
/*-----------------------------------------------------
    function of element OP Bank Business simulation
-----------------------------------------------------*/
fp cmp = compare;

void Note_CustomerArrived(QElemType Q){
    printf("
%d:%d%d	customer %d arrived:
",OPENTIME+en.OccurTime/60,
        en.OccurTime%60/10,en.OccurTime%10,Q.CustNum);
    TypeEventList(ev);
    for(int i=1 ; i<QNUMBER ; i++)
        TypeQueue(q[i],i);
    printf("
");
}

void Note_CustomerDeparture(){
    printf("
%d:%d%d	queue%d customer %d departure:
",OPENTIME+en.OccurTime/60,
        en.OccurTime%60/10,en.OccurTime%10,en.NType,customer.CustNum);
    TypeEventList(ev);
    for(int i=1 ; i<QNUMBER ; i++)
        TypeQueue(q[i],i);
    printf("
");
}

int Minimum(LinkQueue q[]){
    int i,imin,min = 10000;
    for(i = 1 ; i < QNUMBER ; i++)
        if(q[i].length < min){
            min = q[i].length;
            imin = i;
        }
    return imin;
}

void Random(int &durtime,int &intertime){
    durtime = rand()%(DURTIME_UPPER - DURTIME_LOWER)
    + DURTIME_LOWER;    //durtime re service time [5,15(min)]
    intertime = rand()%(INTERTIME_UPPER - INTERTIME_LOWER)
    + INTERTIME_LOWER;//intertime re the time between two customer reaching
                            //[1,10(min)]
}

void OpenForDay(){
    //Initialization for Band Queue model.
    TotalTime =0; CustomerNum =0;
    InitList(ev);
    en.OccurTime = 0; en.NType = 0;
    OrderInsert(ev,en,cmp);
    for(int i = 1 ; i <= 4 ; i++) 
        InitQueue(q[i]);
    printf("%d:%d%d	Bank Open!!!
",8,0,0);
}

Status CustomerArrived(){
    //Handle the event that customers reaching.
    Event Etemp;
    QElemType Qtemp;
    int durtime,intertime;
    ++CustomerNum;
    Random(durtime,intertime);
    Qtemp.ArrivalTime = en.OccurTime;
    Qtemp.Durtime = durtime;
    Etemp.OccurTime = en.OccurTime + intertime;
    Etemp.NType = 0;
    if(Etemp.OccurTime < CloseTime)
        OrderInsert(ev,Etemp,cmp);
    else{
        printf("%d:%d%d	Bank Closed!!
",OPENTIME+CloseTime/60,CloseTime%60/10,CloseTime%10);
        return OK;
    }
    int i = Minimum(q);
    switch(i){            //Each customer was given a numerical order.
        case 1: Qtemp.CustNum = Q1_CUSTNUM + q1; q1++; break;
        case 2: Qtemp.CustNum = Q2_CUSTNUM + q2; q2++; break;
        case 3: Qtemp.CustNum = Q3_CUSTNUM + q3; q3++; break;
        case 4: Qtemp.CustNum = Q4_CUSTNUM + q4; q4++; break;
    }
    EnQueue(q[i],Qtemp);
    if(QueueLength(q[i]) == 1){
        Etemp.OccurTime = en.OccurTime + durtime;
        Etemp.NType = i;
        OrderInsert(ev,Etemp,cmp);
    }
    Note_CustomerArrived(Qtemp);
}

void CustomerDeparture(){
    //Handle the event that customers leaving.
    int i = en.NType; DelQueue(q[i],customer);
    Note_CustomerDeparture();
    TotalTime += en.OccurTime - customer.ArrivalTime;
    if(!IsQEmpty(q[i])){
        GetQHead(q[i],customer);
        Event temp;
        temp.OccurTime = en.OccurTime + customer.Durtime;
        temp.NType = i;
        OrderInsert(ev,temp,cmp);
    }
}

void Bank_Stimulation(){
    //This is a event drived program,simulating the average serving 
    //time on each customer.
    OpenForDay();
    q1=q2=q3=q4=0;
    while(!ListEmpty(ev)){
        DelFirst(ev,en);
        if(en.NType == 0)
            CustomerArrived();
        else
            CustomerDeparture();
    }//while
    printf("Today we sereved for %d customers.
",CustomerNum);
    printf("The average time is %.2f
",(float)TotalTime/CustomerNum);
}
/*-----------------------------------------------------
                    function of main
-----------------------------------------------------*/
int main(){
    CloseTime = (CLOSETIME - OPENTIME)*60;
    int winnum = QNUMBER - 1;
    printf("Today there is %d windows open.
",winnum);
    srand((unsigned)time(NULL));
    Bank_Stimulation();
}
原文地址:https://www.cnblogs.com/JarningGau/p/5360792.html